19226 lines
No EOL
1,019 KiB
JavaScript
19226 lines
No EOL
1,019 KiB
JavaScript
/// <reference path="../declarations/imports_shared.d.ts"/>
|
|
var ppt;
|
|
(function (ppt) {
|
|
let key_listener = [];
|
|
function listener_key(type, event) {
|
|
const key_event = {
|
|
type: type,
|
|
key: event.key,
|
|
key_code: event.code,
|
|
key_ctrl: event.ctrlKey,
|
|
key_shift: event.shiftKey,
|
|
key_alt: event.altKey,
|
|
key_windows: event.metaKey,
|
|
canceled: event.defaultPrevented
|
|
};
|
|
//console.debug("Trigger key event %o", key_event);
|
|
for (const listener of key_listener)
|
|
listener(key_event);
|
|
if (key_event.canceled)
|
|
event.preventDefault();
|
|
}
|
|
const proxy_key_press = event => listener_key(ppt.EventType.KEY_PRESS, event);
|
|
const proxy_key_release = event => listener_key(ppt.EventType.KEY_RELEASE, event);
|
|
const proxy_key_typed = event => listener_key(ppt.EventType.KEY_TYPED, event);
|
|
function initialize() {
|
|
document.addEventListener('keypress', proxy_key_typed);
|
|
document.addEventListener('keydown', proxy_key_press);
|
|
document.addEventListener('keyup', proxy_key_release);
|
|
register_key_listener(listener_hook);
|
|
return Promise.resolve();
|
|
}
|
|
ppt.initialize = initialize;
|
|
function finalize() {
|
|
document.removeEventListener("keypress", proxy_key_typed);
|
|
document.removeEventListener("keydown", proxy_key_press);
|
|
document.removeEventListener("keyup", proxy_key_release);
|
|
unregister_key_listener(listener_hook);
|
|
}
|
|
ppt.finalize = finalize;
|
|
function register_key_listener(listener) {
|
|
key_listener.push(listener);
|
|
}
|
|
ppt.register_key_listener = register_key_listener;
|
|
function unregister_key_listener(listener) {
|
|
key_listener.remove(listener);
|
|
}
|
|
ppt.unregister_key_listener = unregister_key_listener;
|
|
let key_hooks = [];
|
|
let current_state = {
|
|
special: []
|
|
};
|
|
let key_hooks_active = [];
|
|
function listener_hook(event) {
|
|
if (event.type == ppt.EventType.KEY_TYPED)
|
|
return;
|
|
let old_hooks = [...key_hooks_active];
|
|
let new_hooks = [];
|
|
current_state.special[ppt.SpecialKey.ALT] = event.key_alt;
|
|
current_state.special[ppt.SpecialKey.CTRL] = event.key_ctrl;
|
|
current_state.special[ppt.SpecialKey.SHIFT] = event.key_shift;
|
|
current_state.special[ppt.SpecialKey.WINDOWS] = event.key_windows;
|
|
current_state.code = undefined;
|
|
current_state.event = undefined;
|
|
if (event.type == ppt.EventType.KEY_PRESS) {
|
|
current_state.event = event;
|
|
current_state.code = event.key_code;
|
|
for (const hook of key_hooks) {
|
|
if (hook.key_code != event.key_code)
|
|
continue;
|
|
if (hook.key_alt != event.key_alt)
|
|
continue;
|
|
if (hook.key_ctrl != event.key_ctrl)
|
|
continue;
|
|
if (hook.key_shift != event.key_shift)
|
|
continue;
|
|
if (hook.key_windows != event.key_windows)
|
|
continue;
|
|
new_hooks.push(hook);
|
|
if (!old_hooks.remove(hook) && hook.callback_press) {
|
|
hook.callback_press();
|
|
console.debug("Trigger key press for %o!", hook);
|
|
}
|
|
}
|
|
}
|
|
//We have a new situation
|
|
for (const hook of old_hooks)
|
|
if (hook.callback_release) {
|
|
hook.callback_release();
|
|
console.debug("Trigger key release for %o!", hook);
|
|
}
|
|
key_hooks_active = new_hooks;
|
|
}
|
|
function register_key_hook(hook) {
|
|
key_hooks.push(hook);
|
|
}
|
|
ppt.register_key_hook = register_key_hook;
|
|
function unregister_key_hook(hook) {
|
|
key_hooks.remove(hook);
|
|
}
|
|
ppt.unregister_key_hook = unregister_key_hook;
|
|
function key_pressed(code) {
|
|
if (typeof (code) === 'string')
|
|
return current_state.code == code;
|
|
return current_state.special[code];
|
|
}
|
|
ppt.key_pressed = key_pressed;
|
|
})(ppt || (ppt = {}));
|
|
var audio;
|
|
(function (audio) {
|
|
var player;
|
|
(function (player) {
|
|
let _globalContext;
|
|
let _globalContextPromise;
|
|
let _initialized_listener = [];
|
|
function initialize() {
|
|
context();
|
|
return true;
|
|
}
|
|
player.initialize = initialize;
|
|
function initialized() {
|
|
return !!_globalContext && _globalContext.state === 'running';
|
|
}
|
|
player.initialized = initialized;
|
|
function fire_initialized() {
|
|
console.log("Fire initialized: %o", _initialized_listener);
|
|
while (_initialized_listener.length > 0)
|
|
_initialized_listener.pop_front()();
|
|
}
|
|
function context() {
|
|
if (_globalContext && _globalContext.state != "suspended")
|
|
return _globalContext;
|
|
if (!_globalContext)
|
|
_globalContext = new (window.webkitAudioContext || window.AudioContext)();
|
|
if (_globalContext.state == "suspended") {
|
|
if (!_globalContextPromise) {
|
|
(_globalContextPromise = _globalContext.resume()).then(() => {
|
|
fire_initialized();
|
|
}).catch(error => {
|
|
displayCriticalError("Failed to initialize global audio context! (" + error + ")");
|
|
});
|
|
}
|
|
_globalContext.resume(); //We already have our listener
|
|
return undefined;
|
|
}
|
|
if (_globalContext.state == "running") {
|
|
fire_initialized();
|
|
return _globalContext;
|
|
}
|
|
return undefined;
|
|
}
|
|
player.context = context;
|
|
function destination() {
|
|
const ctx = context();
|
|
if (!ctx)
|
|
throw tr("Audio player isn't initialized yet!");
|
|
return ctx.destination;
|
|
}
|
|
player.destination = destination;
|
|
function on_ready(cb) {
|
|
if (initialized())
|
|
cb();
|
|
else
|
|
_initialized_listener.push(cb);
|
|
}
|
|
player.on_ready = on_ready;
|
|
player.WEB_DEVICE = { device_id: "", name: "default playback" };
|
|
function available_devices() {
|
|
return Promise.resolve([player.WEB_DEVICE]);
|
|
}
|
|
player.available_devices = available_devices;
|
|
function set_device(device_id) {
|
|
return Promise.resolve();
|
|
}
|
|
player.set_device = set_device;
|
|
function current_device() {
|
|
return player.WEB_DEVICE;
|
|
}
|
|
player.current_device = current_device;
|
|
function initializeFromGesture() {
|
|
context();
|
|
}
|
|
player.initializeFromGesture = initializeFromGesture;
|
|
})(player = audio.player || (audio.player = {}));
|
|
})(audio || (audio = {}));
|
|
/// <reference path="../../declarations/imports_shared.d.ts"/>
|
|
var audio;
|
|
(function (audio) {
|
|
var codec;
|
|
(function (codec) {
|
|
function new_instance(type) {
|
|
return new CodecWrapperWorker(type);
|
|
}
|
|
codec.new_instance = new_instance;
|
|
function supported(type) {
|
|
return type == CodecType.OPUS_MUSIC || type == CodecType.OPUS_VOICE;
|
|
}
|
|
codec.supported = supported;
|
|
})(codec = audio.codec || (audio.codec = {}));
|
|
})(audio || (audio = {}));
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
function fulfilled(value) { try {
|
|
step(generator.next(value));
|
|
}
|
|
catch (e) {
|
|
reject(e);
|
|
} }
|
|
function rejected(value) { try {
|
|
step(generator["throw"](value));
|
|
}
|
|
catch (e) {
|
|
reject(e);
|
|
} }
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
});
|
|
};
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["d73415969dab3133f6dd0be5e80d3da9f44d28315f6483e40a8a245397d1600a"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["d73415969dab3133f6dd0be5e80d3da9f44d28315f6483e40a8a245397d1600a"] = "d73415969dab3133f6dd0be5e80d3da9f44d28315f6483e40a8a245397d1600a";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var LogCategory;
|
|
(function (LogCategory) {
|
|
LogCategory[LogCategory["CHANNEL"] = 0] = "CHANNEL";
|
|
LogCategory[LogCategory["CHANNEL_PROPERTIES"] = 1] = "CHANNEL_PROPERTIES";
|
|
LogCategory[LogCategory["CLIENT"] = 2] = "CLIENT";
|
|
LogCategory[LogCategory["SERVER"] = 3] = "SERVER";
|
|
LogCategory[LogCategory["PERMISSIONS"] = 4] = "PERMISSIONS";
|
|
LogCategory[LogCategory["GENERAL"] = 5] = "GENERAL";
|
|
LogCategory[LogCategory["NETWORKING"] = 6] = "NETWORKING";
|
|
LogCategory[LogCategory["VOICE"] = 7] = "VOICE";
|
|
LogCategory[LogCategory["I18N"] = 8] = "I18N";
|
|
})(LogCategory || (LogCategory = {}));
|
|
var log;
|
|
(function (log_1) {
|
|
let LogType;
|
|
(function (LogType) {
|
|
LogType[LogType["TRACE"] = 0] = "TRACE";
|
|
LogType[LogType["DEBUG"] = 1] = "DEBUG";
|
|
LogType[LogType["INFO"] = 2] = "INFO";
|
|
LogType[LogType["WARNING"] = 3] = "WARNING";
|
|
LogType[LogType["ERROR"] = 4] = "ERROR";
|
|
})(LogType = log_1.LogType || (log_1.LogType = {}));
|
|
let category_mapping = new Map([
|
|
[LogCategory.CHANNEL, "Channel "],
|
|
[LogCategory.CLIENT, "Channel "],
|
|
[LogCategory.CHANNEL_PROPERTIES, "Client "],
|
|
[LogCategory.SERVER, "Server "],
|
|
[LogCategory.PERMISSIONS, "Permission "],
|
|
[LogCategory.GENERAL, "General "],
|
|
[LogCategory.NETWORKING, "Network "],
|
|
[LogCategory.VOICE, "Voice "],
|
|
[LogCategory.I18N, "I18N "]
|
|
]);
|
|
log_1.enabled_mapping = new Map([
|
|
[LogCategory.CHANNEL, true],
|
|
[LogCategory.CHANNEL_PROPERTIES, false],
|
|
[LogCategory.CLIENT, true],
|
|
[LogCategory.SERVER, true],
|
|
[LogCategory.PERMISSIONS, true],
|
|
[LogCategory.GENERAL, true],
|
|
[LogCategory.NETWORKING, true],
|
|
[LogCategory.VOICE, true],
|
|
[LogCategory.I18N, false]
|
|
]);
|
|
loader.register_task(loader.Stage.LOADED, {
|
|
name: "log enabled initialisation",
|
|
function: () => __awaiter(this, void 0, void 0, function* () { return initialize(); }),
|
|
priority: 10
|
|
});
|
|
//Example: <url>?log.i18n.enabled=0
|
|
function initialize() {
|
|
for (const category of Object.keys(LogCategory).map(e => parseInt(e))) {
|
|
if (isNaN(category))
|
|
continue;
|
|
const category_name = LogCategory[category];
|
|
log_1.enabled_mapping[category] = settings.static_global("log." + category_name.toLowerCase() + ".enabled", log_1.enabled_mapping.get(category));
|
|
}
|
|
}
|
|
log_1.initialize = initialize;
|
|
function logDirect(type, message, ...optionalParams) {
|
|
switch (type) {
|
|
case LogType.TRACE:
|
|
case LogType.DEBUG:
|
|
console.debug(message, ...optionalParams);
|
|
break;
|
|
case LogType.INFO:
|
|
console.log(message, ...optionalParams);
|
|
break;
|
|
case LogType.WARNING:
|
|
console.warn(message, ...optionalParams);
|
|
break;
|
|
case LogType.ERROR:
|
|
console.error(message, ...optionalParams);
|
|
break;
|
|
}
|
|
//console.log("This is %cMy stylish message", "color: yellow; font-style: italic; background-color: blue;padding: 2px");
|
|
}
|
|
function log(type, category, message, ...optionalParams) {
|
|
if (!log_1.enabled_mapping[category])
|
|
return;
|
|
optionalParams.unshift(category_mapping.get(category));
|
|
message = "[%s] " + message;
|
|
logDirect(type, message, ...optionalParams);
|
|
}
|
|
log_1.log = log;
|
|
function trace(category, message, ...optionalParams) {
|
|
log(LogType.TRACE, category, message, ...optionalParams);
|
|
}
|
|
log_1.trace = trace;
|
|
function debug(category, message, ...optionalParams) {
|
|
log(LogType.DEBUG, category, message, ...optionalParams);
|
|
}
|
|
log_1.debug = debug;
|
|
function info(category, message, ...optionalParams) {
|
|
log(LogType.INFO, category, message, ...optionalParams);
|
|
}
|
|
log_1.info = info;
|
|
function warn(category, message, ...optionalParams) {
|
|
log(LogType.WARNING, category, message, ...optionalParams);
|
|
}
|
|
log_1.warn = warn;
|
|
function error(category, message, ...optionalParams) {
|
|
log(LogType.ERROR, category, message, ...optionalParams);
|
|
}
|
|
log_1.error = error;
|
|
function group(level, category, name, ...optionalParams) {
|
|
name = "[%s] " + name;
|
|
optionalParams.unshift(category_mapping.get(category));
|
|
return new Group(level, category, name, optionalParams);
|
|
}
|
|
log_1.group = group;
|
|
class Group {
|
|
constructor(level, category, name, optionalParams, owner = undefined) {
|
|
this.owner = undefined;
|
|
this._collapsed = true;
|
|
this.initialized = false;
|
|
this.level = level;
|
|
this.category = category;
|
|
this.name = name;
|
|
this.optionalParams = optionalParams;
|
|
this.enabled = log_1.enabled_mapping[category];
|
|
}
|
|
group(level, name, ...optionalParams) {
|
|
return new Group(level, this.category, name, optionalParams, this);
|
|
}
|
|
collapsed(flag = true) {
|
|
this._collapsed = flag;
|
|
return this;
|
|
}
|
|
log(message, ...optionalParams) {
|
|
if (!this.enabled)
|
|
return this;
|
|
if (!this.initialized) {
|
|
if (this._collapsed && console.groupCollapsed)
|
|
console.groupCollapsed(this.name, ...this.optionalParams);
|
|
else
|
|
console.group(this.name, ...this.optionalParams);
|
|
this.initialized = true;
|
|
}
|
|
logDirect(this.level, message, ...optionalParams);
|
|
return this;
|
|
}
|
|
end() {
|
|
if (this.initialized)
|
|
console.groupEnd();
|
|
}
|
|
}
|
|
log_1.Group = Group;
|
|
})(log || (log = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["aa4820e2170bccb4c9023974e9ced073b8bc94597aa84bfaf8d5885df8b2ea72"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["aa4820e2170bccb4c9023974e9ced073b8bc94597aa84bfaf8d5885df8b2ea72"] = "aa4820e2170bccb4c9023974e9ced073b8bc94597aa84bfaf8d5885df8b2ea72";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "VS9hwtrt", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/AudioController.ts (17,26)" }, { name: "sQGbUuVV", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/AudioController.ts (19,25)" }, { name: "nYG7F2p3", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/AudioController.ts (108,26)" }, { name: "_Yf07RsH", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/AudioController.ts (112,26)" }, { name: "aWefC7hp", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/AudioController.ts (116,26)" }, { name: "AB2K3e04", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/AudioController.ts (121,25)" }, { name: "gFg5nk4c", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/AudioController.ts (137,33)" }, { name: "TyzWyl9j", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/AudioController.ts (141,37)" }, { name: "_W4xu8ar", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/AudioController.ts (156,29)" }, { name: "FMs8xfPn", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/AudioController.ts (199,34)" }, { name: "JNe36jh0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/AudioController.ts (214,34)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var PlayerState;
|
|
(function (PlayerState) {
|
|
PlayerState[PlayerState["PREBUFFERING"] = 0] = "PREBUFFERING";
|
|
PlayerState[PlayerState["PLAYING"] = 1] = "PLAYING";
|
|
PlayerState[PlayerState["BUFFERING"] = 2] = "BUFFERING";
|
|
PlayerState[PlayerState["STOPPING"] = 3] = "STOPPING";
|
|
PlayerState[PlayerState["STOPPED"] = 4] = "STOPPED";
|
|
})(PlayerState || (PlayerState = {}));
|
|
class AudioController {
|
|
constructor() {
|
|
this.playerState = PlayerState.STOPPED;
|
|
this.audioCache = [];
|
|
this.playingAudioCache = [];
|
|
this._volume = 1;
|
|
this._codecCache = [];
|
|
this._timeIndex = 0;
|
|
this._latencyBufferLength = 3;
|
|
this.allowBuffering = true;
|
|
audio.player.on_ready(() => this.speakerContext = audio.player.context());
|
|
this.onSpeaking = function () { };
|
|
this.onSilence = function () { };
|
|
}
|
|
static initializeAudioController() {
|
|
if (!audio.player.initialize())
|
|
console.warn(_translations.VS9hwtrt || (_translations.VS9hwtrt = tr("Failed to initialize audio controller!")));
|
|
sound.initialize().then(() => {
|
|
console.log(_translations.sQGbUuVV || (_translations.sQGbUuVV = tr("Sounds initialitzed")));
|
|
});
|
|
//this._globalReplayScheduler = setInterval(() => { AudioController.invokeNextReplay(); }, 20); //Fix me
|
|
}
|
|
initialize() {
|
|
AudioController._audioInstances.push(this);
|
|
}
|
|
close() {
|
|
AudioController._audioInstances.remove(this);
|
|
}
|
|
playBuffer(buffer) {
|
|
if (!buffer) {
|
|
console.warn(_translations.nYG7F2p3 || (_translations.nYG7F2p3 = tr("[AudioController] Got empty or undefined buffer! Dropping it")));
|
|
return;
|
|
}
|
|
if (!this.speakerContext) {
|
|
console.warn(_translations._Yf07RsH || (_translations._Yf07RsH = tr("[AudioController] Failed to replay audio. Global audio context not initialized yet!")));
|
|
return;
|
|
}
|
|
if (buffer.sampleRate != this.speakerContext.sampleRate)
|
|
console.warn(_translations.aWefC7hp || (_translations.aWefC7hp = tr("[AudioController] Source sample rate isn't equal to playback sample rate! (%o | %o)")), buffer.sampleRate, this.speakerContext.sampleRate);
|
|
this.applyVolume(buffer);
|
|
this.audioCache.push(buffer);
|
|
if (this.playerState == PlayerState.STOPPED || this.playerState == PlayerState.STOPPING) {
|
|
console.log(_translations.AB2K3e04 || (_translations.AB2K3e04 = tr("[Audio] Starting new playback")));
|
|
this.playerState = PlayerState.PREBUFFERING;
|
|
//New audio
|
|
}
|
|
switch (this.playerState) {
|
|
case PlayerState.PREBUFFERING:
|
|
case PlayerState.BUFFERING:
|
|
this.reset_buffer_timeout(true); //Reset timeout, we got a new buffer
|
|
if (this.audioCache.length <= this._latencyBufferLength) {
|
|
if (this.playerState == PlayerState.BUFFERING) {
|
|
if (this.allowBuffering)
|
|
break;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
if (this.playerState == PlayerState.PREBUFFERING) {
|
|
console.log(_translations.gFg5nk4c || (_translations.gFg5nk4c = tr("[Audio] Prebuffering succeeded (Replaying now)")));
|
|
this.onSpeaking();
|
|
}
|
|
else {
|
|
if (this.allowBuffering)
|
|
console.log(_translations.TyzWyl9j || (_translations.TyzWyl9j = tr("[Audio] Buffering succeeded (Replaying now)")));
|
|
}
|
|
this.playerState = PlayerState.PLAYING;
|
|
case PlayerState.PLAYING:
|
|
this.playQueue();
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
playQueue() {
|
|
let buffer;
|
|
while ((buffer = this.audioCache.pop_front())) {
|
|
if (this.playingAudioCache.length >= this._latencyBufferLength * 1.5 + 3) {
|
|
console.log(_translations._W4xu8ar || (_translations._W4xu8ar = tr("Dropping buffer because playing queue grows to much")));
|
|
continue; /* drop the data (we're behind) */
|
|
}
|
|
if (this._timeIndex < this.speakerContext.currentTime)
|
|
this._timeIndex = this.speakerContext.currentTime;
|
|
let player = this.speakerContext.createBufferSource();
|
|
player.buffer = buffer;
|
|
player.onended = () => this.removeNode(player);
|
|
this.playingAudioCache.push(player);
|
|
player.connect(audio.player.destination());
|
|
player.start(this._timeIndex);
|
|
this._timeIndex += buffer.duration;
|
|
}
|
|
}
|
|
removeNode(node) {
|
|
this.playingAudioCache.remove(node);
|
|
this.testBufferQueue();
|
|
}
|
|
stopAudio(now = false) {
|
|
this.playerState = PlayerState.STOPPING;
|
|
if (now) {
|
|
this.playerState = PlayerState.STOPPED;
|
|
this.audioCache = [];
|
|
for (let entry of this.playingAudioCache)
|
|
entry.stop(0);
|
|
this.playingAudioCache = [];
|
|
}
|
|
this.testBufferQueue();
|
|
this.playQueue(); //Flush queue
|
|
}
|
|
testBufferQueue() {
|
|
if (this.audioCache.length == 0 && this.playingAudioCache.length == 0) {
|
|
if (this.playerState != PlayerState.STOPPING && this.playerState != PlayerState.STOPPED) {
|
|
if (this.playerState == PlayerState.BUFFERING)
|
|
return; //We're already buffering
|
|
this.playerState = PlayerState.BUFFERING;
|
|
if (!this.allowBuffering)
|
|
console.warn(_translations.FMs8xfPn || (_translations.FMs8xfPn = tr("[Audio] Detected a buffer underflow!")));
|
|
this.reset_buffer_timeout(true);
|
|
}
|
|
else {
|
|
this.playerState = PlayerState.STOPPED;
|
|
this.onSilence();
|
|
}
|
|
}
|
|
}
|
|
reset_buffer_timeout(restart) {
|
|
if (this._buffer_timeout)
|
|
clearTimeout(this._buffer_timeout);
|
|
if (restart)
|
|
this._buffer_timeout = setTimeout(() => {
|
|
if (this.playerState == PlayerState.PREBUFFERING || this.playerState == PlayerState.BUFFERING) {
|
|
console.warn(_translations.JNe36jh0 || (_translations.JNe36jh0 = tr("[Audio] Buffering exceeded timeout. Flushing and stopping replay")));
|
|
this.stopAudio();
|
|
}
|
|
this._buffer_timeout = undefined;
|
|
}, 1000);
|
|
}
|
|
get volume() { return this._volume; }
|
|
set volume(val) {
|
|
if (this._volume == val)
|
|
return;
|
|
this._volume = val;
|
|
for (let buffer of this.audioCache)
|
|
this.applyVolume(buffer);
|
|
}
|
|
applyVolume(buffer) {
|
|
if (this._volume == 1)
|
|
return;
|
|
for (let channel = 0; channel < buffer.numberOfChannels; channel++) {
|
|
let data = buffer.getChannelData(channel);
|
|
for (let sample = 0; sample < data.length; sample++) {
|
|
let lane = data[sample];
|
|
lane *= this._volume;
|
|
data[sample] = lane;
|
|
}
|
|
}
|
|
}
|
|
codecCache(codec) {
|
|
while (this._codecCache.length <= codec)
|
|
this._codecCache.push(new CodecClientCache());
|
|
return this._codecCache[codec];
|
|
}
|
|
}
|
|
AudioController._audioInstances = [];
|
|
AudioController._timeIndex = 0;
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["73175f3c3c475118e7753855dc9a37dcbff17356792cb5f958da725f26fef61d"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["73175f3c3c475118e7753855dc9a37dcbff17356792cb5f958da725f26fef61d"] = "73175f3c3c475118e7753855dc9a37dcbff17356792cb5f958da725f26fef61d";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "xXDTVFqp", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/proto.ts (58,31)" }, { name: "VmE4po4t", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/proto.ts (62,31)" }, { name: "jM1uWylR", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/proto.ts (81,27)" }, { name: "X3Guusa0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/proto.ts (208,33)" }, { name: "WzItbAWP", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/proto.ts (210,32)" }, { name: "Yn6EHaG_", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/proto.ts (212,33)" }, { name: "_Pmw_Iot", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/proto.ts (214,35)" }, { name: "gULlVp9g", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/proto.ts (216,35)" }, { name: "lZCpWdXL", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/proto.ts (218,18)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
if (!JSON.map_to) {
|
|
JSON.map_to = function (object, json, variables, validator, variable_direction) {
|
|
if (!validator)
|
|
validator = (a, b) => true;
|
|
if (!variables) {
|
|
variables = [];
|
|
if (!variable_direction || variable_direction == 0) {
|
|
for (let field in json)
|
|
variables.push(field);
|
|
}
|
|
else if (variable_direction == 1) {
|
|
for (let field in object)
|
|
variables.push(field);
|
|
}
|
|
}
|
|
else if (!Array.isArray(variables)) {
|
|
variables = [variables];
|
|
}
|
|
for (let field of variables) {
|
|
if (!json[field]) {
|
|
console.trace(_translations.xXDTVFqp || (_translations.xXDTVFqp = tr("Json does not contains %s")), field);
|
|
continue;
|
|
}
|
|
if (!validator(field, json[field])) {
|
|
console.trace(_translations.VmE4po4t || (_translations.VmE4po4t = tr("Validator results in false for %s")), field);
|
|
continue;
|
|
}
|
|
JSON.map_field_to(object, json[field], field);
|
|
}
|
|
return object;
|
|
};
|
|
}
|
|
if (!JSON.map_field_to) {
|
|
JSON.map_field_to = function (object, value, field) {
|
|
let field_type = typeof (object[field]);
|
|
if (field_type == "string" || field_type == "object" || field_type == "undefined")
|
|
object[field] = value;
|
|
else if (field_type == "number")
|
|
object[field] = parseFloat(value);
|
|
else if (field_type == "boolean")
|
|
object[field] = value == "1" || value == "true";
|
|
else
|
|
console.warn(_translations.jM1uWylR || (_translations.jM1uWylR = tr("Invalid object type %s for entry %s")), field_type, field);
|
|
return object;
|
|
};
|
|
}
|
|
if (!Array.prototype.remove) {
|
|
Array.prototype.remove = function (elem) {
|
|
const index = this.indexOf(elem, 0);
|
|
if (index > -1) {
|
|
this.splice(index, 1);
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
}
|
|
if (!Array.prototype.pop_front) {
|
|
Array.prototype.pop_front = function () {
|
|
if (this.length == 0)
|
|
return undefined;
|
|
return this.splice(0, 1)[0];
|
|
};
|
|
}
|
|
if (!Array.prototype.last) {
|
|
Array.prototype.last = function () {
|
|
if (this.length == 0)
|
|
return undefined;
|
|
return this[this.length - 1];
|
|
};
|
|
}
|
|
if (typeof ($) !== "undefined") {
|
|
if (!$.spawn) {
|
|
$.spawn = function (tagName) {
|
|
return $(document.createElement(tagName));
|
|
};
|
|
}
|
|
if (!$.fn.renderTag) {
|
|
$.fn.renderTag = function (values) {
|
|
let result;
|
|
if (this.render) {
|
|
result = $(this.render(values));
|
|
}
|
|
else {
|
|
const template = window.jsrender.render[this.attr("id")];
|
|
/*
|
|
result = window.jsrender.templates("tmpl_permission_entry", $("#tmpl_permission_entry").html());
|
|
result = window.jsrender.templates("xxx", this.html());
|
|
*/
|
|
result = template(values);
|
|
result = $(result);
|
|
}
|
|
result.find("node").each((index, element) => {
|
|
$(element).replaceWith(values[$(element).attr("key")] || (values[0] || [])[$(element).attr("key")]);
|
|
});
|
|
return result;
|
|
};
|
|
}
|
|
if (!$.fn.hasScrollBar)
|
|
$.fn.hasScrollBar = function () {
|
|
if (this.length <= 0)
|
|
return false;
|
|
return this.get(0).scrollHeight > this.height();
|
|
};
|
|
if (!$.fn.visible_height)
|
|
$.fn.visible_height = function () {
|
|
const original_style = this.attr("style");
|
|
this.css({
|
|
position: 'absolute!important',
|
|
visibility: 'hidden!important',
|
|
display: 'block!important'
|
|
});
|
|
const result = this.height();
|
|
this.attr("style", original_style || "");
|
|
return result;
|
|
};
|
|
if (!$.fn.visible_width)
|
|
$.fn.visible_width = function () {
|
|
const original_style = this.attr("style");
|
|
this.css({
|
|
position: 'absolute!important',
|
|
visibility: 'hidden!important',
|
|
display: 'block!important'
|
|
});
|
|
const result = this.width();
|
|
this.attr("style", original_style || "");
|
|
return result;
|
|
};
|
|
}
|
|
if (!String.prototype.format) {
|
|
String.prototype.format = function () {
|
|
const args = arguments;
|
|
let array = args.length == 1 && $.isArray(args[0]);
|
|
return this.replace(/\{\{|\}\}|\{(\d+)\}/g, function (m, n) {
|
|
if (m == "{{") {
|
|
return "{";
|
|
}
|
|
if (m == "}}") {
|
|
return "}";
|
|
}
|
|
return array ? args[0][n] : args[n];
|
|
});
|
|
};
|
|
}
|
|
function concatenate(resultConstructor, ...arrays) {
|
|
let totalLength = 0;
|
|
for (const arr of arrays) {
|
|
totalLength += arr.length;
|
|
}
|
|
const result = new resultConstructor(totalLength);
|
|
let offset = 0;
|
|
for (const arr of arrays) {
|
|
result.set(arr, offset);
|
|
offset += arr.length;
|
|
}
|
|
return result;
|
|
}
|
|
function formatDate(secs) {
|
|
let years = Math.floor(secs / (60 * 60 * 24 * 365));
|
|
let days = Math.floor(secs / (60 * 60 * 24)) % 365;
|
|
let hours = Math.floor(secs / (60 * 60)) % 24;
|
|
let minutes = Math.floor(secs / 60) % 60;
|
|
let seconds = Math.floor(secs % 60);
|
|
let result = "";
|
|
if (years > 0)
|
|
result += years + " " + (_translations.X3Guusa0 || (_translations.X3Guusa0 = tr("years"))) + " ";
|
|
if (years > 0 || days > 0)
|
|
result += days + " " + (_translations.WzItbAWP || (_translations.WzItbAWP = tr("days"))) + " ";
|
|
if (years > 0 || days > 0 || hours > 0)
|
|
result += hours + " " + (_translations.Yn6EHaG_ || (_translations.Yn6EHaG_ = tr("hours"))) + " ";
|
|
if (years > 0 || days > 0 || hours > 0 || minutes > 0)
|
|
result += minutes + " " + (_translations._Pmw_Iot || (_translations._Pmw_Iot = tr("minutes"))) + " ";
|
|
if (years > 0 || days > 0 || hours > 0 || minutes > 0 || seconds > 0)
|
|
result += seconds + " " + (_translations.gULlVp9g || (_translations.gULlVp9g = tr("seconds"))) + " ";
|
|
else
|
|
result = (_translations.lZCpWdXL || (_translations.lZCpWdXL = tr("now"))) + " ";
|
|
return result.substr(0, result.length - 1);
|
|
}
|
|
function calculate_width(text) {
|
|
let element = $.spawn("div");
|
|
element.text(text)
|
|
.css("display", "none")
|
|
.css("margin", 0);
|
|
$("body").append(element);
|
|
let size = element.width();
|
|
element.detach();
|
|
return size;
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["8bea2622f41d7017b839dd7842376dc7712df60e8b96482e914df09124e9c503"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["8bea2622f41d7017b839dd7842376dc7712df60e8b96482e914df09124e9c503"] = "8bea2622f41d7017b839dd7842376dc7712df60e8b96482e914df09124e9c503";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var CodecType;
|
|
(function (CodecType) {
|
|
CodecType[CodecType["OPUS_VOICE"] = 0] = "OPUS_VOICE";
|
|
CodecType[CodecType["OPUS_MUSIC"] = 1] = "OPUS_MUSIC";
|
|
CodecType[CodecType["SPEEX_NARROWBAND"] = 2] = "SPEEX_NARROWBAND";
|
|
CodecType[CodecType["SPEEX_WIDEBAND"] = 3] = "SPEEX_WIDEBAND";
|
|
CodecType[CodecType["SPEEX_ULTRA_WIDEBAND"] = 4] = "SPEEX_ULTRA_WIDEBAND";
|
|
CodecType[CodecType["CELT_MONO"] = 5] = "CELT_MONO";
|
|
})(CodecType || (CodecType = {}));
|
|
class BufferChunk {
|
|
constructor(buffer) {
|
|
this.buffer = buffer;
|
|
this.index = 0;
|
|
}
|
|
copyRangeTo(target, maxLength, offset) {
|
|
let copy = Math.min(this.buffer.length - this.index, maxLength);
|
|
//TODO may warning if channel counts are not queal?
|
|
for (let channel = 0; channel < Math.min(target.numberOfChannels, this.buffer.numberOfChannels); channel++) {
|
|
target.getChannelData(channel).set(this.buffer.getChannelData(channel).subarray(this.index, this.index + copy), offset);
|
|
}
|
|
return copy;
|
|
}
|
|
}
|
|
class CodecClientCache {
|
|
constructor() {
|
|
this._chunks = [];
|
|
}
|
|
bufferedSamples(max = 0) {
|
|
let value = 0;
|
|
for (let i = 0; i < this._chunks.length && value < max; i++)
|
|
value += this._chunks[i].buffer.length - this._chunks[i].index;
|
|
return value;
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["5df58f3b6832f7418213f7d08bb001f9be22c31798af6163595e1be5d1baa0b9"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["5df58f3b6832f7418213f7d08bb001f9be22c31798af6163595e1be5d1baa0b9"] = "5df58f3b6832f7418213f7d08bb001f9be22c31798af6163595e1be5d1baa0b9";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var ElementType;
|
|
(function (ElementType) {
|
|
ElementType[ElementType["HEADER"] = 0] = "HEADER";
|
|
ElementType[ElementType["BODY"] = 1] = "BODY";
|
|
ElementType[ElementType["FOOTER"] = 2] = "FOOTER";
|
|
})(ElementType || (ElementType = {}));
|
|
const ModalFunctions = {
|
|
divify: function (val) {
|
|
if (val.length > 1)
|
|
return $.spawn("div").append(val);
|
|
return val;
|
|
},
|
|
jqueriefy: function (val, type) {
|
|
if ($.isFunction(val))
|
|
val = val();
|
|
if ($.isArray(val)) {
|
|
let result = $.spawn("div");
|
|
for (let element of val)
|
|
this.jqueriefy(element, type).appendTo(result);
|
|
return result;
|
|
}
|
|
switch (typeof val) {
|
|
case "string":
|
|
if (type == ElementType.HEADER)
|
|
return $.spawn("h5").addClass("modal-title").text(val);
|
|
return $("<div>" + val + "</div>");
|
|
case "object": return val;
|
|
case "undefined":
|
|
return undefined;
|
|
default:
|
|
console.error(("Invalid type %o"), typeof val);
|
|
return $();
|
|
}
|
|
},
|
|
warpProperties(data) {
|
|
if (data instanceof ModalProperties)
|
|
return data;
|
|
else {
|
|
const props = new ModalProperties();
|
|
for (const key of Object.keys(data))
|
|
props[key] = data[key];
|
|
return props;
|
|
}
|
|
}
|
|
};
|
|
class ModalProperties {
|
|
constructor() {
|
|
this.header = () => "HEADER";
|
|
this.body = () => "BODY";
|
|
this.footer = () => "FOOTER";
|
|
this.closeListener = () => { };
|
|
this.width = "60%";
|
|
this.height = "auto";
|
|
this.closeable = true;
|
|
this.template_properties = {};
|
|
this.trigger_tab = true;
|
|
this.full_size = false;
|
|
}
|
|
registerCloseListener(listener) {
|
|
if (this.closeListener) {
|
|
if ($.isArray(this.closeListener))
|
|
this.closeListener.push(listener);
|
|
else
|
|
this.closeListener = [this.closeListener, listener];
|
|
}
|
|
else
|
|
this.closeListener = listener;
|
|
return this;
|
|
}
|
|
triggerClose() {
|
|
if ($.isArray(this.closeListener))
|
|
for (let listener of this.closeListener)
|
|
listener();
|
|
else
|
|
this.closeListener();
|
|
}
|
|
}
|
|
class Modal {
|
|
constructor(props) {
|
|
this.close_listener = [];
|
|
this.properties = props;
|
|
this.shown = false;
|
|
}
|
|
get htmlTag() {
|
|
if (!this._htmlTag)
|
|
this._create();
|
|
return this._htmlTag;
|
|
}
|
|
_create() {
|
|
const header = ModalFunctions.jqueriefy(this.properties.header, ElementType.HEADER);
|
|
const body = ModalFunctions.jqueriefy(this.properties.body, ElementType.BODY);
|
|
const footer = ModalFunctions.jqueriefy(this.properties.footer, ElementType.FOOTER);
|
|
//FIXME: cache template
|
|
const template = $(this.properties.template || "#tmpl_modal");
|
|
const properties = {
|
|
modal_header: header,
|
|
modal_body: body,
|
|
modal_footer: footer,
|
|
closeable: this.properties.closeable,
|
|
full_size: this.properties.full_size
|
|
};
|
|
if (this.properties.template_properties)
|
|
Object.assign(properties, this.properties.template_properties);
|
|
const tag = template.renderTag(properties);
|
|
this._htmlTag = tag;
|
|
this._htmlTag.on('hide.bs.modal', event => !this.properties.closeable || this.close());
|
|
this._htmlTag.on('hidden.bs.modal', event => this._htmlTag.detach());
|
|
}
|
|
open() {
|
|
this.shown = true;
|
|
this.htmlTag.appendTo($("body"));
|
|
this.htmlTag.bootstrapMaterialDesign().modal(this.properties.closeable ? 'show' : {
|
|
backdrop: 'static',
|
|
keyboard: false,
|
|
});
|
|
if (this.properties.trigger_tab)
|
|
this.htmlTag.one('shown.bs.modal', () => this.htmlTag.find(".tab").trigger('tab.resize'));
|
|
}
|
|
close() {
|
|
if (!this.shown)
|
|
return;
|
|
this.shown = false;
|
|
this.htmlTag.modal('hide');
|
|
this.properties.triggerClose();
|
|
for (const listener of this.close_listener)
|
|
listener();
|
|
}
|
|
}
|
|
function createModal(data) {
|
|
return new Modal(ModalFunctions.warpProperties(data));
|
|
}
|
|
class InputModalProperties extends ModalProperties {
|
|
}
|
|
function createInputModal(headMessage, question, validator, callback, props = {}) {
|
|
props = ModalFunctions.warpProperties(props);
|
|
props.template_properties || (props.template_properties = {});
|
|
props.template_properties.field_title = props.field_title;
|
|
props.template_properties.field_label = props.field_label;
|
|
props.template_properties.field_placeholder = props.field_placeholder;
|
|
props.template_properties.error_message = props.error_message;
|
|
props.template = "#tmpl_modal_input";
|
|
props.header = headMessage;
|
|
props.template_properties.question = ModalFunctions.jqueriefy(question);
|
|
const modal = createModal(props);
|
|
const input = modal.htmlTag.find(".container-value input");
|
|
const button_cancel = modal.htmlTag.find(".button-cancel");
|
|
const button_submit = modal.htmlTag.find(".button-submit");
|
|
let submited = false;
|
|
input.on('keyup change', event => {
|
|
const str = input.val();
|
|
const valid = str !== undefined && validator(str);
|
|
input.attr("pattern", valid ? null : "^[a]{1000}$").toggleClass("is-invalid", !valid);
|
|
button_submit.prop("disabled", !valid);
|
|
});
|
|
button_submit.on('click', event => {
|
|
if (!submited) {
|
|
submited = true;
|
|
const str = input.val();
|
|
if (str !== undefined && validator(str))
|
|
callback(str);
|
|
else
|
|
callback(false);
|
|
}
|
|
modal.close();
|
|
}).prop("disabled", !validator("")); /* disabled if empty input isn't allowed */
|
|
button_cancel.on('click', event => {
|
|
if (!submited) {
|
|
submited = true;
|
|
callback(false);
|
|
}
|
|
modal.close();
|
|
});
|
|
modal.close_listener.push(() => button_cancel.trigger('click'));
|
|
return modal;
|
|
}
|
|
function createErrorModal(header, message, props = { footer: undefined }) {
|
|
props = ModalFunctions.warpProperties(props);
|
|
(props.template_properties || (props.template_properties = {})).header_class = "modal-header-error";
|
|
props.header = header;
|
|
props.body = message;
|
|
return createModal(props);
|
|
}
|
|
function createInfoModal(header, message, props = { footer: undefined }) {
|
|
props = ModalFunctions.warpProperties(props);
|
|
(props.template_properties || (props.template_properties = {})).header_class = "modal-header-info";
|
|
props.header = header;
|
|
props.body = message;
|
|
return createModal(props);
|
|
}
|
|
$.fn.modalize = function (entry_callback, properties) {
|
|
properties = properties || {};
|
|
entry_callback = entry_callback || ((a, b, c) => undefined);
|
|
let tag_modal = this[0].tagName.toLowerCase() == "modal" ? this : undefined; /* TODO may throw exception? */
|
|
let tag_head = tag_modal ? tag_modal.find("modal-header") : ModalFunctions.jqueriefy(properties.header);
|
|
let tag_body = tag_modal ? tag_modal.find("modal-body") : this;
|
|
let tag_footer = tag_modal ? tag_modal.find("modal-footer") : ModalFunctions.jqueriefy(properties.footer);
|
|
const result = entry_callback(tag_head, tag_body, tag_footer) || {};
|
|
properties.header = result.header || tag_head;
|
|
properties.body = result.body || tag_body;
|
|
properties.footer = result.footer || tag_footer;
|
|
return createModal(properties);
|
|
};
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["5fd9db372c787bbb778707708e77bfa5f651f4080dfc1637351e827593055aa8"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["5fd9db372c787bbb778707708e77bfa5f651f4080dfc1637351e827593055aa8"] = "5fd9db372c787bbb778707708e77bfa5f651f4080dfc1637351e827593055aa8";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "rylmoMRv", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceRecorder.ts (125,34)" }, { name: "xETnJw_h", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceRecorder.ts (125,54)" }, { name: "UXHjTt3O", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceRecorder.ts (162,26)" }, { name: "P0Yq63W0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceRecorder.ts (211,21)" }, { name: "wE38NthB", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceRecorder.ts (223,30)" }, { name: "Haajz6fY", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceRecorder.ts (223,67)" }, { name: "JzoHoA05", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceRecorder.ts (224,27)" }, { name: "ZAgN8FTN", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceRecorder.ts (230,21)" }, { name: "HvtFBzv8", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceRecorder.ts (256,25)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="VoiceHandler.ts" />
|
|
/// <reference path="../utils/modal.ts" />
|
|
class VoiceActivityDetector {
|
|
initialise() { }
|
|
finalize() { }
|
|
initialiseNewStream(old, _new) { }
|
|
changeHandle(handle, triggerNewStream) {
|
|
const oldStream = !this.handle ? undefined : this.handle.getMicrophoneStream();
|
|
this.handle = handle;
|
|
if (triggerNewStream)
|
|
this.initialiseNewStream(oldStream, !handle ? undefined : handle.getMicrophoneStream());
|
|
}
|
|
}
|
|
if (!AudioBuffer.prototype.copyToChannel) { //Webkit does not implement this function
|
|
AudioBuffer.prototype.copyToChannel = function (source, channelNumber, startInChannel) {
|
|
if (!startInChannel)
|
|
startInChannel = 0;
|
|
let destination = this.getChannelData(channelNumber);
|
|
for (let index = 0; index < source.length; index++)
|
|
if (destination.length < index + startInChannel)
|
|
destination[index + startInChannel] = source[index];
|
|
};
|
|
}
|
|
class VoiceRecorder {
|
|
constructor(handle) {
|
|
this.on_data = undefined;
|
|
this._recording = false;
|
|
this.microphoneStream = undefined;
|
|
this.mediaStream = undefined;
|
|
this._chunkCount = 0;
|
|
this.handle = handle;
|
|
this._deviceId = settings.global("microphone_device_id", "default");
|
|
this._deviceGroup = settings.global("microphone_device_group", "default");
|
|
audio.player.on_ready(() => {
|
|
this.audioContext = audio.player.context();
|
|
this.processor = this.audioContext.createScriptProcessor(VoiceRecorder.BUFFER_SIZE, VoiceRecorder.CHANNELS, VoiceRecorder.CHANNELS);
|
|
const empty_buffer = this.audioContext.createBuffer(VoiceRecorder.CHANNELS, VoiceRecorder.BUFFER_SIZE, 48000);
|
|
this.processor.addEventListener('audioprocess', ev => {
|
|
if (this.microphoneStream && this.vadHandler.shouldRecord(ev.inputBuffer)) {
|
|
if (this._chunkCount == 0 && this.on_start)
|
|
this.on_start();
|
|
if (this.on_data)
|
|
this.on_data(ev.inputBuffer, this._chunkCount == 0);
|
|
else {
|
|
for (let channel = 0; channel < ev.inputBuffer.numberOfChannels; channel++)
|
|
ev.outputBuffer.copyToChannel(ev.inputBuffer.getChannelData(channel), channel);
|
|
}
|
|
this._chunkCount++;
|
|
}
|
|
else {
|
|
if (this._chunkCount != 0 && this.on_end)
|
|
this.on_end();
|
|
this._chunkCount = 0;
|
|
for (let channel = 0; channel < ev.inputBuffer.numberOfChannels; channel++)
|
|
ev.outputBuffer.copyToChannel(empty_buffer.getChannelData(channel), channel);
|
|
}
|
|
});
|
|
this.processor.connect(this.audioContext.destination);
|
|
if (this.vadHandler)
|
|
this.vadHandler.initialise();
|
|
this.on_microphone(this.mediaStream);
|
|
});
|
|
this.setVADHandler(new PassThroughVAD());
|
|
}
|
|
get_output_stream() { return this.processor; }
|
|
available() {
|
|
return !!getUserMediaFunction() && !!getUserMediaFunction();
|
|
}
|
|
recording() {
|
|
return this._recording;
|
|
}
|
|
getMediaStream() {
|
|
return this.mediaStream;
|
|
}
|
|
getMicrophoneStream() {
|
|
return this.microphoneStream;
|
|
}
|
|
reinitialiseVAD() {
|
|
let type = settings.global("vad_type", "vad");
|
|
if (type == "ppt") {
|
|
if (settings.global('vad_ppt_key', undefined)) {
|
|
//TODO remove that because its legacy shit
|
|
createErrorModal(_translations.rylmoMRv || (_translations.rylmoMRv = tr("VAD changed!")), _translations.xETnJw_h || (_translations.xETnJw_h = tr("VAD key detection changed.<br>Please reset your PPT key!"))).open();
|
|
}
|
|
let ppt_settings = settings.global('vad_ppt_settings', undefined);
|
|
ppt_settings = ppt_settings ? JSON.parse(ppt_settings) : {};
|
|
if (ppt_settings.version === undefined)
|
|
ppt_settings.version = 1;
|
|
if (ppt_settings.key_code === undefined)
|
|
ppt_settings.key_code = "KeyT";
|
|
if (ppt_settings.key_ctrl === undefined)
|
|
ppt_settings.key_ctrl = false;
|
|
if (ppt_settings.key_shift === undefined)
|
|
ppt_settings.key_shift = false;
|
|
if (ppt_settings.key_alt === undefined)
|
|
ppt_settings.key_alt = false;
|
|
if (ppt_settings.key_windows === undefined)
|
|
ppt_settings.key_windows = false;
|
|
if (ppt_settings.delay === undefined)
|
|
ppt_settings.delay = 300;
|
|
if (!(this.getVADHandler() instanceof PushToTalkVAD))
|
|
this.setVADHandler(new PushToTalkVAD(ppt_settings));
|
|
else
|
|
this.getVADHandler().settings = ppt_settings;
|
|
}
|
|
else if (type == "pt") {
|
|
if (!(this.getVADHandler() instanceof PassThroughVAD))
|
|
this.setVADHandler(new PassThroughVAD());
|
|
}
|
|
else if (type == "vad") {
|
|
if (!(this.getVADHandler() instanceof VoiceActivityDetectorVAD))
|
|
this.setVADHandler(new VoiceActivityDetectorVAD());
|
|
this.getVADHandler().percentageThreshold = settings.global("vad_threshold", 50);
|
|
}
|
|
else {
|
|
console.warn(_translations.UXHjTt3O || (_translations.UXHjTt3O = tr("Invalid VAD (Voice activation detector) handler! (%o)")), type);
|
|
}
|
|
}
|
|
setVADHandler(handler) {
|
|
if (this.vadHandler) {
|
|
this.vadHandler.changeHandle(null, true);
|
|
this.vadHandler.finalize();
|
|
}
|
|
this.vadHandler = handler;
|
|
this.vadHandler.changeHandle(this, false);
|
|
if (this.audioContext) {
|
|
this.vadHandler.initialise();
|
|
if (this.microphoneStream)
|
|
this.vadHandler.initialiseNewStream(undefined, this.microphoneStream);
|
|
}
|
|
}
|
|
getVADHandler() {
|
|
return this.vadHandler;
|
|
}
|
|
update(flag) {
|
|
if (this._recording == flag)
|
|
return;
|
|
if (flag)
|
|
this.start(this._deviceId, this._deviceGroup);
|
|
else
|
|
this.stop();
|
|
}
|
|
device_group_id() { return this._deviceGroup; }
|
|
device_id() { return this._deviceId; }
|
|
change_device(device, group) {
|
|
if (this._deviceId == device && this._deviceGroup == group)
|
|
return;
|
|
this._deviceId = device;
|
|
this._deviceGroup = group;
|
|
settings.changeGlobal("microphone_device_id", device);
|
|
settings.changeGlobal("microphone_device_group", group);
|
|
if (this._recording) {
|
|
this.stop();
|
|
this.start(device, group);
|
|
}
|
|
}
|
|
start(device, groupId) {
|
|
this._deviceId = device;
|
|
this._deviceGroup = groupId;
|
|
console.log(_translations.P0Yq63W0 || (_translations.P0Yq63W0 = tr("[VoiceRecorder] Start recording! (Device: %o | Group: %o)")), device, groupId);
|
|
this._recording = true;
|
|
//FIXME Implement that here for thew client as well
|
|
getUserMediaFunction()({
|
|
audio: {
|
|
deviceId: device,
|
|
groupId: groupId,
|
|
echoCancellation: true,
|
|
echoCancellationType: 'browser'
|
|
}
|
|
}, this.on_microphone.bind(this), error => {
|
|
createErrorModal(_translations.wE38NthB || (_translations.wE38NthB = tr("Could not resolve microphone!")), (_translations.Haajz6fY || (_translations.Haajz6fY = tr("Could not resolve microphone!<br>Message: "))) + error).open();
|
|
console.error(_translations.JzoHoA05 || (_translations.JzoHoA05 = tr("Could not get microphone!")));
|
|
console.error(error);
|
|
});
|
|
}
|
|
stop(stop_media_stream = true) {
|
|
console.log(_translations.ZAgN8FTN || (_translations.ZAgN8FTN = tr("Stop recording!")));
|
|
this._recording = false;
|
|
if (this.microphoneStream)
|
|
this.microphoneStream.disconnect();
|
|
this.microphoneStream = undefined;
|
|
if (stop_media_stream && this.mediaStream) {
|
|
if (this.mediaStream.stop)
|
|
this.mediaStream.stop();
|
|
else
|
|
this.mediaStream.getTracks().forEach(value => {
|
|
value.stop();
|
|
});
|
|
this.mediaStream = undefined;
|
|
}
|
|
}
|
|
on_microphone(stream) {
|
|
const old_microphone_stream = this.microphoneStream;
|
|
if (old_microphone_stream)
|
|
this.stop(this.mediaStream != stream); //Disconnect old stream
|
|
this.mediaStream = stream;
|
|
if (!this.mediaStream)
|
|
return;
|
|
if (!this.audioContext) {
|
|
console.log(_translations.HvtFBzv8 || (_translations.HvtFBzv8 = tr("[VoiceRecorder] Got microphone stream, but havn't a audio context. Waiting until its initialized")));
|
|
return;
|
|
}
|
|
this.microphoneStream = this.audioContext.createMediaStreamSource(stream);
|
|
this.microphoneStream.connect(this.processor);
|
|
if (this.vadHandler)
|
|
this.vadHandler.initialiseNewStream(old_microphone_stream, this.microphoneStream);
|
|
}
|
|
}
|
|
VoiceRecorder.CHANNEL = 0;
|
|
VoiceRecorder.CHANNELS = 2;
|
|
VoiceRecorder.BUFFER_SIZE = 1024 * 4;
|
|
class MuteVAD extends VoiceActivityDetector {
|
|
shouldRecord(buffer) {
|
|
return false;
|
|
}
|
|
}
|
|
class PassThroughVAD extends VoiceActivityDetector {
|
|
shouldRecord(buffer) {
|
|
return true;
|
|
}
|
|
}
|
|
class VoiceActivityDetectorVAD extends VoiceActivityDetector {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.continuesCount = 0;
|
|
this.maxContinuesCount = 12;
|
|
this.percentageThreshold = 50;
|
|
this.percentage_listener = ($) => { };
|
|
}
|
|
initialise() {
|
|
this.analyzer = audio.player.context().createAnalyser();
|
|
this.analyzer.smoothingTimeConstant = 1; //TODO test
|
|
this.buffer = new Uint8Array(this.analyzer.fftSize);
|
|
return super.initialise();
|
|
}
|
|
initialiseNewStream(old, _new) {
|
|
if (this.analyzer)
|
|
this.analyzer.disconnect();
|
|
if (_new)
|
|
_new.connect(this.analyzer);
|
|
}
|
|
shouldRecord(buffer) {
|
|
let usage = this.calculateUsage();
|
|
if ($.isFunction(this.percentage_listener))
|
|
this.percentage_listener(usage);
|
|
if (usage >= this.percentageThreshold) {
|
|
this.continuesCount = 0;
|
|
}
|
|
else
|
|
this.continuesCount++;
|
|
return this.continuesCount < this.maxContinuesCount;
|
|
}
|
|
calculateUsage() {
|
|
let total = 0, float, rms;
|
|
this.analyzer.getByteTimeDomainData(this.buffer);
|
|
for (let index = 0; index < this.analyzer.fftSize; index++) {
|
|
float = (this.buffer[index++] / 0x7f) - 1;
|
|
total += (float * float);
|
|
}
|
|
rms = Math.sqrt(total / this.analyzer.fftSize);
|
|
let db = 20 * (Math.log(rms) / Math.log(10));
|
|
// sanity check
|
|
db = Math.max(-192, Math.min(db, 0));
|
|
let percentage = 100 + (db * 1.92);
|
|
return percentage;
|
|
}
|
|
}
|
|
class PushToTalkVAD extends VoiceActivityDetector {
|
|
constructor(settings) {
|
|
super();
|
|
this._pushed = false;
|
|
this._settings = settings;
|
|
this._key_hook = {
|
|
callback_release: () => {
|
|
if (this._timeout)
|
|
clearTimeout(this._timeout);
|
|
if (this._settings.delay > 0)
|
|
this._timeout = setTimeout(() => this._pushed = false, this._settings.delay);
|
|
else
|
|
this._pushed = false;
|
|
},
|
|
callback_press: () => {
|
|
if (this._timeout)
|
|
clearTimeout(this._timeout);
|
|
this._pushed = true;
|
|
},
|
|
cancel: false
|
|
};
|
|
this.initialize_hook();
|
|
}
|
|
initialize_hook() {
|
|
this._key_hook.key_code = this._settings.key_code;
|
|
this._key_hook.key_alt = this._settings.key_alt;
|
|
this._key_hook.key_ctrl = this._settings.key_ctrl;
|
|
this._key_hook.key_shift = this._settings.key_shift;
|
|
this._key_hook.key_windows = this._settings.key_windows;
|
|
}
|
|
initialise() {
|
|
ppt.register_key_hook(this._key_hook);
|
|
return super.initialise();
|
|
}
|
|
finalize() {
|
|
ppt.unregister_key_hook(this._key_hook);
|
|
return super.finalize();
|
|
}
|
|
set pushed(flag) {
|
|
this._pushed = flag;
|
|
}
|
|
set settings(settings) {
|
|
ppt.unregister_key_hook(this._key_hook);
|
|
this._settings = settings;
|
|
this.initialize_hook();
|
|
this._pushed = false;
|
|
ppt.register_key_hook(this._key_hook);
|
|
}
|
|
shouldRecord(buffer) {
|
|
return this._pushed;
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["a56b051f4149c533919f4d7866c06de89650bb402337b0eef46443058cd37914"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["a56b051f4149c533919f4d7866c06de89650bb402337b0eef46443058cd37914"] = "a56b051f4149c533919f4d7866c06de89650bb402337b0eef46443058cd37914";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "t8oqO1lc", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (28,25)" }, { name: "mIUPETWo", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (32,30)" }, { name: "chRtM0Ti", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (33,34)" }, { name: "TGT0SBXJ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (33,69)" }, { name: "PHQN4qwo", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (35,31)" }, { name: "ysFQ3wS5", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (37,31)" }, { name: "yAAdD7jC", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (48,24)" }, { name: "tjJfo7Dk", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (62,43)" }, { name: "E0WsEWiE", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (63,73)" }, { name: "YSTA_3JN", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (136,30)" }, { name: "nn0gTahg", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (137,30)" }, { name: "YzErO11B", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (138,30)" }, { name: "JlimUN5_", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (139,30)" }, { name: "INHTsvO8", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (140,30)" }, { name: "SKGjM2fl", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (141,30)" }, { name: "gtVYEggq", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (157,41)" }, { name: "mU7ZAmC6", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (197,37)" }, { name: "F7kOnJnp", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (199,41)" }, { name: "FBBcXTnB", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (274,26)" }, { name: "QTx3nvcX", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (281,25)" }, { name: "z0mKdtjN", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (312,25)" }, { name: "DTf5g1uR", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (315,27)" }, { name: "A1ka3yfu", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (329,25)" }, { name: "BNCVcnv7", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (331,29)" }, { name: "B7EYIlQD", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (336,33)" }, { name: "j7WFGiPM", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (341,29)" }, { name: "Y1UQmWiM", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (343,33)" }, { name: "XOmIStjD", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (346,29)" }, { name: "ythe3GnZ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (351,47)" }, { name: "_vnSXilG", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (352,51)" }, { name: "sHVFQdqt", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (363,21)" }, { name: "R64I2bL6", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (382,21)" }, { name: "rpGfb5bB", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (384,25)" }, { name: "sUrbL8F8", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (388,21)" }, { name: "aCeDkOq4", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (393,21)" }, { name: "u9oEsZpv", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (407,27)" }, { name: "sQ8Ba2oR", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (413,27)" }, { name: "vH2yGkAk", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (429,35)" }, { name: "S2lnS5ls", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (462,21)" }, { name: "PXSYJ5v0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/VoiceHandler.ts (469,21)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../client.ts" />
|
|
/// <reference path="../codec/Codec.ts" />
|
|
/// <reference path="VoiceRecorder.ts" />
|
|
class CodecPoolEntry {
|
|
}
|
|
class CodecPool {
|
|
constructor(handle, index, name, type) {
|
|
this.entries = [];
|
|
this.maxInstances = 2;
|
|
this._supported = true;
|
|
this.handle = handle;
|
|
this.codecIndex = index;
|
|
this.name = name;
|
|
this.type = type;
|
|
this._supported = this.type !== undefined && audio.codec.supported(this.type);
|
|
}
|
|
initialize(cached) {
|
|
/* test if we're able to use this codec */
|
|
const dummy_client_id = 0xFFEF;
|
|
this.ownCodec(dummy_client_id).then(codec => {
|
|
console.log(_translations.t8oqO1lc || (_translations.t8oqO1lc = tr("Release again! (%o)")), codec);
|
|
this.releaseCodec(dummy_client_id);
|
|
}).catch(error => {
|
|
if (this._supported) {
|
|
console.warn(_translations.mIUPETWo || (_translations.mIUPETWo = tr("Disabling codec support for ")), this.name);
|
|
createErrorModal(_translations.chRtM0Ti || (_translations.chRtM0Ti = tr("Could not load codec driver")), (_translations.TGT0SBXJ || (_translations.TGT0SBXJ = tr("Could not load or initialize codec "))) + this.name + "<br>" +
|
|
"Error: <code>" + JSON.stringify(error) + "</code>").open();
|
|
console.error(_translations.PHQN4qwo || (_translations.PHQN4qwo = tr("Failed to initialize the opus codec. Error: %o")), error);
|
|
}
|
|
else {
|
|
console.debug(_translations.ysFQ3wS5 || (_translations.ysFQ3wS5 = tr("Failed to initialize already disabled codec. Error: %o")), error);
|
|
}
|
|
this._supported = false;
|
|
});
|
|
}
|
|
supported() { return this._supported; }
|
|
ownCodec(clientId, create = true) {
|
|
return new Promise((resolve, reject) => {
|
|
if (!this._supported) {
|
|
reject(_translations.yAAdD7jC || (_translations.yAAdD7jC = tr("unsupported codec!")));
|
|
return;
|
|
}
|
|
let freeSlot = 0;
|
|
for (let index = 0; index < this.entries.length; index++) {
|
|
if (this.entries[index].owner == clientId) {
|
|
this.entries[index].last_access = new Date().getTime();
|
|
if (this.entries[index].instance.initialized())
|
|
resolve(this.entries[index].instance);
|
|
else {
|
|
this.entries[index].instance.initialise().then((flag) => {
|
|
//TODO test success flag
|
|
this.ownCodec(clientId, false).then(resolve).catch(reject);
|
|
}).catch(error => {
|
|
console.error(_translations.tjJfo7Dk || (_translations.tjJfo7Dk = tr("Could not initialize codec!\nError: %o")), error);
|
|
reject(typeof (error) === 'string' ? error : _translations.E0WsEWiE || (_translations.E0WsEWiE = tr("Could not initialize codec!")));
|
|
});
|
|
}
|
|
return;
|
|
}
|
|
else if (freeSlot == 0 && this.entries[index].owner == 0) {
|
|
freeSlot = index;
|
|
}
|
|
}
|
|
if (!create) {
|
|
resolve(undefined);
|
|
return;
|
|
}
|
|
if (freeSlot == 0) {
|
|
freeSlot = this.entries.length;
|
|
let entry = new CodecPoolEntry();
|
|
entry.instance = audio.codec.new_instance(this.type);
|
|
entry.instance.on_encoded_data = buffer => this.handle.handleEncodedVoicePacket(buffer, this.codecIndex);
|
|
this.entries.push(entry);
|
|
}
|
|
this.entries[freeSlot].owner = clientId;
|
|
this.entries[freeSlot].last_access = new Date().getTime();
|
|
if (this.entries[freeSlot].instance.initialized())
|
|
this.entries[freeSlot].instance.reset();
|
|
else {
|
|
this.ownCodec(clientId, false).then(resolve).catch(reject);
|
|
return;
|
|
}
|
|
resolve(this.entries[freeSlot].instance);
|
|
});
|
|
}
|
|
releaseCodec(clientId) {
|
|
for (let index = 0; index < this.entries.length; index++)
|
|
if (this.entries[index].owner == clientId)
|
|
this.entries[index].owner = 0;
|
|
}
|
|
}
|
|
var VoiceConnectionType;
|
|
(function (VoiceConnectionType) {
|
|
VoiceConnectionType[VoiceConnectionType["JS_ENCODE"] = 0] = "JS_ENCODE";
|
|
VoiceConnectionType[VoiceConnectionType["NATIVE_ENCODE"] = 1] = "NATIVE_ENCODE";
|
|
})(VoiceConnectionType || (VoiceConnectionType = {}));
|
|
class VoiceConnection {
|
|
constructor(client) {
|
|
this._type = VoiceConnectionType.NATIVE_ENCODE;
|
|
this.codec_pool = [
|
|
new CodecPool(this, 0, _translations.YSTA_3JN || (_translations.YSTA_3JN = tr("Speex Narrowband")), CodecType.SPEEX_NARROWBAND),
|
|
new CodecPool(this, 1, _translations.nn0gTahg || (_translations.nn0gTahg = tr("Speex Wideband")), CodecType.SPEEX_WIDEBAND),
|
|
new CodecPool(this, 2, _translations.YzErO11B || (_translations.YzErO11B = tr("Speex Ultra Wideband")), CodecType.SPEEX_ULTRA_WIDEBAND),
|
|
new CodecPool(this, 3, _translations.JlimUN5_ || (_translations.JlimUN5_ = tr("CELT Mono")), CodecType.CELT_MONO),
|
|
new CodecPool(this, 4, _translations.INHTsvO8 || (_translations.INHTsvO8 = tr("Opus Voice")), CodecType.OPUS_VOICE),
|
|
new CodecPool(this, 5, _translations.SKGjM2fl || (_translations.SKGjM2fl = tr("Opus Music")), CodecType.OPUS_MUSIC)
|
|
];
|
|
this.vpacketId = 0;
|
|
this.chunkVPacketId = 0;
|
|
this.voice_send_queue = [];
|
|
this._ice_use_cache = true;
|
|
this._ice_cache = [];
|
|
this.client = client;
|
|
this._type = settings.static_global("voice_connection_type", this._type);
|
|
this.voiceRecorder = new VoiceRecorder(this);
|
|
this.voiceRecorder.on_end = this.handleVoiceEnded.bind(this);
|
|
this.voiceRecorder.on_start = this.handleVoiceStarted.bind(this);
|
|
this.voiceRecorder.reinitialiseVAD();
|
|
audio.player.on_ready(() => {
|
|
log.info(LogCategory.VOICE, _translations.gtVYEggq || (_translations.gtVYEggq = tr("Initializing voice handler after AudioController has been initialized!")));
|
|
if (native_client) {
|
|
this.codec_pool[0].initialize(2);
|
|
this.codec_pool[1].initialize(2);
|
|
this.codec_pool[2].initialize(2);
|
|
this.codec_pool[3].initialize(2);
|
|
}
|
|
this.codec_pool[4].initialize(2);
|
|
this.codec_pool[5].initialize(2);
|
|
if (this.type == VoiceConnectionType.NATIVE_ENCODE)
|
|
this.setup_native();
|
|
else
|
|
this.setup_js();
|
|
});
|
|
this.send_task = setInterval(this.sendNextVoicePacket.bind(this), 20);
|
|
}
|
|
native_encoding_supported() {
|
|
if (!(window.webkitAudioContext || window.AudioContext || { prototype: {} }).prototype.createMediaStreamDestination)
|
|
return false; //Required, but not available within edge
|
|
return true;
|
|
}
|
|
javascript_encoding_supported() {
|
|
if (!(window.RTCPeerConnection || { prototype: {} }).prototype.createDataChannel)
|
|
return false;
|
|
return true;
|
|
}
|
|
current_encoding_supported() {
|
|
switch (this._type) {
|
|
case VoiceConnectionType.JS_ENCODE:
|
|
return this.javascript_encoding_supported();
|
|
case VoiceConnectionType.NATIVE_ENCODE:
|
|
return this.native_encoding_supported();
|
|
}
|
|
return false;
|
|
}
|
|
setup_native() {
|
|
log.info(LogCategory.VOICE, _translations.mU7ZAmC6 || (_translations.mU7ZAmC6 = tr("Setting up native voice stream!")));
|
|
if (!this.native_encoding_supported()) {
|
|
log.warn(LogCategory.VOICE, _translations.F7kOnJnp || (_translations.F7kOnJnp = tr("Native codec isnt supported!")));
|
|
return;
|
|
}
|
|
this.voiceRecorder.on_data = undefined;
|
|
let stream = this.voiceRecorder.get_output_stream();
|
|
stream.disconnect();
|
|
if (!this.local_audio_stream)
|
|
this.local_audio_stream = audio.player.context().createMediaStreamDestination();
|
|
stream.connect(this.local_audio_stream);
|
|
}
|
|
setup_js() {
|
|
if (!this.javascript_encoding_supported())
|
|
return;
|
|
this.voiceRecorder.on_data = this.handleVoiceData.bind(this);
|
|
}
|
|
get type() { return this._type; }
|
|
set type(target) {
|
|
if (target == this.type)
|
|
return;
|
|
this._type = target;
|
|
if (this.type == VoiceConnectionType.NATIVE_ENCODE)
|
|
this.setup_native();
|
|
else
|
|
this.setup_js();
|
|
this.createSession();
|
|
}
|
|
codecSupported(type) {
|
|
return this.codec_pool.length > type && this.codec_pool[type].supported();
|
|
}
|
|
voice_playback_support() {
|
|
return this.dataChannel && this.dataChannel.readyState == "open";
|
|
}
|
|
voice_send_support() {
|
|
if (this.type == VoiceConnectionType.NATIVE_ENCODE)
|
|
return this.native_encoding_supported() && this.rtcPeerConnection.getLocalStreams().length > 0;
|
|
else
|
|
return this.voice_playback_support();
|
|
}
|
|
handleEncodedVoicePacket(data, codec) {
|
|
this.voice_send_queue.push({ data: data, codec: codec });
|
|
}
|
|
sendNextVoicePacket() {
|
|
let buffer = this.voice_send_queue.pop_front();
|
|
if (!buffer)
|
|
return;
|
|
this.sendVoicePacket(buffer.data, buffer.codec);
|
|
}
|
|
sendVoicePacket(data, codec) {
|
|
if (this.dataChannel) {
|
|
this.vpacketId++;
|
|
if (this.vpacketId > 65535)
|
|
this.vpacketId = 0;
|
|
let packet = new Uint8Array(data.byteLength + 2 + 3);
|
|
packet[0] = this.chunkVPacketId++ < 5 ? 1 : 0; //Flag header
|
|
packet[1] = 0; //Flag fragmented
|
|
packet[2] = (this.vpacketId >> 8) & 0xFF; //HIGHT (voiceID)
|
|
packet[3] = (this.vpacketId >> 0) & 0xFF; //LOW (voiceID)
|
|
packet[4] = codec; //Codec
|
|
packet.set(data, 5);
|
|
try {
|
|
this.dataChannel.send(packet);
|
|
}
|
|
catch (e) {
|
|
//TODO may handle error?
|
|
}
|
|
}
|
|
else {
|
|
console.warn(_translations.FBBcXTnB || (_translations.FBBcXTnB = tr("Could not transfer audio (not connected)")));
|
|
}
|
|
}
|
|
createSession() {
|
|
if (!audio.player.initialized()) {
|
|
console.log(_translations.QTx3nvcX || (_translations.QTx3nvcX = tr("Audio player isn't initialized yet. Waiting for gesture.")));
|
|
audio.player.on_ready(() => this.createSession());
|
|
return;
|
|
}
|
|
if (!this.current_encoding_supported())
|
|
return false;
|
|
if (this.rtcPeerConnection) {
|
|
this.dropSession();
|
|
}
|
|
this._ice_use_cache = true;
|
|
let config = {};
|
|
config.iceServers = [];
|
|
config.iceServers.push({ urls: 'stun:stun.l.google.com:19302' });
|
|
this.rtcPeerConnection = new RTCPeerConnection(config);
|
|
const dataChannelConfig = { ordered: true, maxRetransmits: 0 };
|
|
this.dataChannel = this.rtcPeerConnection.createDataChannel('main', dataChannelConfig);
|
|
this.dataChannel.onmessage = this.onDataChannelMessage.bind(this);
|
|
this.dataChannel.onopen = this.onDataChannelOpen.bind(this);
|
|
this.dataChannel.binaryType = "arraybuffer";
|
|
let sdpConstraints = {};
|
|
sdpConstraints.offerToReceiveAudio = this._type == VoiceConnectionType.NATIVE_ENCODE;
|
|
sdpConstraints.offerToReceiveVideo = false;
|
|
this.rtcPeerConnection.onicecandidate = this.onIceCandidate.bind(this);
|
|
if (this.local_audio_stream) { //May a typecheck?
|
|
this.rtcPeerConnection.addStream(this.local_audio_stream.stream);
|
|
console.log(_translations.z0mKdtjN || (_translations.z0mKdtjN = tr("Adding stream (%o)!")), this.local_audio_stream.stream);
|
|
}
|
|
this.rtcPeerConnection.createOffer(this.onOfferCreated.bind(this), () => {
|
|
console.error(_translations.DTf5g1uR || (_translations.DTf5g1uR = tr("Could not create ice offer!")));
|
|
}, sdpConstraints);
|
|
}
|
|
dropSession() {
|
|
if (this.dataChannel)
|
|
this.dataChannel.close();
|
|
if (this.rtcPeerConnection)
|
|
this.rtcPeerConnection.close();
|
|
//TODO here!
|
|
}
|
|
handleControlPacket(json) {
|
|
if (json["request"] === "answer") {
|
|
console.log(_translations.A1ka3yfu || (_translations.A1ka3yfu = tr("Set remote sdp! (%o)")), json["msg"]);
|
|
this.rtcPeerConnection.setRemoteDescription(new RTCSessionDescription(json["msg"])).catch(error => {
|
|
console.log(_translations.BNCVcnv7 || (_translations.BNCVcnv7 = tr("Failed to apply remote description: %o")), error); //FIXME error handling!
|
|
});
|
|
this._ice_use_cache = false;
|
|
for (let msg of this._ice_cache) {
|
|
this.rtcPeerConnection.addIceCandidate(new RTCIceCandidate(msg)).catch(error => {
|
|
console.log(_translations.B7EYIlQD || (_translations.B7EYIlQD = tr("Failed to add remote cached ice candidate %s: %o")), msg, error);
|
|
});
|
|
}
|
|
}
|
|
else if (json["request"] === "ice") {
|
|
if (!this._ice_use_cache) {
|
|
console.log(_translations.j7WFGiPM || (_translations.j7WFGiPM = tr("Add remote ice! (%s | %o)")), json["msg"], json);
|
|
this.rtcPeerConnection.addIceCandidate(new RTCIceCandidate(json["msg"])).catch(error => {
|
|
console.log(_translations.Y1UQmWiM || (_translations.Y1UQmWiM = tr("Failed to add remote ice candidate %s: %o")), json["msg"], error);
|
|
});
|
|
}
|
|
else {
|
|
console.log(_translations.XOmIStjD || (_translations.XOmIStjD = tr("Cache remote ice! (%s | %o)")), json["msg"], json);
|
|
this._ice_cache.push(json["msg"]);
|
|
}
|
|
}
|
|
else if (json["request"] == "status") {
|
|
if (json["state"] == "failed") {
|
|
chat.serverChat().appendError(_translations.ythe3GnZ || (_translations.ythe3GnZ = tr("Failed to setup voice bridge ({}). Allow reconnect: {}")), json["reason"], json["allow_reconnect"]);
|
|
log.error(LogCategory.NETWORKING, _translations._vnSXilG || (_translations._vnSXilG = tr("Failed to setup voice bridge (%s). Allow reconnect: %s")), json["reason"], json["allow_reconnect"]);
|
|
if (json["allow_reconnect"] == true) {
|
|
this.createSession();
|
|
}
|
|
//TODO handle fail specially when its not allowed to reconnect
|
|
}
|
|
}
|
|
}
|
|
//Listeners
|
|
onIceCandidate(event) {
|
|
console.log(_translations.sHVFQdqt || (_translations.sHVFQdqt = tr("Got ice candidate! Event:")));
|
|
console.log(event);
|
|
if (event) {
|
|
if (event.candidate)
|
|
this.client.serverConnection.sendData(JSON.stringify({
|
|
type: 'WebRTC',
|
|
request: "ice",
|
|
msg: event.candidate,
|
|
}));
|
|
else {
|
|
this.client.serverConnection.sendData(JSON.stringify({
|
|
type: 'WebRTC',
|
|
request: "ice_finish"
|
|
}));
|
|
}
|
|
}
|
|
}
|
|
onOfferCreated(localSession) {
|
|
console.log(_translations.R64I2bL6 || (_translations.R64I2bL6 = tr("Offer created and accepted")));
|
|
this.rtcPeerConnection.setLocalDescription(localSession).catch(error => {
|
|
console.log(_translations.rpGfb5bB || (_translations.rpGfb5bB = tr("Failed to apply local description: %o")), error);
|
|
//FIXME error handling
|
|
});
|
|
console.log(_translations.sUrbL8F8 || (_translations.sUrbL8F8 = tr("Send offer: %o")), localSession);
|
|
this.client.serverConnection.sendData(JSON.stringify({ type: 'WebRTC', request: "create", msg: localSession }));
|
|
}
|
|
onDataChannelOpen(channel) {
|
|
console.log(_translations.aCeDkOq4 || (_translations.aCeDkOq4 = tr("Got new data channel! (%s)")), this.dataChannel.readyState);
|
|
this.client.controlBar.updateVoice();
|
|
}
|
|
onDataChannelMessage(message) {
|
|
if (this.client.controlBar.muteOutput)
|
|
return;
|
|
let bin = new Uint8Array(message.data);
|
|
let clientId = bin[2] << 8 | bin[3];
|
|
let packetId = bin[0] << 8 | bin[1];
|
|
let codec = bin[4];
|
|
//console.log("Client id " + clientId + " PacketID " + packetId + " Codec: " + codec);
|
|
let client = this.client.channelTree.findClient(clientId);
|
|
if (!client) {
|
|
console.error(_translations.u9oEsZpv || (_translations.u9oEsZpv = tr("Having voice from unknown client? (ClientID: %o)")), clientId);
|
|
return;
|
|
}
|
|
let codecPool = this.codec_pool[codec];
|
|
if (!codecPool) {
|
|
console.error(_translations.sQ8Ba2oR || (_translations.sQ8Ba2oR = tr("Could not playback codec %o")), codec);
|
|
return;
|
|
}
|
|
let encodedData;
|
|
if (message.data.subarray)
|
|
encodedData = message.data.subarray(5);
|
|
else
|
|
encodedData = new Uint8Array(message.data, 5);
|
|
if (encodedData.length == 0) {
|
|
client.getAudioController().stopAudio();
|
|
codecPool.releaseCodec(clientId);
|
|
}
|
|
else {
|
|
codecPool.ownCodec(clientId)
|
|
.then(decoder => decoder.decodeSamples(client.getAudioController().codecCache(codec), encodedData))
|
|
.then(buffer => client.getAudioController().playBuffer(buffer)).catch(error => {
|
|
console.error(_translations.vH2yGkAk || (_translations.vH2yGkAk = tr("Could not playback client's (%o) audio (%o)")), clientId, error);
|
|
if (error instanceof Error)
|
|
console.error(error.stack);
|
|
});
|
|
}
|
|
}
|
|
current_channel_codec() {
|
|
return (this.client.getClient().currentChannel() || { properties: { channel_codec: 4 } }).properties.channel_codec;
|
|
}
|
|
handleVoiceData(data, head) {
|
|
if (!this.voiceRecorder)
|
|
return;
|
|
if (!this.client.connected)
|
|
return false;
|
|
if (this.client.controlBar.muteInput)
|
|
return;
|
|
if (head) {
|
|
this.chunkVPacketId = 0;
|
|
this.client.getClient().speaking = true;
|
|
}
|
|
//TODO Use channel codec!
|
|
const codec = this.current_channel_codec();
|
|
this.codec_pool[codec].ownCodec(this.client.getClientId())
|
|
.then(encoder => encoder.encodeSamples(this.client.getClient().getAudioController().codecCache(codec), data));
|
|
}
|
|
handleVoiceEnded() {
|
|
if (this.client && this.client.getClient())
|
|
this.client.getClient().speaking = false;
|
|
if (!this.voiceRecorder)
|
|
return;
|
|
if (!this.client.connected)
|
|
return;
|
|
console.log(_translations.S2lnS5ls || (_translations.S2lnS5ls = tr("Local voice ended")));
|
|
if (this.dataChannel)
|
|
this.sendVoicePacket(new Uint8Array(0), this.current_channel_codec()); //TODO Use channel codec!
|
|
}
|
|
handleVoiceStarted() {
|
|
console.log(_translations.PXSYJ5v0 || (_translations.PXSYJ5v0 = tr("Local voice started")));
|
|
if (this.client && this.client.getClient())
|
|
this.client.getClient().speaking = true;
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["775ab808069a9c2be9cc5e58e0bd80887fbc8b52ca9b9db14075a1018288337a"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["775ab808069a9c2be9cc5e58e0bd80887fbc8b52ca9b9db14075a1018288337a"] = "775ab808069a9c2be9cc5e58e0bd80887fbc8b52ca9b9db14075a1018288337a";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
let context_menu;
|
|
$(document).bind("mousedown", function (e) {
|
|
let menu = context_menu || (context_menu = $(".context-menu"));
|
|
if (!menu.is(":visible"))
|
|
return;
|
|
if ($(e.target).parents(".context-menu").length == 0) {
|
|
despawn_context_menu();
|
|
}
|
|
});
|
|
let contextMenuCloseFn = undefined;
|
|
function despawn_context_menu() {
|
|
let menu = context_menu || (context_menu = $(".context-menu"));
|
|
if (!menu.is(":visible"))
|
|
return;
|
|
menu.hide(100);
|
|
if (contextMenuCloseFn)
|
|
contextMenuCloseFn();
|
|
}
|
|
var MenuEntryType;
|
|
(function (MenuEntryType) {
|
|
MenuEntryType[MenuEntryType["CLOSE"] = 0] = "CLOSE";
|
|
MenuEntryType[MenuEntryType["ENTRY"] = 1] = "ENTRY";
|
|
MenuEntryType[MenuEntryType["HR"] = 2] = "HR";
|
|
MenuEntryType[MenuEntryType["SUB_MENU"] = 3] = "SUB_MENU";
|
|
})(MenuEntryType || (MenuEntryType = {}));
|
|
class MenuEntry {
|
|
static HR() {
|
|
return {
|
|
callback: () => { },
|
|
type: MenuEntryType.HR,
|
|
name: "",
|
|
icon: ""
|
|
};
|
|
}
|
|
;
|
|
static CLOSE(callback) {
|
|
return {
|
|
callback: callback,
|
|
type: MenuEntryType.CLOSE,
|
|
name: "",
|
|
icon: ""
|
|
};
|
|
}
|
|
}
|
|
function generate_tag(entry) {
|
|
if (entry.type == MenuEntryType.HR) {
|
|
return $.spawn("hr");
|
|
}
|
|
else if (entry.type == MenuEntryType.ENTRY) {
|
|
console.log(entry.icon);
|
|
let icon = $.isFunction(entry.icon) ? entry.icon() : entry.icon;
|
|
if (typeof (icon) === "string") {
|
|
if (!icon || icon.length == 0)
|
|
icon = "icon_empty";
|
|
else
|
|
icon = "icon " + icon;
|
|
}
|
|
let tag = $.spawn("div").addClass("entry");
|
|
tag.append(typeof (icon) === "string" ? $.spawn("div").addClass(icon) : icon);
|
|
tag.append($.spawn("div").html($.isFunction(entry.name) ? entry.name() : entry.name));
|
|
if (entry.disabled || entry.invalidPermission)
|
|
tag.addClass("disabled");
|
|
else {
|
|
tag.click(function () {
|
|
if ($.isFunction(entry.callback))
|
|
entry.callback();
|
|
despawn_context_menu();
|
|
});
|
|
}
|
|
return tag;
|
|
}
|
|
else if (entry.type == MenuEntryType.SUB_MENU) {
|
|
let icon = $.isFunction(entry.icon) ? entry.icon() : entry.icon;
|
|
if (typeof (icon) === "string") {
|
|
if (!icon || icon.length == 0)
|
|
icon = "icon_empty";
|
|
else
|
|
icon = "icon " + icon;
|
|
}
|
|
let tag = $.spawn("div").addClass("entry").addClass("sub-container");
|
|
tag.append(typeof (icon) === "string" ? $.spawn("div").addClass(icon) : icon);
|
|
tag.append($.spawn("div").html($.isFunction(entry.name) ? entry.name() : entry.name));
|
|
tag.append($.spawn("div").addClass("arrow right"));
|
|
if (entry.disabled || entry.invalidPermission)
|
|
tag.addClass("disabled");
|
|
else {
|
|
let menu = $.spawn("div").addClass("sub-menu").addClass("context-menu");
|
|
for (let e of entry.sub_menu)
|
|
menu.append(generate_tag(e));
|
|
menu.appendTo(tag);
|
|
}
|
|
return tag;
|
|
}
|
|
return $.spawn("div").text("undefined");
|
|
}
|
|
function spawn_context_menu(x, y, ...entries) {
|
|
let menu = context_menu || (context_menu = $(".context-menu"));
|
|
menu.finish().empty();
|
|
contextMenuCloseFn = undefined;
|
|
for (let entry of entries) {
|
|
if (entry.type == MenuEntryType.CLOSE) {
|
|
contextMenuCloseFn = entry.callback;
|
|
}
|
|
else
|
|
menu.append(generate_tag(entry));
|
|
}
|
|
menu.show(100);
|
|
// In the right position (the mouse)
|
|
menu.css({
|
|
"top": y + "px",
|
|
"left": x + "px"
|
|
});
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["51a461c33127132fca0884de56176443fbdb7d1b6404f440f36b4489afd06853"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["51a461c33127132fca0884de56176443fbdb7d1b6404f440f36b4489afd06853"] = "51a461c33127132fca0884de56176443fbdb7d1b6404f440f36b4489afd06853";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var sha;
|
|
(function (sha) {
|
|
/*
|
|
* [js-sha1]{@link https://github.com/emn178/js-sha1}
|
|
*
|
|
* @version 0.6.0
|
|
* @author Chen, Yi-Cyuan [emn178@gmail.com]
|
|
* @copyright Chen, Yi-Cyuan 2014-2017
|
|
* @license MIT
|
|
*/
|
|
/*jslint bitwise: true */
|
|
(function () {
|
|
'use strict';
|
|
let root = typeof window === 'object' ? window : {};
|
|
let NODE_JS = !root.JS_SHA1_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
|
|
if (NODE_JS) {
|
|
root = global;
|
|
}
|
|
let COMMON_JS = !root.JS_SHA1_NO_COMMON_JS && typeof module === 'object' && module.exports;
|
|
let AMD = typeof define === 'function' && define.amd;
|
|
let HEX_CHARS = '0123456789abcdef'.split('');
|
|
let EXTRA = [-2147483648, 8388608, 32768, 128];
|
|
let SHIFT = [24, 16, 8, 0];
|
|
let OUTPUT_TYPES = ['hex', 'array', 'digest', 'arrayBuffer'];
|
|
let blocks = [];
|
|
let createOutputMethod = function (outputType) {
|
|
return function (message) {
|
|
return new Sha1(true).update(message)[outputType]();
|
|
};
|
|
};
|
|
let createMethod = function () {
|
|
let method = createOutputMethod('hex');
|
|
if (NODE_JS) {
|
|
method = nodeWrap(method);
|
|
}
|
|
method.create = function () {
|
|
return new Sha1();
|
|
};
|
|
method.update = function (message) {
|
|
return method.create().update(message);
|
|
};
|
|
for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
|
|
var type = OUTPUT_TYPES[i];
|
|
method[type] = createOutputMethod(type);
|
|
}
|
|
return method;
|
|
};
|
|
var nodeWrap = function (method) {
|
|
var crypto = eval("require('crypto')");
|
|
var Buffer = eval("require('buffer').Buffer");
|
|
var nodeMethod = function (message) {
|
|
if (typeof message === 'string') {
|
|
return crypto.createHash('sha1').update(message, 'utf8').digest('hex');
|
|
}
|
|
else if (message.constructor === ArrayBuffer) {
|
|
message = new Uint8Array(message);
|
|
}
|
|
else if (message.length === undefined) {
|
|
return method(message);
|
|
}
|
|
return crypto.createHash('sha1').update(new Buffer(message)).digest('hex');
|
|
};
|
|
return nodeMethod;
|
|
};
|
|
function Sha1(sharedMemory) {
|
|
if (sharedMemory) {
|
|
blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] =
|
|
blocks[4] = blocks[5] = blocks[6] = blocks[7] =
|
|
blocks[8] = blocks[9] = blocks[10] = blocks[11] =
|
|
blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
|
|
this.blocks = blocks;
|
|
}
|
|
else {
|
|
this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
}
|
|
this.h0 = 0x67452301;
|
|
this.h1 = 0xEFCDAB89;
|
|
this.h2 = 0x98BADCFE;
|
|
this.h3 = 0x10325476;
|
|
this.h4 = 0xC3D2E1F0;
|
|
this.block = this.start = this.bytes = this.hBytes = 0;
|
|
this.finalized = this.hashed = false;
|
|
this.first = true;
|
|
}
|
|
Sha1.prototype.update = function (message) {
|
|
if (this.finalized) {
|
|
return;
|
|
}
|
|
var notString = typeof (message) !== 'string';
|
|
if (notString && message.constructor === root.ArrayBuffer) {
|
|
message = new Uint8Array(message);
|
|
}
|
|
var code, index = 0, i, length = message.length || 0, blocks = this.blocks;
|
|
while (index < length) {
|
|
if (this.hashed) {
|
|
this.hashed = false;
|
|
blocks[0] = this.block;
|
|
blocks[16] = blocks[1] = blocks[2] = blocks[3] =
|
|
blocks[4] = blocks[5] = blocks[6] = blocks[7] =
|
|
blocks[8] = blocks[9] = blocks[10] = blocks[11] =
|
|
blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
|
|
}
|
|
if (notString) {
|
|
for (i = this.start; index < length && i < 64; ++index) {
|
|
blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
|
|
}
|
|
}
|
|
else {
|
|
for (i = this.start; index < length && i < 64; ++index) {
|
|
code = message.charCodeAt(index);
|
|
if (code < 0x80) {
|
|
blocks[i >> 2] |= code << SHIFT[i++ & 3];
|
|
}
|
|
else if (code < 0x800) {
|
|
blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
|
|
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
|
|
}
|
|
else if (code < 0xd800 || code >= 0xe000) {
|
|
blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
|
|
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
|
|
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
|
|
}
|
|
else {
|
|
code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
|
|
blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
|
|
blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
|
|
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
|
|
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
|
|
}
|
|
}
|
|
}
|
|
this.lastByteIndex = i;
|
|
this.bytes += i - this.start;
|
|
if (i >= 64) {
|
|
this.block = blocks[16];
|
|
this.start = i - 64;
|
|
this.hash();
|
|
this.hashed = true;
|
|
}
|
|
else {
|
|
this.start = i;
|
|
}
|
|
}
|
|
if (this.bytes > 4294967295) {
|
|
this.hBytes += this.bytes / 4294967296 << 0;
|
|
this.bytes = this.bytes % 4294967296;
|
|
}
|
|
return this;
|
|
};
|
|
Sha1.prototype.finalize = function () {
|
|
if (this.finalized) {
|
|
return;
|
|
}
|
|
this.finalized = true;
|
|
var blocks = this.blocks, i = this.lastByteIndex;
|
|
blocks[16] = this.block;
|
|
blocks[i >> 2] |= EXTRA[i & 3];
|
|
this.block = blocks[16];
|
|
if (i >= 56) {
|
|
if (!this.hashed) {
|
|
this.hash();
|
|
}
|
|
blocks[0] = this.block;
|
|
blocks[16] = blocks[1] = blocks[2] = blocks[3] =
|
|
blocks[4] = blocks[5] = blocks[6] = blocks[7] =
|
|
blocks[8] = blocks[9] = blocks[10] = blocks[11] =
|
|
blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
|
|
}
|
|
blocks[14] = this.hBytes << 3 | this.bytes >>> 29;
|
|
blocks[15] = this.bytes << 3;
|
|
this.hash();
|
|
};
|
|
Sha1.prototype.hash = function () {
|
|
var a = this.h0, b = this.h1, c = this.h2, d = this.h3, e = this.h4;
|
|
var f, j, t, blocks = this.blocks;
|
|
for (j = 16; j < 80; ++j) {
|
|
t = blocks[j - 3] ^ blocks[j - 8] ^ blocks[j - 14] ^ blocks[j - 16];
|
|
blocks[j] = (t << 1) | (t >>> 31);
|
|
}
|
|
for (j = 0; j < 20; j += 5) {
|
|
f = (b & c) | ((~b) & d);
|
|
t = (a << 5) | (a >>> 27);
|
|
e = t + f + e + 1518500249 + blocks[j] << 0;
|
|
b = (b << 30) | (b >>> 2);
|
|
f = (a & b) | ((~a) & c);
|
|
t = (e << 5) | (e >>> 27);
|
|
d = t + f + d + 1518500249 + blocks[j + 1] << 0;
|
|
a = (a << 30) | (a >>> 2);
|
|
f = (e & a) | ((~e) & b);
|
|
t = (d << 5) | (d >>> 27);
|
|
c = t + f + c + 1518500249 + blocks[j + 2] << 0;
|
|
e = (e << 30) | (e >>> 2);
|
|
f = (d & e) | ((~d) & a);
|
|
t = (c << 5) | (c >>> 27);
|
|
b = t + f + b + 1518500249 + blocks[j + 3] << 0;
|
|
d = (d << 30) | (d >>> 2);
|
|
f = (c & d) | ((~c) & e);
|
|
t = (b << 5) | (b >>> 27);
|
|
a = t + f + a + 1518500249 + blocks[j + 4] << 0;
|
|
c = (c << 30) | (c >>> 2);
|
|
}
|
|
for (; j < 40; j += 5) {
|
|
f = b ^ c ^ d;
|
|
t = (a << 5) | (a >>> 27);
|
|
e = t + f + e + 1859775393 + blocks[j] << 0;
|
|
b = (b << 30) | (b >>> 2);
|
|
f = a ^ b ^ c;
|
|
t = (e << 5) | (e >>> 27);
|
|
d = t + f + d + 1859775393 + blocks[j + 1] << 0;
|
|
a = (a << 30) | (a >>> 2);
|
|
f = e ^ a ^ b;
|
|
t = (d << 5) | (d >>> 27);
|
|
c = t + f + c + 1859775393 + blocks[j + 2] << 0;
|
|
e = (e << 30) | (e >>> 2);
|
|
f = d ^ e ^ a;
|
|
t = (c << 5) | (c >>> 27);
|
|
b = t + f + b + 1859775393 + blocks[j + 3] << 0;
|
|
d = (d << 30) | (d >>> 2);
|
|
f = c ^ d ^ e;
|
|
t = (b << 5) | (b >>> 27);
|
|
a = t + f + a + 1859775393 + blocks[j + 4] << 0;
|
|
c = (c << 30) | (c >>> 2);
|
|
}
|
|
for (; j < 60; j += 5) {
|
|
f = (b & c) | (b & d) | (c & d);
|
|
t = (a << 5) | (a >>> 27);
|
|
e = t + f + e - 1894007588 + blocks[j] << 0;
|
|
b = (b << 30) | (b >>> 2);
|
|
f = (a & b) | (a & c) | (b & c);
|
|
t = (e << 5) | (e >>> 27);
|
|
d = t + f + d - 1894007588 + blocks[j + 1] << 0;
|
|
a = (a << 30) | (a >>> 2);
|
|
f = (e & a) | (e & b) | (a & b);
|
|
t = (d << 5) | (d >>> 27);
|
|
c = t + f + c - 1894007588 + blocks[j + 2] << 0;
|
|
e = (e << 30) | (e >>> 2);
|
|
f = (d & e) | (d & a) | (e & a);
|
|
t = (c << 5) | (c >>> 27);
|
|
b = t + f + b - 1894007588 + blocks[j + 3] << 0;
|
|
d = (d << 30) | (d >>> 2);
|
|
f = (c & d) | (c & e) | (d & e);
|
|
t = (b << 5) | (b >>> 27);
|
|
a = t + f + a - 1894007588 + blocks[j + 4] << 0;
|
|
c = (c << 30) | (c >>> 2);
|
|
}
|
|
for (; j < 80; j += 5) {
|
|
f = b ^ c ^ d;
|
|
t = (a << 5) | (a >>> 27);
|
|
e = t + f + e - 899497514 + blocks[j] << 0;
|
|
b = (b << 30) | (b >>> 2);
|
|
f = a ^ b ^ c;
|
|
t = (e << 5) | (e >>> 27);
|
|
d = t + f + d - 899497514 + blocks[j + 1] << 0;
|
|
a = (a << 30) | (a >>> 2);
|
|
f = e ^ a ^ b;
|
|
t = (d << 5) | (d >>> 27);
|
|
c = t + f + c - 899497514 + blocks[j + 2] << 0;
|
|
e = (e << 30) | (e >>> 2);
|
|
f = d ^ e ^ a;
|
|
t = (c << 5) | (c >>> 27);
|
|
b = t + f + b - 899497514 + blocks[j + 3] << 0;
|
|
d = (d << 30) | (d >>> 2);
|
|
f = c ^ d ^ e;
|
|
t = (b << 5) | (b >>> 27);
|
|
a = t + f + a - 899497514 + blocks[j + 4] << 0;
|
|
c = (c << 30) | (c >>> 2);
|
|
}
|
|
this.h0 = this.h0 + a << 0;
|
|
this.h1 = this.h1 + b << 0;
|
|
this.h2 = this.h2 + c << 0;
|
|
this.h3 = this.h3 + d << 0;
|
|
this.h4 = this.h4 + e << 0;
|
|
};
|
|
Sha1.prototype.hex = function () {
|
|
this.finalize();
|
|
var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4;
|
|
return HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] +
|
|
HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] +
|
|
HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] +
|
|
HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] +
|
|
HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] +
|
|
HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] +
|
|
HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] +
|
|
HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] +
|
|
HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] +
|
|
HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] +
|
|
HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] +
|
|
HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] +
|
|
HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F] +
|
|
HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] +
|
|
HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] +
|
|
HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] +
|
|
HEX_CHARS[(h4 >> 28) & 0x0F] + HEX_CHARS[(h4 >> 24) & 0x0F] +
|
|
HEX_CHARS[(h4 >> 20) & 0x0F] + HEX_CHARS[(h4 >> 16) & 0x0F] +
|
|
HEX_CHARS[(h4 >> 12) & 0x0F] + HEX_CHARS[(h4 >> 8) & 0x0F] +
|
|
HEX_CHARS[(h4 >> 4) & 0x0F] + HEX_CHARS[h4 & 0x0F];
|
|
};
|
|
Sha1.prototype.toString = Sha1.prototype.hex;
|
|
Sha1.prototype.digest = function () {
|
|
this.finalize();
|
|
var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3, h4 = this.h4;
|
|
return [
|
|
(h0 >> 24) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 8) & 0xFF, h0 & 0xFF,
|
|
(h1 >> 24) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 8) & 0xFF, h1 & 0xFF,
|
|
(h2 >> 24) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 8) & 0xFF, h2 & 0xFF,
|
|
(h3 >> 24) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 8) & 0xFF, h3 & 0xFF,
|
|
(h4 >> 24) & 0xFF, (h4 >> 16) & 0xFF, (h4 >> 8) & 0xFF, h4 & 0xFF
|
|
];
|
|
};
|
|
Sha1.prototype.array = Sha1.prototype.digest;
|
|
Sha1.prototype.arrayBuffer = function () {
|
|
this.finalize();
|
|
var buffer = new ArrayBuffer(20);
|
|
var dataView = new DataView(buffer);
|
|
dataView.setUint32(0, this.h0);
|
|
dataView.setUint32(4, this.h1);
|
|
dataView.setUint32(8, this.h2);
|
|
dataView.setUint32(12, this.h3);
|
|
dataView.setUint32(16, this.h4);
|
|
return buffer;
|
|
};
|
|
var exports = createMethod();
|
|
if (COMMON_JS) {
|
|
module.exports = exports;
|
|
}
|
|
else {
|
|
root._sha1 = exports;
|
|
if (AMD) {
|
|
define(function () {
|
|
return exports;
|
|
});
|
|
}
|
|
}
|
|
})();
|
|
function encode_text(buffer) {
|
|
if (window.TextEncoder) {
|
|
return new TextEncoder().encode(buffer).buffer;
|
|
}
|
|
let utf8 = unescape(encodeURIComponent(buffer));
|
|
let result = new Uint8Array(utf8.length);
|
|
for (let i = 0; i < utf8.length; i++) {
|
|
result[i] = utf8.charCodeAt(i);
|
|
}
|
|
return result.buffer;
|
|
}
|
|
sha.encode_text = encode_text;
|
|
function sha1(message) {
|
|
if (!(typeof (message) === "string" || message instanceof ArrayBuffer))
|
|
throw "Invalid type!";
|
|
let buffer = message instanceof ArrayBuffer ? message : encode_text(message);
|
|
if (!crypto || !crypto.subtle || !crypto.subtle.digest || /Edge/.test(navigator.userAgent))
|
|
return new Promise(resolve => {
|
|
resolve(_sha1.arrayBuffer(buffer));
|
|
});
|
|
else
|
|
return crypto.subtle.digest("SHA-1", buffer);
|
|
}
|
|
sha.sha1 = sha1;
|
|
})(sha || (sha = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["517d19bc00e3255e9af067c1436f53169327e8a5ef9fb42c1f675a97eda58851"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["517d19bc00e3255e9af067c1436f53169327e8a5ef9fb42c1f675a97eda58851"] = "517d19bc00e3255e9af067c1436f53169327e8a5ef9fb42c1f675a97eda58851";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../crypto/sha.ts" />
|
|
var helpers;
|
|
(function (helpers) {
|
|
function hashPassword(password) {
|
|
return new Promise((resolve, reject) => {
|
|
sha.sha1(password).then(result => {
|
|
resolve(btoa(String.fromCharCode.apply(null, new Uint8Array(result))));
|
|
});
|
|
});
|
|
}
|
|
helpers.hashPassword = hashPassword;
|
|
})(helpers || (helpers = {}));
|
|
class LaterPromise extends Promise {
|
|
constructor() {
|
|
super((resolve, reject) => { });
|
|
this._handle = new Promise((resolve, reject) => {
|
|
this._resolve = resolve;
|
|
this._reject = reject;
|
|
});
|
|
this._time = Date.now();
|
|
}
|
|
resolved(object) {
|
|
this._resolve(object);
|
|
}
|
|
rejected(reason) {
|
|
this._reject(reason);
|
|
}
|
|
function_rejected() {
|
|
return error => this.rejected(error);
|
|
}
|
|
time() { return this._time; }
|
|
/**
|
|
* Attaches callbacks for the resolution and/or rejection of the Promise.
|
|
* @param onfulfilled The callback to execute when the Promise is resolved.
|
|
* @param onrejected The callback to execute when the Promise is rejected.
|
|
* @returns A Promise for the completion of which ever callback is executed.
|
|
*/
|
|
then(onfulfilled, onrejected) {
|
|
return this._handle.then(onfulfilled, onrejected);
|
|
}
|
|
/**
|
|
* Attaches a callback for only the rejection of the Promise.
|
|
* @param onrejected The callback to execute when the Promise is rejected.
|
|
* @returns A Promise for the completion of the callback.
|
|
*/
|
|
catch(onrejected) {
|
|
return this._handle.then(onrejected);
|
|
}
|
|
}
|
|
const copy_to_clipboard = str => {
|
|
const el = document.createElement('textarea');
|
|
el.value = str;
|
|
el.setAttribute('readonly', '');
|
|
el.style.position = 'absolute';
|
|
el.style.left = '-9999px';
|
|
document.body.appendChild(el);
|
|
const selected = document.getSelection().rangeCount > 0
|
|
? document.getSelection().getRangeAt(0)
|
|
: false;
|
|
el.select();
|
|
document.execCommand('copy');
|
|
document.body.removeChild(el);
|
|
if (selected) {
|
|
document.getSelection().removeAllRanges();
|
|
document.getSelection().addRange(selected);
|
|
}
|
|
};
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["87b19fc0c7bbf638de93ca469843e03db19abbee1f2beffc648540779fc5ffe7"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["87b19fc0c7bbf638de93ca469843e03db19abbee1f2beffc648540779fc5ffe7"] = "87b19fc0c7bbf638de93ca469843e03db19abbee1f2beffc648540779fc5ffe7";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "aj1gtLqv", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (237,36)" }, { name: "teLhTVSa", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (244,36)" }, { name: "J0dpFOc2", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (251,36)" }, { name: "AJW_7Ysi", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (258,36)" }, { name: "WQPwyWBa", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (265,36)" }, { name: "fYGIIiFf", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (430,23)" }, { name: "xjDLtc_W", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (437,23)" }, { name: "fK8ljRBd", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (444,59)" }, { name: "Yzzhr43h", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (471,23)" }, { name: "NCpTBV8E", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (483,23)" }, { name: "CAKzmQnK", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (486,41)" }, { name: "Xy9l9iJX", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (486,73)" }, { name: "cW_P2hlA", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (492,42)" }, { name: "okfaF6u3", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (492,98)" }, { name: "vsYTC19a", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (500,23)" }, { name: "INSAXHWq", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (506,23)" }, { name: "F8DyGDHM", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (531,25)" }, { name: "fTdJPDs3", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (554,25)" }, { name: "g1tVT87U", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (585,59)" }, { name: "oU_VGnSx", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (592,21)" }, { name: "bLb2uTaE", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (601,82)" }, { name: "t4jDfLgx", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (608,23)" }, { name: "DbnOB3N5", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (688,30)" }, { name: "vKeWNwib", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/channel.ts (688,54)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="view.ts" />
|
|
/// <reference path="../utils/helpers.ts" />
|
|
var ChannelType;
|
|
(function (ChannelType) {
|
|
ChannelType[ChannelType["PERMANENT"] = 0] = "PERMANENT";
|
|
ChannelType[ChannelType["SEMI_PERMANENT"] = 1] = "SEMI_PERMANENT";
|
|
ChannelType[ChannelType["TEMPORARY"] = 2] = "TEMPORARY";
|
|
})(ChannelType || (ChannelType = {}));
|
|
(function (ChannelType) {
|
|
function normalize(mode) {
|
|
let value = ChannelType[mode];
|
|
value = value.toLowerCase();
|
|
return value[0].toUpperCase() + value.substr(1);
|
|
}
|
|
ChannelType.normalize = normalize;
|
|
})(ChannelType || (ChannelType = {}));
|
|
class ChannelProperties {
|
|
constructor() {
|
|
this.channel_order = 0;
|
|
this.channel_name = "";
|
|
this.channel_name_phonetic = "";
|
|
this.channel_topic = "";
|
|
this.channel_password = "";
|
|
this.channel_codec = 4;
|
|
this.channel_codec_quality = 0;
|
|
this.channel_codec_is_unencrypted = false;
|
|
this.channel_maxclients = -1;
|
|
this.channel_maxfamilyclients = -1;
|
|
this.channel_needed_talk_power = 1;
|
|
this.channel_flag_permanent = false;
|
|
this.channel_flag_semi_permanent = false;
|
|
this.channel_flag_default = false;
|
|
this.channel_flag_password = false;
|
|
this.channel_flag_maxclients_unlimited = false;
|
|
this.channel_flag_maxfamilyclients_inherited = false;
|
|
this.channel_flag_maxfamilyclients_unlimited = false;
|
|
this.channel_icon_id = 0;
|
|
this.channel_delete_delay = 0;
|
|
//Only after request
|
|
this.channel_description = "";
|
|
}
|
|
}
|
|
class ChannelEntry {
|
|
constructor(channelId, channelName, parent = null) {
|
|
this.properties = new ChannelProperties();
|
|
this._channel_name_alignment = undefined;
|
|
this._channel_name_formatted = undefined;
|
|
this._family_index = 0;
|
|
this._cached_channel_description = undefined;
|
|
this._cached_channel_description_promise = undefined;
|
|
this._cached_channel_description_promise_resolve = undefined;
|
|
this._cached_channel_description_promise_reject = undefined;
|
|
this.properties = new ChannelProperties();
|
|
this.channelId = channelId;
|
|
this.properties.channel_name = channelName;
|
|
this.parent = parent;
|
|
this.channelTree = null;
|
|
this.initializeTag();
|
|
this.__updateChannelName();
|
|
}
|
|
channelName() {
|
|
return this.properties.channel_name;
|
|
}
|
|
formattedChannelName() {
|
|
return this._channel_name_formatted || this.properties.channel_name;
|
|
}
|
|
getChannelDescription() {
|
|
if (this._cached_channel_description)
|
|
return new Promise(resolve => resolve(this._cached_channel_description));
|
|
if (this._cached_channel_description_promise)
|
|
return this._cached_channel_description_promise;
|
|
this.channelTree.client.serverConnection.send_command("channelgetdescription", { cid: this.channelId }).catch(error => {
|
|
this._cached_channel_description_promise_reject(error);
|
|
});
|
|
return this._cached_channel_description_promise = new Promise((resolve, reject) => {
|
|
this._cached_channel_description_promise_resolve = resolve;
|
|
this._cached_channel_description_promise_reject = reject;
|
|
});
|
|
}
|
|
parent_channel() { return this.parent; }
|
|
hasParent() { return this.parent != null; }
|
|
getChannelId() { return this.channelId; }
|
|
children(deep = false) {
|
|
const result = [];
|
|
if (this.channelTree == null)
|
|
return [];
|
|
const self = this;
|
|
this.channelTree.channels.forEach(function (entry) {
|
|
let current = entry;
|
|
if (deep) {
|
|
while (current) {
|
|
if (current.parent_channel() == self) {
|
|
result.push(entry);
|
|
break;
|
|
}
|
|
current = current.parent_channel();
|
|
}
|
|
}
|
|
else if (current.parent_channel() == self)
|
|
result.push(entry);
|
|
});
|
|
return result;
|
|
}
|
|
clients(deep = false) {
|
|
const result = [];
|
|
if (this.channelTree == null)
|
|
return [];
|
|
const self = this;
|
|
this.channelTree.clients.forEach(function (entry) {
|
|
let current = entry.currentChannel();
|
|
if (deep) {
|
|
while (current) {
|
|
if (current == self) {
|
|
result.push(entry);
|
|
break;
|
|
}
|
|
current = current.parent_channel();
|
|
}
|
|
}
|
|
else if (current == self)
|
|
result.push(entry);
|
|
});
|
|
return result;
|
|
}
|
|
clients_ordered() {
|
|
const clients = this.clients(false);
|
|
clients.sort((a, b) => {
|
|
if (a.properties.client_talk_power < b.properties.client_talk_power)
|
|
return 1;
|
|
if (a.properties.client_talk_power > b.properties.client_talk_power)
|
|
return -1;
|
|
if (a.properties.client_nickname > b.properties.client_nickname)
|
|
return 1;
|
|
if (a.properties.client_nickname < b.properties.client_nickname)
|
|
return -1;
|
|
return 0;
|
|
});
|
|
return clients;
|
|
}
|
|
update_family_index(enforce) {
|
|
const current_index = this._family_index;
|
|
const new_index = this.calculate_family_index(true);
|
|
if (current_index == new_index && !enforce)
|
|
return;
|
|
this._tag_channel.css("z-index", this._family_index);
|
|
this._tag_channel.css("padding-left", (this._family_index + 1) * 16 + "px");
|
|
}
|
|
calculate_family_index(enforce_recalculate = false) {
|
|
if (this._family_index !== undefined && !enforce_recalculate)
|
|
return this._family_index;
|
|
this._family_index = 0;
|
|
let channel = this.parent_channel();
|
|
while (channel) {
|
|
this._family_index++;
|
|
channel = channel.parent_channel();
|
|
}
|
|
return this._family_index;
|
|
}
|
|
initializeTag() {
|
|
const tag_channel = $.spawn("div").addClass("tree-entry channel");
|
|
{
|
|
const container_entry = $.spawn("div").addClass("container-channel");
|
|
container_entry.attr("channel-id", this.channelId);
|
|
container_entry.addClass(this._channel_name_alignment);
|
|
/* channel icon (type) */
|
|
{
|
|
container_entry.append($.spawn("div")
|
|
.addClass("show-channel-normal-only channel-type icon client-channel_green_subscribed"));
|
|
}
|
|
/* channel name */
|
|
{
|
|
container_entry.append($.spawn("div")
|
|
.addClass("container-channel-name")
|
|
.append($.spawn("a")
|
|
.addClass("channel-name")
|
|
.text(this.channelName())));
|
|
}
|
|
/* all icons (last element) */
|
|
{
|
|
//Icons
|
|
let container_icons = $.spawn("span").addClass("icons");
|
|
//Default icon (5)
|
|
container_icons.append($.spawn("div")
|
|
.addClass("show-channel-normal-only icon_entry icon_default icon client-channel_default")
|
|
.attr("title", _translations.aj1gtLqv || (_translations.aj1gtLqv = tr("Default channel"))));
|
|
//Password icon (4)
|
|
container_icons.append($.spawn("div")
|
|
.addClass("show-channel-normal-only icon_entry icon_password icon client-register")
|
|
.attr("title", _translations.teLhTVSa || (_translations.teLhTVSa = tr("The channel is password protected"))));
|
|
//Music icon (3)
|
|
container_icons.append($.spawn("div")
|
|
.addClass("show-channel-normal-only icon_entry icon_music icon client-music")
|
|
.attr("title", _translations.J0dpFOc2 || (_translations.J0dpFOc2 = tr("Music quality"))));
|
|
//Channel moderated (2)
|
|
container_icons.append($.spawn("div")
|
|
.addClass("show-channel-normal-only icon_entry icon_moderated icon client-moderated")
|
|
.attr("title", _translations.AJW_7Ysi || (_translations.AJW_7Ysi = tr("Channel is moderated"))));
|
|
//Channel Icon (1)
|
|
container_icons.append($.spawn("div")
|
|
.addClass("show-channel-normal-only icon_entry channel_icon")
|
|
.attr("title", _translations.WQPwyWBa || (_translations.WQPwyWBa = tr("Channel icon"))));
|
|
//Default no sound (0)
|
|
let container = $.spawn("div")
|
|
.css("position", "relative")
|
|
.addClass("icon_no_sound");
|
|
let noSound = $.spawn("div")
|
|
.addClass("icon_entry icon client-conflict-icon")
|
|
.attr("title", "You don't support the channel codec");
|
|
let bg = $.spawn("div")
|
|
.width(10)
|
|
.height(14)
|
|
.css("background", "red")
|
|
.css("position", "absolute")
|
|
.css("top", "1px")
|
|
.css("left", "3px")
|
|
.css("z-index", "-1");
|
|
bg.appendTo(container);
|
|
noSound.appendTo(container);
|
|
container_icons.append(container);
|
|
container_icons.appendTo(container_entry);
|
|
}
|
|
tag_channel.append(this._tag_channel = container_entry);
|
|
this.update_family_index(true);
|
|
}
|
|
{
|
|
const container_client = $.spawn("div").addClass("container-clients");
|
|
tag_channel.append(this._tag_clients = container_client);
|
|
}
|
|
{
|
|
const container_children = $.spawn("div").addClass("container-children");
|
|
tag_channel.append(this._tag_siblings = container_children);
|
|
}
|
|
/*
|
|
setInterval(() => {
|
|
let color = (Math.random() * 10000000).toString(16).substr(0, 6);
|
|
bg.css("background", "#" + color);
|
|
}, 150);
|
|
*/
|
|
this._tag_root = tag_channel;
|
|
}
|
|
rootTag() {
|
|
return this._tag_root;
|
|
}
|
|
channelTag() {
|
|
return this._tag_channel;
|
|
}
|
|
siblingTag() {
|
|
return this._tag_siblings;
|
|
}
|
|
clientTag() {
|
|
return this._tag_clients;
|
|
}
|
|
reorderClients() {
|
|
let clients = this.clients();
|
|
if (clients.length > 1) {
|
|
clients.sort((a, b) => {
|
|
if (a.properties.client_talk_power < b.properties.client_talk_power)
|
|
return 1;
|
|
if (a.properties.client_talk_power > b.properties.client_talk_power)
|
|
return -1;
|
|
if (a.properties.client_nickname > b.properties.client_nickname)
|
|
return 1;
|
|
if (a.properties.client_nickname < b.properties.client_nickname)
|
|
return -1;
|
|
return 0;
|
|
});
|
|
clients.reverse();
|
|
for (let index = 0; index + 1 < clients.length; index++)
|
|
clients[index].tag.before(clients[index + 1].tag);
|
|
for (let client of clients) {
|
|
console.log("- %i %s", client.properties.client_talk_power, client.properties.client_nickname);
|
|
}
|
|
}
|
|
}
|
|
initializeListener() {
|
|
const _this = this;
|
|
this.channelTag().click(function () {
|
|
_this.channelTree.onSelect(_this);
|
|
});
|
|
this.channelTag().dblclick(() => {
|
|
if ($.isArray(this.channelTree.currently_selected)) { //Multiselect
|
|
return;
|
|
}
|
|
this.joinChannel();
|
|
});
|
|
if (!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
|
|
this.channelTag().on("contextmenu", (event) => {
|
|
event.preventDefault();
|
|
if ($.isArray(this.channelTree.currently_selected)) { //Multiselect
|
|
(this.channelTree.currently_selected_context_callback || ((_) => null))(event);
|
|
return;
|
|
}
|
|
_this.channelTree.onSelect(_this, true);
|
|
_this.showContextMenu(event.pageX, event.pageY, () => {
|
|
_this.channelTree.onSelect(undefined, true);
|
|
});
|
|
});
|
|
}
|
|
}
|
|
showContextMenu(x, y, on_close = undefined) {
|
|
let channelCreate = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_TEMPORARY).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_SEMI_PERMANENT).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_PERMANENT).granted(1);
|
|
let channelModify = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_DEFAULT).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_PERMANENT).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_SEMI_PERMANENT).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_TEMPORARY).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_NAME).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_TOPIC).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_DESCRIPTION).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_PASSWORD).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_CODEC).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_CODEC_QUALITY).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_CODEC_LATENCY_FACTOR).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAXCLIENTS).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAXFAMILYCLIENTS).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_SORTORDER).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_NEEDED_TALK_POWER).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_CODEC_ENCRYPTED).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_TEMP_DELETE_DELAY).granted(1) ||
|
|
this.channelTree.client.permissions.neededPermission(PermissionType.B_ICON_MANAGE).granted(1);
|
|
let flagDelete = true;
|
|
if (this.clients(true).length > 0)
|
|
flagDelete = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_DELETE_FLAG_FORCE).granted(1);
|
|
if (flagDelete) {
|
|
if (this.properties.channel_flag_permanent)
|
|
flagDelete = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_DELETE_PERMANENT).granted(1);
|
|
else if (this.properties.channel_flag_semi_permanent)
|
|
flagDelete = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_DELETE_PERMANENT).granted(1);
|
|
else
|
|
flagDelete = this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_DELETE_TEMPORARY).granted(1);
|
|
}
|
|
spawn_context_menu(x, y, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-channel_switch",
|
|
name: _translations.fYGIIiFf || (_translations.fYGIIiFf = tr("<b>Switch to channel</b>")),
|
|
callback: () => this.joinChannel()
|
|
}, MenuEntry.HR(), {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-channel_edit",
|
|
name: _translations.xjDLtc_W || (_translations.xjDLtc_W = tr("Edit channel")),
|
|
invalidPermission: !channelModify,
|
|
callback: () => {
|
|
Modals.createChannelModal(this, undefined, this.channelTree.client.permissions, (changes, permissions) => {
|
|
if (changes) {
|
|
changes["cid"] = this.channelId;
|
|
this.channelTree.client.serverConnection.send_command("channeledit", changes);
|
|
log.info(LogCategory.CHANNEL, _translations.fK8ljRBd || (_translations.fK8ljRBd = tr("Changed channel properties of channel %s: %o")), this.channelName(), changes);
|
|
}
|
|
if (permissions && permissions.length > 0) {
|
|
let perms = [];
|
|
for (let perm of permissions) {
|
|
perms.push({
|
|
permvalue: perm.value,
|
|
permnegated: false,
|
|
permskip: false,
|
|
permid: perm.type.id
|
|
});
|
|
}
|
|
perms[0]["cid"] = this.channelId;
|
|
this.channelTree.client.serverConnection.send_command("channeladdperm", perms, {
|
|
flagset: ["continueonerror"]
|
|
}).then(() => {
|
|
sound.play(Sound.CHANNEL_EDITED_SELF);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-channel_delete",
|
|
name: _translations.Yzzhr43h || (_translations.Yzzhr43h = tr("Delete channel")),
|
|
invalidPermission: !flagDelete,
|
|
callback: () => {
|
|
this.channelTree.client.serverConnection.send_command("channeldelete", { cid: this.channelId }).then(() => {
|
|
sound.play(Sound.CHANNEL_DELETED);
|
|
});
|
|
}
|
|
}, MenuEntry.HR(), {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-addon-collection",
|
|
name: _translations.NCpTBV8E || (_translations.NCpTBV8E = tr("Create music bot")),
|
|
callback: () => {
|
|
this.channelTree.client.serverConnection.send_command("musicbotcreate", { cid: this.channelId }).then(() => {
|
|
createInfoModal(_translations.CAKzmQnK || (_translations.CAKzmQnK = tr("Bot successfully created")), _translations.Xy9l9iJX || (_translations.Xy9l9iJX = tr("Bot has been successfully created."))).open();
|
|
}).catch(error => {
|
|
if (error instanceof CommandResult) {
|
|
error = error.extra_message || error.message;
|
|
}
|
|
createErrorModal(_translations.cW_P2hlA || (_translations.cW_P2hlA = tr("Failed to create bot")), MessageHelper.formatMessage(_translations.okfaF6u3 || (_translations.okfaF6u3 = tr("Failed to create the music bot:<br>{0}")), error)).open();
|
|
});
|
|
}
|
|
}, MenuEntry.HR(), {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-channel_create_sub",
|
|
name: _translations.vsYTC19a || (_translations.vsYTC19a = tr("Create sub channel")),
|
|
invalidPermission: !(channelCreate && this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_CHILD).granted(1)),
|
|
callback: () => this.channelTree.spawnCreateChannel(this)
|
|
}, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-channel_create",
|
|
name: _translations.INSAXHWq || (_translations.INSAXHWq = tr("Create channel")),
|
|
invalidPermission: !channelCreate,
|
|
callback: () => this.channelTree.spawnCreateChannel()
|
|
}, MenuEntry.CLOSE(on_close));
|
|
}
|
|
handle_frame_resized() {
|
|
this.__updateChannelName();
|
|
}
|
|
__updateChannelName() {
|
|
this._channel_name_formatted = undefined;
|
|
parseType: if (this.parent_channel() == null && this.properties.channel_name.charAt(0) == '[') {
|
|
let end = this.properties.channel_name.indexOf(']');
|
|
if (end == -1)
|
|
break parseType;
|
|
let options = this.properties.channel_name.substr(1, end - 1);
|
|
if (options.indexOf("spacer") == -1)
|
|
break parseType;
|
|
options = options.substr(0, options.indexOf("spacer"));
|
|
console.log(_translations.F8DyGDHM || (_translations.F8DyGDHM = tr("Channel options: '%o'")), options);
|
|
if (options.length == 0)
|
|
options = "align-left";
|
|
else if (options.length > 1)
|
|
options = options[0];
|
|
switch (options) {
|
|
case "r":
|
|
this._channel_name_alignment = "align-right";
|
|
break;
|
|
case "l":
|
|
this._channel_name_alignment = "align-left";
|
|
break;
|
|
case "c":
|
|
this._channel_name_alignment = "align-center";
|
|
break;
|
|
case "*":
|
|
this._channel_name_alignment = "align-repetitive";
|
|
break;
|
|
default:
|
|
this._channel_name_alignment = undefined;
|
|
break parseType;
|
|
}
|
|
this._channel_name_formatted = this.properties.channel_name.substr(end + 1) || "";
|
|
console.log(_translations.fTdJPDs3 || (_translations.fTdJPDs3 = tr("Got formated channel name: %o")), this._channel_name_formatted);
|
|
}
|
|
this._tag_channel.find(".show-channel-normal-only").toggleClass("channel-normal", this._channel_name_formatted === undefined);
|
|
const tag_container_name = this._tag_channel.find(".container-channel-name");
|
|
tag_container_name.removeClass(ChannelEntry.NAME_ALIGNMENTS.join(" "));
|
|
const tag_name = tag_container_name.find(".channel-name");
|
|
tag_name.text(this._channel_name_formatted === undefined ? this.properties.channel_name : this._channel_name_formatted);
|
|
if (this._channel_name_formatted !== undefined) {
|
|
tag_container_name.addClass(this._channel_name_alignment);
|
|
if (this._channel_name_alignment == "align-repetitive") {
|
|
if (tag_name.parent().width() != 0) {
|
|
let lastSuccess = "";
|
|
let index = 6;
|
|
let name = this._channel_name_formatted;
|
|
if (name.length < 1)
|
|
throw "invalid name!";
|
|
while (index-- > 0)
|
|
name = name + name;
|
|
tag_name.text(name);
|
|
do {
|
|
tag_name.text(name = name + name);
|
|
if (name.length > 1024 * 8)
|
|
index = 63;
|
|
} while (tag_name.parent().width() >= tag_name.width() && ++index < 64);
|
|
if (index == 64)
|
|
console.warn(LogCategory.CHANNEL, _translations.g1tVT87U || (_translations.g1tVT87U = tr("Repeating spacer took too much repeats!")));
|
|
if (lastSuccess.length > 0) {
|
|
tag_name.text(lastSuccess);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
console.log(_translations.oU_VGnSx || (_translations.oU_VGnSx = tr("Align: %s")), this._channel_name_alignment);
|
|
}
|
|
recalculate_repetitive_name() {
|
|
if (this._channel_name_alignment == "align-repetitive")
|
|
this.__updateChannelName();
|
|
}
|
|
updateVariables(...variables) {
|
|
let group = log.group(log.LogType.DEBUG, LogCategory.CHANNEL_PROPERTIES, _translations.bLb2uTaE || (_translations.bLb2uTaE = tr("Update properties (%i) of %s (%i)")), variables.length, this.channelName(), this.getChannelId());
|
|
for (let variable of variables) {
|
|
let key = variable.key;
|
|
let value = variable.value;
|
|
JSON.map_field_to(this.properties, value, variable.key);
|
|
group.log(_translations.t4jDfLgx || (_translations.t4jDfLgx = tr("Updating property %s = '%s' -> %o")), key, value, this.properties[key]);
|
|
if (key == "channel_name") {
|
|
this.__updateChannelName();
|
|
}
|
|
else if (key == "channel_order") {
|
|
let order = this.channelTree.findChannel(this.properties.channel_order);
|
|
this.channelTree.moveChannel(this, order, this.parent);
|
|
}
|
|
else if (key == "channel_icon_id") {
|
|
let tag = this.channelTag().find(".icons .channel_icon");
|
|
(this.properties.channel_icon_id > 0 ? $.fn.show : $.fn.hide).apply(tag);
|
|
if (this.properties.channel_icon_id > 0) {
|
|
tag.children().detach();
|
|
this.channelTree.client.fileManager.icons.generateTag(this.properties.channel_icon_id).appendTo(tag);
|
|
}
|
|
}
|
|
else if (key == "channel_codec") {
|
|
(this.properties.channel_codec == 5 || this.properties.channel_codec == 3 ? $.fn.show : $.fn.hide).apply(this.channelTag().find(".icons .icon_music"));
|
|
(this.channelTree.client.voiceConnection.codecSupported(this.properties.channel_codec) ? $.fn.hide : $.fn.show).apply(this.channelTag().find(".icons .icon_no_sound"));
|
|
}
|
|
else if (key == "channel_flag_default") {
|
|
(this.properties.channel_flag_default ? $.fn.show : $.fn.hide).apply(this.channelTag().find(".icons .icon_default"));
|
|
}
|
|
else if (key == "channel_flag_password")
|
|
(this.properties.channel_flag_password ? $.fn.show : $.fn.hide).apply(this.channelTag().find(".icons .icon_password"));
|
|
else if (key == "channel_needed_talk_power")
|
|
(this.properties.channel_needed_talk_power > 0 ? $.fn.show : $.fn.hide).apply(this.channelTag().find(".icons .icon_moderated"));
|
|
else if (key == "channel_description") {
|
|
this._cached_channel_description = undefined;
|
|
if (this._cached_channel_description_promise_resolve)
|
|
this._cached_channel_description_promise_resolve(value);
|
|
this._cached_channel_description_promise = undefined;
|
|
this._cached_channel_description_promise_resolve = undefined;
|
|
this._cached_channel_description_promise_reject = undefined;
|
|
}
|
|
if (key == "channel_maxclients" || key == "channel_maxfamilyclients" || key == "channel_flag_private" || key == "channel_flag_password")
|
|
this.updateChannelTypeIcon();
|
|
}
|
|
group.end();
|
|
}
|
|
updateChannelTypeIcon() {
|
|
let tag = this.channelTag().find(".channel-type");
|
|
tag.removeAttr('class');
|
|
tag.addClass("show-channel-normal-only channel-type icon");
|
|
if (this._channel_name_formatted === undefined)
|
|
tag.addClass("channel-normal");
|
|
let type;
|
|
if (this.properties.channel_flag_password == true && !this._cachedPassword)
|
|
type = "yellow";
|
|
else if ((!this.properties.channel_flag_maxclients_unlimited && this.clients().length >= this.properties.channel_maxclients) ||
|
|
(!this.properties.channel_flag_maxfamilyclients_unlimited && this.properties.channel_maxfamilyclients >= 0 && this.clients(true).length >= this.properties.channel_maxfamilyclients))
|
|
type = "red";
|
|
else
|
|
type = "green";
|
|
tag.addClass("client-channel_" + type + "_subscribed");
|
|
}
|
|
generate_bbcode() {
|
|
return "[url=channel://" + this.channelId + "/" + encodeURIComponent(this.properties.channel_name) + "]" + this.formattedChannelName() + "[/url]";
|
|
}
|
|
generate_tag(braces = false) {
|
|
return $(htmltags.generate_channel({
|
|
channel_name: this.properties.channel_name,
|
|
channel_id: this.channelId,
|
|
add_braces: braces
|
|
}));
|
|
}
|
|
channelType() {
|
|
if (this.properties.channel_flag_permanent == true)
|
|
return ChannelType.PERMANENT;
|
|
if (this.properties.channel_flag_semi_permanent == true)
|
|
return ChannelType.SEMI_PERMANENT;
|
|
return ChannelType.TEMPORARY;
|
|
}
|
|
joinChannel() {
|
|
if (this.properties.channel_flag_password == true &&
|
|
!this._cachedPassword &&
|
|
!this.channelTree.client.permissions.neededPermission(PermissionType.B_CHANNEL_JOIN_IGNORE_PASSWORD).granted(1)) {
|
|
createInputModal(_translations.DbnOB3N5 || (_translations.DbnOB3N5 = tr("Channel password")), _translations.vKeWNwib || (_translations.vKeWNwib = tr("Channel password:")), () => true, text => {
|
|
if (typeof (text) == typeof (true))
|
|
return;
|
|
helpers.hashPassword(text).then(result => {
|
|
this._cachedPassword = result;
|
|
this.joinChannel();
|
|
this.updateChannelTypeIcon();
|
|
});
|
|
}).open();
|
|
}
|
|
else if (this.channelTree.client.getClient().currentChannel() != this)
|
|
this.channelTree.client.getServerConnection().command_helper.joinChannel(this, this._cachedPassword).then(() => {
|
|
sound.play(Sound.CHANNEL_JOINED);
|
|
}).catch(error => {
|
|
if (error instanceof CommandResult) {
|
|
if (error.id == 781) { //Invalid password
|
|
this._cachedPassword = undefined;
|
|
this.updateChannelTypeIcon();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
ChannelEntry.NAME_ALIGNMENTS = ["align-left", "align-center", "align-right", "align-repetitive"];
|
|
//Global functions
|
|
function chat_channel_contextmenu(_element, event) {
|
|
event.preventDefault();
|
|
let element = $(_element);
|
|
let chid = Number.parseInt(element.attr("channelId"));
|
|
let channel = globalClient.channelTree.findChannel(chid);
|
|
if (!channel) {
|
|
//TODO
|
|
return;
|
|
}
|
|
channel.showContextMenu(event.pageX, event.pageY);
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["fe89711a43b24f07f1aeaf001e66406e4c8ea4bc71ed5c5f1cac1bda261407b6"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["fe89711a43b24f07f1aeaf001e66406e4c8ea4bc71ed5c5f1cac1bda261407b6"] = "fe89711a43b24f07f1aeaf001e66406e4c8ea4bc71ed5c5f1cac1bda261407b6";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "ZLhA9e2l", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalChangeVolume.ts (10,29)" }, { name: "x8QJcf2k", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalChangeVolume.ts (31,34)" }, { name: "qQQ55JPY", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalChangeVolume.ts (39,35)" }, { name: "RvdOD61Y", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalChangeVolume.ts (48,31)" }, { name: "as7HKx_Z", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalChangeVolume.ts (77,29)" }, { name: "i4uIKqph", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalChangeVolume.ts (98,39)" }, { name: "bIx1IofH", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalChangeVolume.ts (107,39)" }, { name: "n5WtCyPz", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalChangeVolume.ts (115,40)" }, { name: "r4iXq8Au", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalChangeVolume.ts (123,36)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../utils/modal.ts" />
|
|
/// <reference path="../../proto.ts" />
|
|
var Modals;
|
|
(function (Modals) {
|
|
function spawnChangeVolume(current, callback) {
|
|
let updateCallback;
|
|
const connectModal = createModal({
|
|
header: function () {
|
|
let header = $.spawn("div");
|
|
header.text(_translations.ZLhA9e2l || (_translations.ZLhA9e2l = tr("Change volume")));
|
|
return header;
|
|
},
|
|
body: function () {
|
|
let tag = $("#tmpl_change_volume").renderTag({
|
|
max_volume: 200
|
|
});
|
|
tag.find(".volume_slider").on("change", _ => updateCallback(tag.find(".volume_slider").val()));
|
|
tag.find(".volume_slider").on("input", _ => updateCallback(tag.find(".volume_slider").val()));
|
|
//connect_address
|
|
return tag;
|
|
},
|
|
footer: function () {
|
|
let tag = $.spawn("div");
|
|
tag.css("text-align", "right");
|
|
tag.css("margin-top", "3px");
|
|
tag.css("margin-bottom", "6px");
|
|
tag.addClass("modal-button-group");
|
|
let buttonReset = $.spawn("button");
|
|
buttonReset.text(_translations.x8QJcf2k || (_translations.x8QJcf2k = tr("Reset")));
|
|
buttonReset.on("click", function () {
|
|
updateCallback(100);
|
|
});
|
|
tag.append(buttonReset);
|
|
let buttonCancel = $.spawn("button");
|
|
buttonCancel.text(_translations.qQQ55JPY || (_translations.qQQ55JPY = tr("Cancel")));
|
|
buttonCancel.on("click", function () {
|
|
updateCallback(current * 100);
|
|
connectModal.close();
|
|
});
|
|
tag.append(buttonCancel);
|
|
let buttonOk = $.spawn("button");
|
|
buttonOk.text(_translations.RvdOD61Y || (_translations.RvdOD61Y = tr("OK")));
|
|
buttonOk.on("click", function () {
|
|
connectModal.close();
|
|
});
|
|
tag.append(buttonOk);
|
|
return tag;
|
|
},
|
|
width: 600
|
|
});
|
|
updateCallback = value => {
|
|
connectModal.htmlTag.find(".volume_slider").val(value);
|
|
let display = connectModal.htmlTag.find(".display_volume");
|
|
let number = (value - 100);
|
|
display.html((number == 0 ? "±" : number > 0 ? "+" : "") + number + " %");
|
|
callback(value / 100);
|
|
};
|
|
connectModal.open();
|
|
updateCallback(current * 100);
|
|
}
|
|
Modals.spawnChangeVolume = spawnChangeVolume;
|
|
/* Units are between 0 and 1 */
|
|
function spawnChangeRemoteVolume(current, max_value, callback) {
|
|
let update_volume;
|
|
let current_value = current; /* between 0 and 100! */
|
|
const modal = createModal({
|
|
header: function () {
|
|
let header = $.spawn("div");
|
|
header.text(_translations.as7HKx_Z || (_translations.as7HKx_Z = tr("Change volume")));
|
|
return header;
|
|
},
|
|
body: function () {
|
|
let tag = $("#tmpl_change_volume").renderTag({
|
|
max_volume: Math.ceil(max_value * 100)
|
|
});
|
|
tag.find(".volume_slider").on("change", _ => update_volume(tag.find(".volume_slider").val()));
|
|
tag.find(".volume_slider").on("input", _ => update_volume(tag.find(".volume_slider").val()));
|
|
//connect_address
|
|
return tag;
|
|
},
|
|
footer: function () {
|
|
let tag = $.spawn("div");
|
|
tag.css("text-align", "right");
|
|
tag.css("margin-top", "3px");
|
|
tag.css("margin-bottom", "6px");
|
|
tag.addClass("modal-button-group");
|
|
{
|
|
let button_apply = $.spawn("button");
|
|
button_apply.text(_translations.i4uIKqph || (_translations.i4uIKqph = tr("Apply")));
|
|
button_apply.on("click", () => {
|
|
callback(current_value / 100);
|
|
});
|
|
tag.append(button_apply);
|
|
}
|
|
{
|
|
let button_reset = $.spawn("button");
|
|
button_reset.text(_translations.bIx1IofH || (_translations.bIx1IofH = tr("Reset")));
|
|
button_reset.on("click", () => update_volume(max_value * 100));
|
|
tag.append(button_reset);
|
|
}
|
|
{
|
|
let button_cancel = $.spawn("button");
|
|
button_cancel.text(_translations.n5WtCyPz || (_translations.n5WtCyPz = tr("Cancel")));
|
|
button_cancel.on("click", () => modal.close());
|
|
tag.append(button_cancel);
|
|
}
|
|
{
|
|
let button_ok = $.spawn("button");
|
|
button_ok.text(_translations.r4iXq8Au || (_translations.r4iXq8Au = tr("OK")));
|
|
button_ok.on("click", () => {
|
|
callback(current_value / 100);
|
|
modal.close();
|
|
});
|
|
tag.append(button_ok);
|
|
}
|
|
return tag;
|
|
},
|
|
width: 600
|
|
});
|
|
update_volume = value => {
|
|
modal.htmlTag.find(".volume_slider").val(value);
|
|
const tag_display = modal.htmlTag.find(".display_volume");
|
|
tag_display.html(value + " %");
|
|
current_value = value;
|
|
};
|
|
modal.open();
|
|
update_volume(current * 100);
|
|
}
|
|
Modals.spawnChangeRemoteVolume = spawnChangeRemoteVolume;
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["708d45d2c158bc747ff051fa9488db664d0024c6f66c07320691939b63b78f77"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["708d45d2c158bc747ff051fa9488db664d0024c6f66c07320691939b63b78f77"] = "708d45d2c158bc747ff051fa9488db664d0024c6f66c07320691939b63b78f77";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "Tdn9l0kj", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalServerGroupDialog.ts (4,21)" }, { name: "nfIjkcVs", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalServerGroupDialog.ts (31,42)" }, { name: "b3pPvY46", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalServerGroupDialog.ts (48,35)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var Modals;
|
|
(function (Modals) {
|
|
function createServerGroupAssignmentModal(client, callback) {
|
|
const modal = createModal({
|
|
header: _translations.Tdn9l0kj || (_translations.Tdn9l0kj = tr("Server Groups")),
|
|
body: () => {
|
|
let tag = {};
|
|
let groups = tag["groups"] = [];
|
|
tag["client_name"] = client.clientNickName();
|
|
for (let group of client.channelTree.client.groups.serverGroups.sort(GroupManager.sorter())) {
|
|
if (group.type != GroupType.NORMAL)
|
|
continue;
|
|
let entry = {};
|
|
entry["id"] = group.id;
|
|
entry["name"] = group.name;
|
|
entry["assigned"] = client.groupAssigned(group);
|
|
entry["disabled"] = !client.channelTree.client.permissions.neededPermission(PermissionType.I_GROUP_MEMBER_ADD_POWER).granted(group.requiredMemberRemovePower);
|
|
tag["icon_" + group.id] = client.channelTree.client.fileManager.icons.generateTag(group.properties.iconid);
|
|
groups.push(entry);
|
|
}
|
|
let template = $("#tmpl_server_group_assignment").renderTag(tag);
|
|
template.find(".group-entry input").each((_idx, _entry) => {
|
|
let entry = $(_entry);
|
|
entry.on('change', event => {
|
|
let group_id = parseInt(entry.attr("group-id"));
|
|
let group = client.channelTree.client.groups.serverGroup(group_id);
|
|
if (!group) {
|
|
console.warn(_translations.nfIjkcVs || (_translations.nfIjkcVs = tr("Could not resolve target group!")));
|
|
return false;
|
|
}
|
|
let target = entry.prop("checked");
|
|
callback(group, target).then(flag => flag ? Promise.resolve() : Promise.reject()).catch(error => entry.prop("checked", !target));
|
|
});
|
|
});
|
|
return template;
|
|
},
|
|
footer: () => {
|
|
let footer = $.spawn("div");
|
|
footer.addClass("modal-button-group");
|
|
footer.css("margin", "5px");
|
|
let button_close = $.spawn("button");
|
|
button_close.text(_translations.b3pPvY46 || (_translations.b3pPvY46 = tr("Close"))).addClass("button_close");
|
|
footer.append(button_close);
|
|
return footer;
|
|
},
|
|
width: "max-content"
|
|
});
|
|
modal.htmlTag.find(".button_close").click(() => {
|
|
modal.close();
|
|
});
|
|
modal.open();
|
|
}
|
|
Modals.createServerGroupAssignmentModal = createServerGroupAssignmentModal;
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["ed30afb7068cb78a1fff26ad87178b5052f672ac142bb4d11f9311f059d1ee5f"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["ed30afb7068cb78a1fff26ad87178b5052f672ac142bb4d11f9311f059d1ee5f"] = "ed30afb7068cb78a1fff26ad87178b5052f672ac142bb4d11f9311f059d1ee5f";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "B5ot5_mB", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client_move.ts (48,21)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="client.ts" />
|
|
class ClientMover {
|
|
constructor(tree) {
|
|
this._active = false;
|
|
this.origin_point = undefined;
|
|
this.channel_tree = tree;
|
|
}
|
|
is_active() { return this._active; }
|
|
hover_text() {
|
|
if ($.isArray(this.selected_client)) {
|
|
return this.selected_client.filter(client => !!client).map(client => client.clientNickName()).join(", ");
|
|
}
|
|
else if (this.selected_client) {
|
|
return this.selected_client.clientNickName();
|
|
}
|
|
else
|
|
return "";
|
|
}
|
|
bbcode_text() {
|
|
if ($.isArray(this.selected_client)) {
|
|
return this.selected_client.filter(client => !!client).map(client => client.create_bbcode()).join(", ");
|
|
}
|
|
else if (this.selected_client) {
|
|
return this.selected_client.create_bbcode();
|
|
}
|
|
else
|
|
return "";
|
|
}
|
|
activate(client, callback, event) {
|
|
this.finish_listener(undefined);
|
|
this.selected_client = client;
|
|
this.callback = callback;
|
|
console.log(_translations.B5ot5_mB || (_translations.B5ot5_mB = tr("Starting mouse move")));
|
|
ClientMover.listener_root.on('mouseup', this._bound_finish = this.finish_listener.bind(this)).on('mousemove', this._bound_move = this.move_listener.bind(this));
|
|
{
|
|
const content = ClientMover.move_element.find(".container");
|
|
content.empty();
|
|
content.append($.spawn("a").text(this.hover_text()));
|
|
}
|
|
this.move_listener(event);
|
|
}
|
|
move_listener(event) {
|
|
//console.log("Mouse move: " + event.pageX + " - " + event.pageY);
|
|
if (!event.pageX || !event.pageY)
|
|
return;
|
|
if (!this.origin_point)
|
|
this.origin_point = { x: event.pageX, y: event.pageY };
|
|
ClientMover.move_element.css({
|
|
"top": (event.pageY - 1) + "px",
|
|
"left": (event.pageX + 10) + "px"
|
|
});
|
|
if (!this._active) {
|
|
const d_x = this.origin_point.x - event.pageX;
|
|
const d_y = this.origin_point.y - event.pageY;
|
|
this._active = Math.sqrt(d_x * d_x + d_y * d_y) > 5 * 5;
|
|
if (this._active) {
|
|
if ($.isArray(this.selected_client)) {
|
|
this.channel_tree.onSelect(this.selected_client[0], true);
|
|
for (const client of this.selected_client.slice(1))
|
|
this.channel_tree.onSelect(client, false, true);
|
|
}
|
|
else {
|
|
this.channel_tree.onSelect(this.selected_client, true);
|
|
}
|
|
ClientMover.move_element.show();
|
|
}
|
|
}
|
|
const elements = document.elementsFromPoint(event.pageX, event.pageY);
|
|
while (elements.length > 0) {
|
|
if (elements[0].classList.contains("container-channel"))
|
|
break;
|
|
elements.pop_front();
|
|
}
|
|
if (this.hovered_channel) {
|
|
this.hovered_channel.classList.remove("move-selected");
|
|
this.hovered_channel = undefined;
|
|
}
|
|
if (elements.length > 0) {
|
|
elements[0].classList.add("move-selected");
|
|
this.hovered_channel = elements[0];
|
|
}
|
|
}
|
|
finish_listener(event) {
|
|
ClientMover.move_element.hide();
|
|
const channel_id = this.hovered_channel ? parseInt(this.hovered_channel.getAttribute("channel-id")) : 0;
|
|
ClientMover.listener_root.unbind('mouseleave', this._bound_finish);
|
|
ClientMover.listener_root.unbind('mouseup', this._bound_finish);
|
|
ClientMover.listener_root.unbind('mousemove', this._bound_move);
|
|
if (this.hovered_channel) {
|
|
this.hovered_channel.classList.remove("move-selected");
|
|
this.hovered_channel = undefined;
|
|
}
|
|
this.origin_point = undefined;
|
|
if (!this._active) {
|
|
this.selected_client = undefined;
|
|
this.callback = undefined;
|
|
return;
|
|
}
|
|
this._active = false;
|
|
if (this.callback) {
|
|
if (!channel_id)
|
|
this.callback(undefined);
|
|
else {
|
|
this.callback(this.channel_tree.findChannel(channel_id));
|
|
}
|
|
this.callback = undefined;
|
|
}
|
|
/* test for the chat box */
|
|
{
|
|
const elements = document.elementsFromPoint(event.pageX, event.pageY);
|
|
console.error(elements);
|
|
while (elements.length > 0) {
|
|
if (elements[0].classList.contains("client-chat-box-field"))
|
|
break;
|
|
elements.pop_front();
|
|
}
|
|
if (elements.length > 0) {
|
|
const element = $(elements[0]);
|
|
element.val((element.val() || "") + this.bbcode_text());
|
|
}
|
|
}
|
|
}
|
|
deactivate() {
|
|
this.callback = undefined;
|
|
this.finish_listener(undefined);
|
|
}
|
|
}
|
|
ClientMover.listener_root = $(document);
|
|
ClientMover.move_element = $("#mouse-move");
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["9d81e62fbece35b2c7f7202b89538496b5c2c217088adc7b87fb08d71561a99c"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["9d81e62fbece35b2c7f7202b89538496b5c2c217088adc7b87fb08d71561a99c"] = "9d81e62fbece35b2c7f7202b89538496b5c2c217088adc7b87fb08d71561a99c";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "wzuKK0mB", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (228,19)" }, { name: "KUowCgCL", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (255,19)" }, { name: "Jxeh4FBs", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (262,19)" }, { name: "BDDek24b", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (275,23)" }, { name: "HJvmO6Yv", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (283,23)" }, { name: "BuvvoxPa", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (285,38)" }, { name: "z8B9Jr_b", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (285,57)" }, { name: "tQTaM2vV", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (300,23)" }, { name: "yKzAGCKN", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (302,38)" }, { name: "Q1CApngv", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (302,71)" }, { name: "lA_9fifG", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (320,23)" }, { name: "sMx2dF57", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (330,23)" }, { name: "ZTYB4b5C", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (332,38)" }, { name: "XFG3swM3", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (332,70)" }, { name: "LZ87Hyos", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (348,23)" }, { name: "WObQGUNP", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (350,38)" }, { name: "p1vJZOOJ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (350,69)" }, { name: "IxNwAB6Z", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (366,23)" }, { name: "uhdldy7w", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (404,23)" }, { name: "IcO_rO5a", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (565,70)" }, { name: "nZsgZjvq", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (790,23)" }, { name: "luXlxqAz", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (795,23)" }, { name: "L3eN3w7x", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (798,38)" }, { name: "pJm9WNWU", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (798,68)" }, { name: "huKXae1n", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (800,41)" }, { name: "LUgGlgDn", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (858,49)" }, { name: "erjjkAEe", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (860,47)" }, { name: "yOofHBYZ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (913,23)" }, { name: "Ib4e7gF0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (917,38)" }, { name: "IW3obMAX", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (917,72)" }, { name: "QEBR_LaZ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (929,23)" }, { name: "C8pFnqhh", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (933,38)" }, { name: "AEH0aFoC", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (933,75)" }, { name: "NFoAqO50", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (955,23)" }, { name: "hi3i15FD", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (966,42)" }, { name: "aEP95pp4", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (966,69)" }, { name: "Em4GmMYf", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (968,42)" }, { name: "HjT6bOoT", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (968,75)" }, { name: "BUWjmbJD", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (974,23)" }, { name: "u0N7Wpfv", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (978,38)" }, { name: "isk4PsRv", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (978,66)" }, { name: "E4YHyYIB", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (989,50)" }, { name: "DNOAqnou", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (1001,23)" }, { name: "mtkKxwaH", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (1011,23)" }, { name: "envwWmFs", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (1013,38)" }, { name: "mfkXcBbD", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (1013,70)" }, { name: "N8PkkYgk", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (1015,41)" }, { name: "a83GPSuP", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (1029,23)" }, { name: "vU0_4DbG", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (1042,23)" }, { name: "ReawvrYk", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (1061,23)" }, { name: "Iilzvtrs", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (1065,83)" }, { name: "GzAtMa7f", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/client.ts (1066,39)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="channel.ts" />
|
|
/// <reference path="modal/ModalChangeVolume.ts" />
|
|
/// <reference path="modal/ModalServerGroupDialog.ts" />
|
|
/// <reference path="client_move.ts" />
|
|
var ClientType;
|
|
(function (ClientType) {
|
|
ClientType[ClientType["CLIENT_VOICE"] = 0] = "CLIENT_VOICE";
|
|
ClientType[ClientType["CLIENT_QUERY"] = 1] = "CLIENT_QUERY";
|
|
ClientType[ClientType["CLIENT_INTERNAL"] = 2] = "CLIENT_INTERNAL";
|
|
ClientType[ClientType["CLIENT_WEB"] = 3] = "CLIENT_WEB";
|
|
ClientType[ClientType["CLIENT_MUSIC"] = 4] = "CLIENT_MUSIC";
|
|
ClientType[ClientType["CLIENT_UNDEFINED"] = 5] = "CLIENT_UNDEFINED";
|
|
})(ClientType || (ClientType = {}));
|
|
class ClientProperties {
|
|
constructor() {
|
|
this.client_type = ClientType.CLIENT_VOICE; //TeamSpeaks type
|
|
this.client_type_exact = ClientType.CLIENT_VOICE;
|
|
this.client_database_id = 0;
|
|
this.client_version = "";
|
|
this.client_platform = "";
|
|
this.client_nickname = "unknown";
|
|
this.client_unique_identifier = "unknown";
|
|
this.client_description = "";
|
|
this.client_servergroups = "";
|
|
this.client_channel_group_id = 0;
|
|
this.client_lastconnected = 0;
|
|
this.client_flag_avatar = "";
|
|
this.client_icon_id = 0;
|
|
this.client_away_message = "";
|
|
this.client_away = false;
|
|
this.client_input_hardware = false;
|
|
this.client_output_hardware = false;
|
|
this.client_input_muted = false;
|
|
this.client_output_muted = false;
|
|
this.client_is_channel_commander = false;
|
|
this.client_teaforum_id = 0;
|
|
this.client_teaforum_name = "";
|
|
this.client_talk_power = 0;
|
|
}
|
|
}
|
|
class ClientEntry {
|
|
constructor(clientId, clientName, properties = new ClientProperties()) {
|
|
this.lastVariableUpdate = 0;
|
|
this._speaking = false;
|
|
this._properties = properties;
|
|
this._properties.client_nickname = clientName;
|
|
this._clientId = clientId;
|
|
this.channelTree = null;
|
|
this._channel = null;
|
|
this.audioController = new AudioController();
|
|
const _this = this;
|
|
this.audioController.onSpeaking = function () {
|
|
_this.speaking = true;
|
|
};
|
|
this.audioController.onSilence = function () {
|
|
_this.speaking = false;
|
|
};
|
|
this.audioController.initialize();
|
|
}
|
|
get properties() {
|
|
return this._properties;
|
|
}
|
|
currentChannel() { return this._channel; }
|
|
clientNickName() { return this.properties.client_nickname; }
|
|
clientUid() { return this.properties.client_unique_identifier; }
|
|
clientId() { return this._clientId; }
|
|
getAudioController() {
|
|
return this.audioController;
|
|
}
|
|
initializeListener() {
|
|
if (this._listener_initialized)
|
|
return;
|
|
this._listener_initialized = true;
|
|
this.tag.on('mouseup', event => {
|
|
if (!this.channelTree.client_mover.is_active()) {
|
|
this.channelTree.onSelect(this);
|
|
}
|
|
});
|
|
this.tag.click(event => {
|
|
console.log("Clicked!");
|
|
});
|
|
if (!(this instanceof LocalClientEntry) && !(this instanceof MusicClientEntry))
|
|
this.tag.dblclick(event => {
|
|
if ($.isArray(this.channelTree.currently_selected)) { //Multiselect
|
|
return;
|
|
}
|
|
this.chat(true).focus();
|
|
});
|
|
if (!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
|
|
this.tag.on("contextmenu", (event) => {
|
|
event.preventDefault();
|
|
if ($.isArray(this.channelTree.currently_selected)) { //Multiselect
|
|
(this.channelTree.currently_selected_context_callback || ((_) => null))(event);
|
|
return;
|
|
}
|
|
this.channelTree.onSelect(this, true);
|
|
this.showContextMenu(event.pageX, event.pageY, () => { });
|
|
return false;
|
|
});
|
|
}
|
|
this.tag.mousedown(event => {
|
|
if (event.which != 1)
|
|
return; //Only the left button
|
|
let clients = this.channelTree.currently_selected;
|
|
if (ppt.key_pressed(ppt.SpecialKey.SHIFT)) {
|
|
if (clients != this && !($.isArray(clients) && clients.indexOf(this) != -1))
|
|
clients = $.isArray(clients) ? [...clients, this] : [clients, this];
|
|
}
|
|
else {
|
|
clients = this;
|
|
}
|
|
this.channelTree.client_mover.activate(clients, target => {
|
|
if (!target)
|
|
return;
|
|
for (const client of $.isArray(clients) ? clients : [clients]) {
|
|
if (target == client._channel)
|
|
continue;
|
|
const source = client._channel;
|
|
const self = this.channelTree.client.getClient();
|
|
this.channelTree.client.serverConnection.send_command("clientmove", {
|
|
clid: client.clientId(),
|
|
cid: target.getChannelId()
|
|
}).then(event => {
|
|
if (client.clientId() == this.channelTree.client.clientId)
|
|
sound.play(Sound.CHANNEL_JOINED);
|
|
else if (target !== source && target != self.currentChannel())
|
|
sound.play(Sound.USER_MOVED);
|
|
});
|
|
}
|
|
this.channelTree.onSelect();
|
|
}, event);
|
|
});
|
|
}
|
|
assignment_context() {
|
|
let server_groups = [];
|
|
for (let group of this.channelTree.client.groups.serverGroups.sort(GroupManager.sorter())) {
|
|
if (group.type != GroupType.NORMAL)
|
|
continue;
|
|
let entry = {};
|
|
{
|
|
let tag = $.spawn("label").addClass("checkbox");
|
|
$.spawn("input").attr("type", "checkbox").prop("checked", this.groupAssigned(group)).appendTo(tag);
|
|
$.spawn("span").addClass("checkmark").appendTo(tag);
|
|
entry.icon = tag;
|
|
}
|
|
entry.name = group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]";
|
|
if (this.groupAssigned(group)) {
|
|
entry.callback = () => {
|
|
this.channelTree.client.serverConnection.send_command("servergroupdelclient", {
|
|
sgid: group.id,
|
|
cldbid: this.properties.client_database_id
|
|
});
|
|
};
|
|
entry.disabled = !this.channelTree.client.permissions.neededPermission(PermissionType.I_GROUP_MEMBER_ADD_POWER).granted(group.requiredMemberRemovePower);
|
|
}
|
|
else {
|
|
entry.callback = () => {
|
|
this.channelTree.client.serverConnection.send_command("servergroupaddclient", {
|
|
sgid: group.id,
|
|
cldbid: this.properties.client_database_id
|
|
});
|
|
};
|
|
entry.disabled = !this.channelTree.client.permissions.neededPermission(PermissionType.I_GROUP_MEMBER_REMOVE_POWER).granted(group.requiredMemberAddPower);
|
|
}
|
|
entry.type = MenuEntryType.ENTRY;
|
|
server_groups.push(entry);
|
|
}
|
|
let channel_groups = [];
|
|
for (let group of this.channelTree.client.groups.channelGroups.sort(GroupManager.sorter())) {
|
|
if (group.type != GroupType.NORMAL)
|
|
continue;
|
|
let entry = {};
|
|
{
|
|
let tag = $.spawn("label").addClass("checkbox");
|
|
$.spawn("input").attr("type", "checkbox").prop("checked", this.assignedChannelGroup() == group.id).appendTo(tag);
|
|
$.spawn("span").addClass("checkmark").appendTo(tag);
|
|
entry.icon = tag;
|
|
}
|
|
entry.name = group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]";
|
|
entry.callback = () => {
|
|
this.channelTree.client.serverConnection.send_command("setclientchannelgroup", {
|
|
cldbid: this.properties.client_database_id,
|
|
cgid: group.id,
|
|
cid: this.currentChannel().channelId
|
|
});
|
|
};
|
|
entry.disabled = !this.channelTree.client.permissions.neededPermission(PermissionType.I_GROUP_MEMBER_ADD_POWER).granted(group.requiredMemberRemovePower);
|
|
entry.type = MenuEntryType.ENTRY;
|
|
channel_groups.push(entry);
|
|
}
|
|
return [{
|
|
type: MenuEntryType.SUB_MENU,
|
|
icon: "client-permission_server_groups",
|
|
name: _translations.wzuKK0mB || (_translations.wzuKK0mB = tr("Set server group")),
|
|
sub_menu: [
|
|
{
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-permission_server_groups",
|
|
name: "Server groups dialog",
|
|
callback: () => {
|
|
Modals.createServerGroupAssignmentModal(this, (group, flag) => {
|
|
if (flag) {
|
|
return this.channelTree.client.serverConnection.send_command("servergroupaddclient", {
|
|
sgid: group.id,
|
|
cldbid: this.properties.client_database_id
|
|
}).then(result => true);
|
|
}
|
|
else
|
|
return this.channelTree.client.serverConnection.send_command("servergroupdelclient", {
|
|
sgid: group.id,
|
|
cldbid: this.properties.client_database_id
|
|
}).then(result => true);
|
|
});
|
|
}
|
|
},
|
|
MenuEntry.HR(),
|
|
...server_groups
|
|
]
|
|
}, {
|
|
type: MenuEntryType.SUB_MENU,
|
|
icon: "client-permission_channel",
|
|
name: _translations.KUowCgCL || (_translations.KUowCgCL = tr("Set channel group")),
|
|
sub_menu: [
|
|
...channel_groups
|
|
]
|
|
}, {
|
|
type: MenuEntryType.SUB_MENU,
|
|
icon: "client-permission_client",
|
|
name: _translations.Jxeh4FBs || (_translations.Jxeh4FBs = tr("Permissions")),
|
|
disabled: true,
|
|
sub_menu: []
|
|
}];
|
|
}
|
|
showContextMenu(x, y, on_close = undefined) {
|
|
const _this = this;
|
|
spawn_context_menu(x, y, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-change_nickname",
|
|
name: _translations.BDDek24b || (_translations.BDDek24b = tr("<b>Open text chat</b>")),
|
|
callback: function () {
|
|
chat.activeChat = _this.chat(true);
|
|
chat.focus();
|
|
}
|
|
}, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-poke",
|
|
name: _translations.HJvmO6Yv || (_translations.HJvmO6Yv = tr("Poke client")),
|
|
callback: function () {
|
|
createInputModal(_translations.BuvvoxPa || (_translations.BuvvoxPa = tr("Poke client")), _translations.z8B9Jr_b || (_translations.z8B9Jr_b = tr("Poke message:<br>")), text => true, result => {
|
|
if (typeof (result) === "string") {
|
|
//TODO tr
|
|
console.log("Poking client " + _this.clientNickName() + " with message " + result);
|
|
_this.channelTree.client.serverConnection.send_command("clientpoke", {
|
|
clid: _this.clientId(),
|
|
msg: result
|
|
});
|
|
}
|
|
}, { width: 400, maxLength: 512 }).open();
|
|
}
|
|
}, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-edit",
|
|
name: _translations.tQTaM2vV || (_translations.tQTaM2vV = tr("Change description")),
|
|
callback: function () {
|
|
createInputModal(_translations.yKzAGCKN || (_translations.yKzAGCKN = tr("Change client description")), _translations.Q1CApngv || (_translations.Q1CApngv = tr("New description:<br>")), text => true, result => {
|
|
if (typeof (result) === "string") {
|
|
//TODO tr
|
|
console.log("Changing " + _this.clientNickName() + "'s description to " + result);
|
|
_this.channelTree.client.serverConnection.send_command("clientedit", {
|
|
clid: _this.clientId(),
|
|
client_description: result
|
|
});
|
|
}
|
|
}, { width: 400, maxLength: 1024 }).open();
|
|
}
|
|
}, MenuEntry.HR(), ...this.assignment_context(), MenuEntry.HR(), {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-move_client_to_own_channel",
|
|
name: _translations.lA_9fifG || (_translations.lA_9fifG = tr("Move client to your channel")),
|
|
callback: () => {
|
|
this.channelTree.client.serverConnection.send_command("clientmove", {
|
|
clid: this.clientId(),
|
|
cid: this.channelTree.client.getClient().currentChannel().getChannelId()
|
|
});
|
|
}
|
|
}, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-kick_channel",
|
|
name: _translations.sMx2dF57 || (_translations.sMx2dF57 = tr("Kick client from channel")),
|
|
callback: () => {
|
|
createInputModal(_translations.ZTYB4b5C || (_translations.ZTYB4b5C = tr("Kick client from channel")), _translations.XFG3swM3 || (_translations.XFG3swM3 = tr("Kick reason:<br>")), text => true, result => {
|
|
if (result) {
|
|
//TODO tr
|
|
console.log("Kicking client " + _this.clientNickName() + " from channel with reason " + result);
|
|
_this.channelTree.client.serverConnection.send_command("clientkick", {
|
|
clid: _this.clientId(),
|
|
reasonid: ViewReasonId.VREASON_CHANNEL_KICK,
|
|
reasonmsg: result
|
|
});
|
|
}
|
|
}, { width: 400, maxLength: 255 }).open();
|
|
}
|
|
}, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-kick_server",
|
|
name: _translations.LZ87Hyos || (_translations.LZ87Hyos = tr("Kick client fom server")),
|
|
callback: () => {
|
|
createInputModal(_translations.WObQGUNP || (_translations.WObQGUNP = tr("Kick client from server")), _translations.p1vJZOOJ || (_translations.p1vJZOOJ = tr("Kick reason:<br>")), text => true, result => {
|
|
if (result) {
|
|
//TODO tr
|
|
console.log("Kicking client " + _this.clientNickName() + " from server with reason " + result);
|
|
_this.channelTree.client.serverConnection.send_command("clientkick", {
|
|
clid: _this.clientId(),
|
|
reasonid: ViewReasonId.VREASON_SERVER_KICK,
|
|
reasonmsg: result
|
|
});
|
|
}
|
|
}, { width: 400, maxLength: 255 }).open();
|
|
}
|
|
}, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-ban_client",
|
|
name: _translations.IxNwAB6Z || (_translations.IxNwAB6Z = tr("Ban client")),
|
|
invalidPermission: !this.channelTree.client.permissions.neededPermission(PermissionType.I_CLIENT_BAN_MAX_BANTIME).granted(1),
|
|
callback: () => {
|
|
Modals.spawnBanClient(this.properties.client_nickname, (data) => {
|
|
this.channelTree.client.serverConnection.send_command("banclient", {
|
|
uid: this.properties.client_unique_identifier,
|
|
banreason: data.reason,
|
|
time: data.length
|
|
}, {
|
|
flagset: [data.no_ip ? "no-ip" : "", data.no_hwid ? "no-hardware-id" : "", data.no_name ? "no-nickname" : ""]
|
|
}).then(() => {
|
|
sound.play(Sound.USER_BANNED);
|
|
});
|
|
});
|
|
}
|
|
}, MenuEntry.HR(),
|
|
/*
|
|
{
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-kick_server",
|
|
name: "Add group to client",
|
|
invalidPermission: true, //!this.channelTree.client.permissions.neededPermission(PermissionType.I_CLIENT_BAN_MAX_BANTIME).granted(1),
|
|
callback: () => {
|
|
Modals.spawnBanClient(this.properties.client_nickname, (duration, reason) => {
|
|
this.channelTree.client.serverConnection.send_command("banclient", {
|
|
uid: this.properties.client_unique_identifier,
|
|
banreason: reason,
|
|
time: duration
|
|
});
|
|
});
|
|
}
|
|
},
|
|
MenuEntry.HR(),
|
|
*/
|
|
{
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-volume",
|
|
name: _translations.uhdldy7w || (_translations.uhdldy7w = tr("Change Volume")),
|
|
callback: () => {
|
|
Modals.spawnChangeVolume(this.audioController.volume, volume => {
|
|
settings.changeServer("volume_client_" + this.clientUid(), volume);
|
|
this.audioController.volume = volume;
|
|
if (globalClient.selectInfo.currentSelected == this)
|
|
globalClient.selectInfo.update();
|
|
});
|
|
}
|
|
}, MenuEntry.CLOSE(on_close));
|
|
}
|
|
get tag() {
|
|
if (this._tag)
|
|
return this._tag;
|
|
let container_client = $.spawn("div")
|
|
.addClass("tree-entry client")
|
|
.attr("client-id", this.clientId());
|
|
container_client.append($.spawn("div")
|
|
.addClass("icon_client_state")
|
|
.attr("title", "Client state"));
|
|
container_client.append($.spawn("div")
|
|
.addClass("group-prefix")
|
|
.attr("title", "Server groups prefixes")
|
|
.hide());
|
|
container_client.append($.spawn("div")
|
|
.addClass("client-name")
|
|
.text(this.clientNickName()));
|
|
container_client.append($.spawn("div")
|
|
.addClass("group-suffix")
|
|
.attr("title", "Server groups suffix")
|
|
.hide());
|
|
container_client.append($.spawn("div")
|
|
.addClass("client-away-message")
|
|
.text(this.clientNickName()));
|
|
let container_icons = $.spawn("div").addClass("container-icons");
|
|
container_icons.append($.spawn("div")
|
|
.addClass("icon icon_talk_power client-input_muted")
|
|
.hide());
|
|
container_icons.append($.spawn("div")
|
|
.addClass("container-icons-group"));
|
|
container_icons.append($.spawn("div")
|
|
.addClass("container-icon-client"));
|
|
container_client.append(container_icons);
|
|
this._tag = container_client;
|
|
this.initializeListener();
|
|
return this._tag;
|
|
}
|
|
static bbcodeTag(id, name, uid) {
|
|
return "[url=client://" + id + "/" + uid + "~" + encodeURIComponent(name) + "]" + name + "[/url]";
|
|
}
|
|
static chatTag(id, name, uid, braces = false) {
|
|
return $(htmltags.generate_client({
|
|
client_name: name,
|
|
client_avatar_id: id,
|
|
client_unique_id: uid,
|
|
add_braces: braces
|
|
}));
|
|
}
|
|
create_bbcode() {
|
|
return ClientEntry.bbcodeTag(this.clientId(), this.clientNickName(), this.clientUid());
|
|
}
|
|
createChatTag(braces = false) {
|
|
return ClientEntry.chatTag(this.clientId(), this.clientNickName(), this.clientUid(), braces);
|
|
}
|
|
set speaking(flag) {
|
|
if (flag == this._speaking)
|
|
return;
|
|
this._speaking = flag;
|
|
this.updateClientSpeakIcon();
|
|
}
|
|
updateClientStatusIcons() {
|
|
let talk_power = this.properties.client_talk_power >= this._channel.properties.channel_needed_talk_power;
|
|
if (talk_power)
|
|
this.tag.find(".icon_talk_power").hide();
|
|
else
|
|
this.tag.find(".icon_talk_power").show();
|
|
}
|
|
updateClientSpeakIcon() {
|
|
let icon = "";
|
|
let clicon = "";
|
|
if (this.properties.client_type_exact == ClientType.CLIENT_QUERY) {
|
|
icon = "client-server_query";
|
|
console.log("Server query!");
|
|
}
|
|
else {
|
|
if (this.properties.client_away) {
|
|
icon = "client-away";
|
|
}
|
|
else if (!this.properties.client_output_hardware) {
|
|
icon = "client-hardware_output_muted";
|
|
}
|
|
else if (this.properties.client_output_muted) {
|
|
icon = "client-output_muted";
|
|
}
|
|
else if (!this.properties.client_input_hardware) {
|
|
icon = "client-hardware_input_muted";
|
|
}
|
|
else if (this.properties.client_input_muted) {
|
|
icon = "client-input_muted";
|
|
}
|
|
else {
|
|
if (this._speaking) {
|
|
if (this.properties.client_is_channel_commander)
|
|
clicon = "client_cc_talk";
|
|
else
|
|
clicon = "client_talk";
|
|
}
|
|
else {
|
|
if (this.properties.client_is_channel_commander)
|
|
clicon = "client_cc_idle";
|
|
else
|
|
clicon = "client_idle";
|
|
}
|
|
}
|
|
}
|
|
if (clicon.length > 0)
|
|
this.tag.find(".icon_client_state").attr('class', 'icon_client_state clicon ' + clicon);
|
|
else if (icon.length > 0)
|
|
this.tag.find(".icon_client_state").attr('class', 'icon_client_state icon ' + icon);
|
|
else
|
|
this.tag.find(".icon_client_state").attr('class', 'icon_client_state icon_empty');
|
|
}
|
|
updateAwayMessage() {
|
|
let tag = this.tag.find(".client-away-message");
|
|
if (this.properties.client_away == true && this.properties.client_away_message) {
|
|
tag.text("[" + this.properties.client_away_message + "]");
|
|
tag.show();
|
|
}
|
|
else {
|
|
tag.hide();
|
|
}
|
|
}
|
|
updateVariables(...variables) {
|
|
let group = log.group(log.LogType.DEBUG, LogCategory.CLIENT, _translations.IcO_rO5a || (_translations.IcO_rO5a = tr("Update properties (%i) of %s (%i)")), variables.length, this.clientNickName(), this.clientId());
|
|
let update_icon_status = false;
|
|
let update_icon_speech = false;
|
|
let update_away = false;
|
|
let reorder_channel = false;
|
|
for (let variable of variables) {
|
|
JSON.map_field_to(this._properties, variable.value, variable.key);
|
|
//TODO tr
|
|
group.log("Updating client " + this.clientId() + ". Key " + variable.key + " Value: '" + variable.value + "' (" + typeof (this.properties[variable.key]) + ")");
|
|
if (variable.key == "client_nickname") {
|
|
this.tag.find(".client-name").text(variable.value);
|
|
let chat = this.chat(false);
|
|
if (chat)
|
|
chat.name = variable.value;
|
|
reorder_channel = true;
|
|
}
|
|
if (variable.key == "client_away" || variable.key == "client_output_muted" || variable.key == "client_input_hardware" || variable.key == "client_input_muted" || variable.key == "client_is_channel_commander") {
|
|
update_icon_speech = true;
|
|
}
|
|
if (variable.key == "client_away_message" || variable.key == "client_away") {
|
|
update_away = true;
|
|
}
|
|
if (variable.key == "client_unique_identifier") {
|
|
this.audioController.volume = parseFloat(settings.server("volume_client_" + this.clientUid(), "1"));
|
|
//TODO tr
|
|
console.error("Updated volume from config " + this.audioController.volume + " - " + "volume_client_" + this.clientUid() + " - " + settings.server("volume_client_" + this.clientUid(), "1"));
|
|
console.log(this.avatarId());
|
|
}
|
|
if (variable.key == "client_talk_power") {
|
|
reorder_channel = true;
|
|
update_icon_status = true;
|
|
}
|
|
if (variable.key == "client_icon_id")
|
|
this.updateClientIcon();
|
|
if (variable.key == "client_channel_group_id" || variable.key == "client_servergroups")
|
|
this.update_displayed_client_groups();
|
|
}
|
|
/* process updates after variables have been set */
|
|
if (this._channel && reorder_channel)
|
|
this._channel.reorderClients();
|
|
if (update_icon_speech)
|
|
this.updateClientSpeakIcon();
|
|
if (update_icon_status)
|
|
this.updateClientStatusIcons();
|
|
if (update_away)
|
|
this.updateAwayMessage();
|
|
group.end();
|
|
}
|
|
update_displayed_client_groups() {
|
|
this.tag.find(".container-icons-group").children().detach();
|
|
for (let id of this.assignedServerGroupIds())
|
|
this.updateGroupIcon(this.channelTree.client.groups.serverGroup(id));
|
|
this.updateGroupIcon(this.channelTree.client.groups.channelGroup(this.properties.client_channel_group_id));
|
|
let prefix_groups = [];
|
|
let suffix_groups = [];
|
|
for (const group_id of this.assignedServerGroupIds()) {
|
|
const group = this.channelTree.client.groups.serverGroup(group_id);
|
|
if (!group)
|
|
continue;
|
|
if (group.properties.namemode == 1)
|
|
prefix_groups.push(group.name);
|
|
else if (group.properties.namemode == 2)
|
|
suffix_groups.push(group.name);
|
|
}
|
|
const tag_group_prefix = this.tag.find(".group-prefix");
|
|
const tag_group_suffix = this.tag.find(".group-suffix");
|
|
if (prefix_groups.length > 0) {
|
|
tag_group_prefix.text("[" + prefix_groups.join("][") + "]").show();
|
|
}
|
|
else {
|
|
tag_group_prefix.hide();
|
|
}
|
|
if (suffix_groups.length > 0) {
|
|
tag_group_suffix.text("[" + suffix_groups.join("][") + "]").show();
|
|
}
|
|
else {
|
|
tag_group_suffix.hide();
|
|
}
|
|
}
|
|
updateClientVariables() {
|
|
if (this.lastVariableUpdate == 0 || new Date().getTime() - 10 * 60 * 1000 > this.lastVariableUpdate) { //Cache these only 10 min
|
|
this.lastVariableUpdate = new Date().getTime();
|
|
this.channelTree.client.serverConnection.send_command("clientgetvariables", { clid: this.clientId() });
|
|
}
|
|
}
|
|
chat(create = false) {
|
|
let chatName = "client_" + this.clientUid() + ":" + this.clientId();
|
|
let c = chat.findChat(chatName);
|
|
if ((!c) && create) {
|
|
c = chat.createChat(chatName);
|
|
c.closeable = true;
|
|
c.name = this.clientNickName();
|
|
const _this = this;
|
|
c.onMessageSend = function (text) {
|
|
_this.channelTree.client.serverConnection.command_helper.sendMessage(text, ChatType.CLIENT, _this);
|
|
};
|
|
c.onClose = function () {
|
|
//TODO check online?
|
|
_this.channelTree.client.serverConnection.send_command("clientchatclosed", { "clid": _this.clientId() });
|
|
return true;
|
|
};
|
|
}
|
|
return c;
|
|
}
|
|
updateClientIcon() {
|
|
this.tag.find(".container-icon-client").children().detach();
|
|
if (this.properties.client_icon_id > 0) {
|
|
this.channelTree.client.fileManager.icons.generateTag(this.properties.client_icon_id).attr("title", "Client icon")
|
|
.appendTo(this.tag.find(".container-icon-client"));
|
|
}
|
|
}
|
|
updateGroupIcon(group) {
|
|
if (!group)
|
|
return;
|
|
//TODO group icon order
|
|
this.tag.find(".container-icons-group .icon_group_" + group.id).detach();
|
|
if (group.properties.iconid > 0) {
|
|
this.tag.find(".container-icons-group").append($.spawn("div")
|
|
.addClass("container-group-icon icon_group_" + group.id)
|
|
.append(this.channelTree.client.fileManager.icons.generateTag(group.properties.iconid)).attr("title", group.name));
|
|
}
|
|
}
|
|
assignedServerGroupIds() {
|
|
let result = [];
|
|
for (let id of this.properties.client_servergroups.split(",")) {
|
|
if (id.length == 0)
|
|
continue;
|
|
result.push(Number.parseInt(id));
|
|
}
|
|
return result;
|
|
}
|
|
assignedChannelGroup() {
|
|
return this.properties.client_channel_group_id;
|
|
}
|
|
groupAssigned(group) {
|
|
if (group.target == GroupTarget.SERVER) {
|
|
for (let id of this.assignedServerGroupIds())
|
|
if (id == group.id)
|
|
return true;
|
|
return false;
|
|
}
|
|
else
|
|
return group.id == this.assignedChannelGroup();
|
|
}
|
|
onDelete() {
|
|
this.audioController.close();
|
|
this.audioController = undefined;
|
|
}
|
|
calculateOnlineTime() {
|
|
return Date.now() / 1000 - this.properties.client_lastconnected;
|
|
}
|
|
avatarId() {
|
|
function str2ab(str) {
|
|
let buf = new ArrayBuffer(str.length); // 2 bytes for each char
|
|
let bufView = new Uint8Array(buf);
|
|
for (let i = 0, strLen = str.length; i < strLen; i++) {
|
|
bufView[i] = str.charCodeAt(i);
|
|
}
|
|
return buf;
|
|
}
|
|
try {
|
|
let raw = atob(this.properties.client_unique_identifier);
|
|
let input = hex.encode(str2ab(raw));
|
|
let result = "";
|
|
for (let index = 0; index < input.length; index++) {
|
|
let c = input.charAt(index);
|
|
let offset = 0;
|
|
if (c >= '0' && c <= '9')
|
|
offset = c.charCodeAt(0) - '0'.charCodeAt(0);
|
|
else if (c >= 'A' && c <= 'F')
|
|
offset = c.charCodeAt(0) - 'A'.charCodeAt(0) + 0x0A;
|
|
else if (c >= 'a' && c <= 'f')
|
|
offset = c.charCodeAt(0) - 'a'.charCodeAt(0) + 0x0A;
|
|
result += String.fromCharCode('a'.charCodeAt(0) + offset);
|
|
}
|
|
return result;
|
|
}
|
|
catch (e) { //invalid base 64 (like music bot etc)
|
|
return undefined;
|
|
}
|
|
}
|
|
update_family_index() {
|
|
if (!this._channel)
|
|
return;
|
|
const index = this._channel.calculate_family_index();
|
|
this.tag.css('padding-left', (index + 2) * 16 + "px");
|
|
}
|
|
}
|
|
class LocalClientEntry extends ClientEntry {
|
|
constructor(handle) {
|
|
super(0, "local client");
|
|
this.handle = handle;
|
|
}
|
|
showContextMenu(x, y, on_close = undefined) {
|
|
const _self = this;
|
|
spawn_context_menu(x, y, {
|
|
name: _translations.nZsgZjvq || (_translations.nZsgZjvq = tr("<b>Change name</b>")),
|
|
icon: "client-change_nickname",
|
|
callback: () => _self.openRename(),
|
|
type: MenuEntryType.ENTRY
|
|
}, {
|
|
name: _translations.luXlxqAz || (_translations.luXlxqAz = tr("Change description")),
|
|
icon: "client-edit",
|
|
callback: () => {
|
|
createInputModal(_translations.L3eN3w7x || (_translations.L3eN3w7x = tr("Change own description")), _translations.pJm9WNWU || (_translations.pJm9WNWU = tr("New description:<br>")), text => true, result => {
|
|
if (result) {
|
|
console.log(_translations.huKXae1n || (_translations.huKXae1n = tr("Changing own description to %s")), result);
|
|
_self.channelTree.client.serverConnection.send_command("clientedit", {
|
|
clid: _self.clientId(),
|
|
client_description: result
|
|
});
|
|
}
|
|
}, { width: 400, maxLength: 1024 }).open();
|
|
},
|
|
type: MenuEntryType.ENTRY
|
|
}, MenuEntry.HR(), ...this.assignment_context(), MenuEntry.CLOSE(on_close));
|
|
}
|
|
initializeListener() {
|
|
super.initializeListener();
|
|
this.tag.find(".client-name").addClass("client-name-own");
|
|
this.tag.dblclick(() => {
|
|
if ($.isArray(this.channelTree.currently_selected)) { //Multiselect
|
|
return;
|
|
}
|
|
this.openRename();
|
|
});
|
|
}
|
|
openRename() {
|
|
const _self = this;
|
|
const elm = this.tag.find(".client-name");
|
|
elm.attr("contenteditable", "true");
|
|
elm.removeClass("client-name-own");
|
|
elm.css("background-color", "white");
|
|
elm.focus();
|
|
_self.renaming = true;
|
|
elm.keypress(function (e) {
|
|
if (e.keyCode == 13 /* Enter */) {
|
|
$(this).trigger("focusout");
|
|
return false;
|
|
}
|
|
});
|
|
elm.focusout(function (e) {
|
|
if (!_self.renaming)
|
|
return;
|
|
_self.renaming = false;
|
|
elm.css("background-color", "");
|
|
elm.removeAttr("contenteditable");
|
|
elm.addClass("client-name-own");
|
|
let text = elm.text().toString();
|
|
if (_self.clientNickName() == text)
|
|
return;
|
|
elm.text(_self.clientNickName());
|
|
_self.handle.serverConnection.command_helper.updateClient("client_nickname", text).then((e) => {
|
|
chat.serverChat().appendMessage(_translations.LUgGlgDn || (_translations.LUgGlgDn = tr("Nickname successfully changed")));
|
|
}).catch((e) => {
|
|
chat.serverChat().appendError(_translations.erjjkAEe || (_translations.erjjkAEe = tr("Could not change nickname ({})")), e.extra_message);
|
|
_self.openRename();
|
|
});
|
|
});
|
|
}
|
|
}
|
|
class MusicClientProperties extends ClientProperties {
|
|
constructor() {
|
|
super(...arguments);
|
|
this.player_state = 0;
|
|
this.player_volume = 0;
|
|
this.client_playlist_id = 0;
|
|
this.client_disabled = false;
|
|
}
|
|
}
|
|
class MusicClientPlayerInfo {
|
|
constructor() {
|
|
this.bot_id = 0;
|
|
this.player_state = 0;
|
|
this.player_buffered_index = 0;
|
|
this.player_replay_index = 0;
|
|
this.player_max_index = 0;
|
|
this.player_seekable = false;
|
|
this.player_title = "";
|
|
this.player_description = "";
|
|
this.song_id = 0;
|
|
this.song_url = "";
|
|
this.song_invoker = 0;
|
|
this.song_loaded = false;
|
|
this.song_title = "";
|
|
this.song_thumbnail = "";
|
|
this.song_length = 0;
|
|
}
|
|
}
|
|
class MusicClientEntry extends ClientEntry {
|
|
constructor(clientId, clientName) {
|
|
super(clientId, clientName, new MusicClientProperties());
|
|
this._info_promise_age = 0;
|
|
}
|
|
get properties() {
|
|
return this._properties;
|
|
}
|
|
showContextMenu(x, y, on_close = undefined) {
|
|
spawn_context_menu(x, y, {
|
|
name: _translations.yOofHBYZ || (_translations.yOofHBYZ = tr("<b>Change bot name</b>")),
|
|
icon: "client-change_nickname",
|
|
disabled: false,
|
|
callback: () => {
|
|
createInputModal(_translations.Ib4e7gF0 || (_translations.Ib4e7gF0 = tr("Change music bots nickname")), _translations.IW3obMAX || (_translations.IW3obMAX = tr("New nickname:<br>")), text => text.length >= 3 && text.length <= 31, result => {
|
|
if (result) {
|
|
this.channelTree.client.serverConnection.send_command("clientedit", {
|
|
clid: this.clientId(),
|
|
client_nickname: result
|
|
});
|
|
}
|
|
}, { width: 400, maxLength: 255 }).open();
|
|
},
|
|
type: MenuEntryType.ENTRY
|
|
}, {
|
|
name: _translations.QEBR_LaZ || (_translations.QEBR_LaZ = tr("Change bot description")),
|
|
icon: "client-edit",
|
|
disabled: false,
|
|
callback: () => {
|
|
createInputModal(_translations.C8pFnqhh || (_translations.C8pFnqhh = tr("Change music bots description")), _translations.AEH0aFoC || (_translations.AEH0aFoC = tr("New description:<br>")), text => true, result => {
|
|
if (typeof (result) === 'string') {
|
|
this.channelTree.client.serverConnection.send_command("clientedit", {
|
|
clid: this.clientId(),
|
|
client_description: result
|
|
});
|
|
}
|
|
}, { width: 400, maxLength: 255 }).open();
|
|
},
|
|
type: MenuEntryType.ENTRY
|
|
},
|
|
/*
|
|
{
|
|
name: tr("Open music panel"),
|
|
icon: "client-edit",
|
|
disabled: true,
|
|
callback: () => {},
|
|
type: MenuEntryType.ENTRY
|
|
},
|
|
*/
|
|
{
|
|
name: _translations.NFoAqO50 || (_translations.NFoAqO50 = tr("Open bot's playlist")),
|
|
icon: "client-edit",
|
|
disabled: false,
|
|
callback: () => {
|
|
this.channelTree.client.serverConnection.command_helper.request_playlist_list().then(lists => {
|
|
for (const entry of lists) {
|
|
if (entry.playlist_id == this.properties.client_playlist_id) {
|
|
Modals.spawnPlaylistEdit(this.channelTree.client, entry);
|
|
return;
|
|
}
|
|
}
|
|
createErrorModal(_translations.hi3i15FD || (_translations.hi3i15FD = tr("Invalid permissions")), _translations.aEP95pp4 || (_translations.aEP95pp4 = tr("You dont have to see the bots playlist."))).open();
|
|
}).catch(error => {
|
|
createErrorModal(_translations.Em4GmMYf || (_translations.Em4GmMYf = tr("Failed to query playlist.")), _translations.HjT6bOoT || (_translations.HjT6bOoT = tr("Failed to query playlist info."))).open();
|
|
});
|
|
},
|
|
type: MenuEntryType.ENTRY
|
|
}, {
|
|
name: _translations.BUWjmbJD || (_translations.BUWjmbJD = tr("Quick url replay")),
|
|
icon: "client-edit",
|
|
disabled: false,
|
|
callback: () => {
|
|
createInputModal(_translations.u0N7Wpfv || (_translations.u0N7Wpfv = tr("Please enter the URL")), _translations.isk4PsRv || (_translations.isk4PsRv = tr("URL:")), text => true, result => {
|
|
if (result) {
|
|
this.channelTree.client.serverConnection.send_command("musicbotqueueadd", {
|
|
bot_id: this.properties.client_database_id,
|
|
type: "yt",
|
|
url: result
|
|
}).catch(error => {
|
|
if (error instanceof CommandResult) {
|
|
error = error.extra_message || error.message;
|
|
}
|
|
//TODO tr
|
|
createErrorModal(_translations.E4YHyYIB || (_translations.E4YHyYIB = tr("Failed to replay url")), "Failed to enqueue url:<br>" + error).open();
|
|
});
|
|
}
|
|
}, { width: 400, maxLength: 255 }).open();
|
|
},
|
|
type: MenuEntryType.ENTRY
|
|
}, MenuEntry.HR(), ...super.assignment_context(), MenuEntry.HR(), {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-move_client_to_own_channel",
|
|
name: _translations.DNOAqnou || (_translations.DNOAqnou = tr("Move client to your channel")),
|
|
callback: () => {
|
|
this.channelTree.client.serverConnection.send_command("clientmove", {
|
|
clid: this.clientId(),
|
|
cid: this.channelTree.client.getClient().currentChannel().getChannelId()
|
|
});
|
|
}
|
|
}, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-kick_channel",
|
|
name: _translations.mtkKxwaH || (_translations.mtkKxwaH = tr("Kick client from channel")),
|
|
callback: () => {
|
|
createInputModal(_translations.envwWmFs || (_translations.envwWmFs = tr("Kick client from channel")), _translations.mfkXcBbD || (_translations.mfkXcBbD = tr("Kick reason:<br>")), text => true, result => {
|
|
if (result) {
|
|
console.log(_translations.N8PkkYgk || (_translations.N8PkkYgk = tr("Kicking client %o from channel with reason %o")), this.clientNickName(), result);
|
|
this.channelTree.client.serverConnection.send_command("clientkick", {
|
|
clid: this.clientId(),
|
|
reasonid: ViewReasonId.VREASON_CHANNEL_KICK,
|
|
reasonmsg: result
|
|
});
|
|
}
|
|
}, { width: 400, maxLength: 255 }).open();
|
|
}
|
|
}, MenuEntry.HR(), {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-volume",
|
|
name: _translations.a83GPSuP || (_translations.a83GPSuP = tr("Change local volume")),
|
|
callback: () => {
|
|
Modals.spawnChangeVolume(this.audioController.volume, volume => {
|
|
settings.changeServer("volume_client_" + this.clientUid(), volume);
|
|
this.audioController.volume = volume;
|
|
if (globalClient.selectInfo.currentSelected == this)
|
|
globalClient.selectInfo.current_manager().update_local_volume(volume);
|
|
});
|
|
}
|
|
}, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-volume",
|
|
name: _translations.vU0_4DbG || (_translations.vU0_4DbG = tr("Change remote volume")),
|
|
callback: () => {
|
|
let max_volume = this.channelTree.client.permissions.neededPermission(PermissionType.I_CLIENT_MUSIC_CREATE_MODIFY_MAX_VOLUME).value;
|
|
if (max_volume < 0)
|
|
max_volume = 100;
|
|
Modals.spawnChangeRemoteVolume(this.properties.player_volume, max_volume / 100, value => {
|
|
this.channelTree.client.serverConnection.send_command("clientedit", {
|
|
clid: this.clientId(),
|
|
player_volume: value,
|
|
}).then(() => {
|
|
if (globalClient.selectInfo.currentSelected == this)
|
|
globalClient.selectInfo.current_manager().update_remote_volume(value);
|
|
});
|
|
});
|
|
}
|
|
}, MenuEntry.HR(), {
|
|
name: _translations.ReawvrYk || (_translations.ReawvrYk = tr("Delete bot")),
|
|
icon: "client-delete",
|
|
disabled: false,
|
|
callback: () => {
|
|
const tag = $.spawn("div").append(MessageHelper.formatMessage(_translations.Iilzvtrs || (_translations.Iilzvtrs = tr("Do you really want to delete {0}")), this.createChatTag(false)));
|
|
Modals.spawnYesNo(_translations.GzAtMa7f || (_translations.GzAtMa7f = tr("Are you sure?")), $.spawn("div").append(tag), result => {
|
|
if (result) {
|
|
this.channelTree.client.serverConnection.send_command("musicbotdelete", {
|
|
bot_id: this.properties.client_database_id
|
|
});
|
|
}
|
|
});
|
|
},
|
|
type: MenuEntryType.ENTRY
|
|
}, MenuEntry.CLOSE(on_close));
|
|
}
|
|
initializeListener() {
|
|
super.initializeListener();
|
|
}
|
|
handlePlayerInfo(json) {
|
|
if (json) {
|
|
let info = JSON.map_to(new MusicClientPlayerInfo(), json);
|
|
if (this._info_promise_resolve)
|
|
this._info_promise_resolve(info);
|
|
this._info_promise_reject = undefined;
|
|
}
|
|
if (this._info_promise) {
|
|
if (this._info_promise_reject)
|
|
this._info_promise_reject("timeout");
|
|
this._info_promise = undefined;
|
|
this._info_promise_age = undefined;
|
|
this._info_promise_reject = undefined;
|
|
this._info_promise_resolve = undefined;
|
|
}
|
|
}
|
|
requestPlayerInfo(max_age = 1000) {
|
|
if (this._info_promise && this._info_promise_age && Date.now() - max_age <= this._info_promise_age)
|
|
return this._info_promise;
|
|
this._info_promise_age = Date.now();
|
|
this._info_promise = new Promise((resolve, reject) => {
|
|
this._info_promise_reject = reject;
|
|
this._info_promise_resolve = resolve;
|
|
});
|
|
this.channelTree.client.serverConnection.send_command("musicbotplayerinfo", { bot_id: this.properties.client_database_id });
|
|
return this._info_promise;
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["a2cf9f5398ab8ba40622e442d19e664992e019695aaa85a26579c2ba375729e9"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["a2cf9f5398ab8ba40622e442d19e664992e019695aaa85a26579c2ba375729e9"] = "a2cf9f5398ab8ba40622e442d19e664992e019695aaa85a26579c2ba375729e9";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "I_5eKNaW", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalCreateChannel.ts (7,31)" }, { name: "cONwhwiT", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalCreateChannel.ts (7,52)" }, { name: "aqtjtrQn", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalCreateChannel.ts (21,35)" }, { name: "AOJLpmQS", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalCreateChannel.ts (24,31)" }, { name: "PjdLwfL1", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalCreateChannel.ts (48,56)" }, { name: "_OFKRUyl", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalCreateChannel.ts (55,25)" }, { name: "K4OJG2tR", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalCreateChannel.ts (173,25)" }, { name: "EXs5RdoR", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalCreateChannel.ts (185,56)" }, { name: "liNig9Yy", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalCreateChannel.ts (192,33)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../utils/modal.ts" />
|
|
var Modals;
|
|
(function (Modals) {
|
|
function createChannelModal(channel, parent, permissions, callback) {
|
|
let properties = {}; //The changes properties
|
|
const modal = createModal({
|
|
header: channel ? _translations.I_5eKNaW || (_translations.I_5eKNaW = tr("Edit channel")) : _translations.cONwhwiT || (_translations.cONwhwiT = tr("Create channel")),
|
|
body: () => {
|
|
let template = $("#tmpl_channel_edit").renderTag(channel ? channel.properties : {
|
|
channel_flag_maxfamilyclients_unlimited: true,
|
|
channel_flag_maxclients_unlimited: true
|
|
});
|
|
return template.tabify();
|
|
},
|
|
footer: () => {
|
|
let footer = $.spawn("div");
|
|
footer.addClass("modal-button-group");
|
|
footer.css("margin", "5px");
|
|
let buttonCancel = $.spawn("button");
|
|
buttonCancel.text(_translations.aqtjtrQn || (_translations.aqtjtrQn = tr("Cancel"))).addClass("button_cancel");
|
|
let buttonOk = $.spawn("button");
|
|
buttonOk.text(_translations.AOJLpmQS || (_translations.AOJLpmQS = tr("Ok"))).addClass("button_ok");
|
|
footer.append(buttonCancel);
|
|
footer.append(buttonOk);
|
|
return footer;
|
|
},
|
|
width: 500
|
|
});
|
|
applyGeneralListener(properties, modal.htmlTag.find(".general_properties"), modal.htmlTag.find(".button_ok"), !channel);
|
|
applyStandardListener(properties, modal.htmlTag.find(".settings_standard"), modal.htmlTag.find(".button_ok"), parent, !channel);
|
|
applyPermissionListener(properties, modal.htmlTag.find(".settings_permissions"), modal.htmlTag.find(".button_ok"), permissions, channel);
|
|
applyAudioListener(properties, modal.htmlTag.find(".container-channel-settings-audio"), modal.htmlTag.find(".button_ok"), channel);
|
|
applyAdvancedListener(properties, modal.htmlTag.find(".settings_advanced"), modal.htmlTag.find(".button_ok"), channel);
|
|
let updated = [];
|
|
modal.htmlTag.find(".button_ok").click(() => {
|
|
modal.htmlTag.find(".settings_permissions").find("input[permission]").each((index, _element) => {
|
|
let element = $(_element);
|
|
if (!element.prop("changed"))
|
|
return;
|
|
let permission = permissions.resolveInfo(element.attr("permission"));
|
|
if (!permission) {
|
|
log.error(LogCategory.PERMISSIONS, _translations.PjdLwfL1 || (_translations.PjdLwfL1 = tr("Failed to resolve channel permission for name %o")), element.attr("permission"));
|
|
element.prop("disabled", true);
|
|
return;
|
|
}
|
|
updated.push(new PermissionValue(permission, element.val()));
|
|
});
|
|
console.log(_translations._OFKRUyl || (_translations._OFKRUyl = tr("Updated permissions %o")), updated);
|
|
}).click(() => {
|
|
modal.close();
|
|
callback(properties, updated); //First may create the channel
|
|
});
|
|
modal.htmlTag.find(".button_cancel").click(() => {
|
|
modal.close();
|
|
callback();
|
|
});
|
|
modal.open();
|
|
if (!channel)
|
|
modal.htmlTag.find(".channel_name").focus();
|
|
}
|
|
Modals.createChannelModal = createChannelModal;
|
|
function applyGeneralListener(properties, tag, button, create) {
|
|
let updateButton = () => {
|
|
if (tag.find(".input_error").length == 0)
|
|
button.removeAttr("disabled");
|
|
else
|
|
button.attr("disabled", "true");
|
|
};
|
|
tag.find(".channel_name").on('change keyup', function () {
|
|
properties.channel_name = this.value;
|
|
$(this).removeClass("input_error");
|
|
if (this.value.length < 1 || this.value.length > 40)
|
|
$(this).addClass("input_error");
|
|
updateButton();
|
|
}).prop("disabled", !create && !globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_NAME).granted(1));
|
|
tag.find(".channel_password").change(function () {
|
|
properties.channel_flag_password = this.value.length != 0;
|
|
if (properties.channel_flag_password)
|
|
helpers.hashPassword(this.value).then(pass => properties.channel_password = pass);
|
|
$(this).removeClass("input_error");
|
|
if (!properties.channel_flag_password)
|
|
if (globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_MODIFY_WITH_FORCE_PASSWORD).granted(1))
|
|
$(this).addClass("input_error");
|
|
updateButton();
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_PASSWORD : PermissionType.B_CHANNEL_MODIFY_PASSWORD).granted(1));
|
|
tag.find(".channel_topic").change(function () {
|
|
properties.channel_topic = this.value;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_TOPIC : PermissionType.B_CHANNEL_MODIFY_TOPIC).granted(1));
|
|
tag.find(".channel_description").change(function () {
|
|
properties.channel_description = this.value;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_DESCRIPTION : PermissionType.B_CHANNEL_MODIFY_DESCRIPTION).granted(1));
|
|
if (create) {
|
|
setTimeout(() => {
|
|
tag.find(".channel_name").trigger("change");
|
|
tag.find(".channel_password").trigger('change');
|
|
}, 0);
|
|
}
|
|
}
|
|
function applyStandardListener(properties, tag, button, parent, create) {
|
|
tag.find("input[name=\"channel_type\"]").change(function () {
|
|
switch (this.value) {
|
|
case "semi":
|
|
properties.channel_flag_permanent = false;
|
|
properties.channel_flag_semi_permanent = true;
|
|
break;
|
|
case "perm":
|
|
properties.channel_flag_permanent = true;
|
|
properties.channel_flag_semi_permanent = false;
|
|
break;
|
|
default:
|
|
properties.channel_flag_permanent = false;
|
|
properties.channel_flag_semi_permanent = false;
|
|
break;
|
|
}
|
|
});
|
|
tag.find("input[name=\"channel_type\"][value=\"temp\"]")
|
|
.prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_TEMPORARY : PermissionType.B_CHANNEL_MODIFY_MAKE_TEMPORARY).granted(1));
|
|
tag.find("input[name=\"channel_type\"][value=\"semi\"]")
|
|
.prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_SEMI_PERMANENT : PermissionType.B_CHANNEL_MODIFY_MAKE_SEMI_PERMANENT).granted(1));
|
|
tag.find("input[name=\"channel_type\"][value=\"perm\"]")
|
|
.prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_PERMANENT : PermissionType.B_CHANNEL_MODIFY_MAKE_PERMANENT).granted(1));
|
|
if (create)
|
|
tag.find("input[name=\"channel_type\"]:not(:disabled)").last().prop("checked", true).trigger('change');
|
|
tag.find("input[name=\"channel_default\"]").change(function () {
|
|
console.log(this.checked);
|
|
properties.channel_flag_default = this.checked;
|
|
let elements = tag.find("input[name=\"channel_type\"]");
|
|
elements.prop("disabled", this.checked);
|
|
if (this.checked) {
|
|
elements.prop("checked", false);
|
|
tag.find("input[name=\"channel_type\"][value=\"perm\"]").prop("checked", true).trigger("change");
|
|
}
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_PERMANENT : PermissionType.B_CHANNEL_MODIFY_MAKE_PERMANENT).granted(1) ||
|
|
!globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_DEFAULT : PermissionType.B_CHANNEL_MODIFY_MAKE_DEFAULT).granted(1));
|
|
tag.find("input[name=\"talk_power\"]").change(function () {
|
|
properties.channel_needed_talk_power = parseInt(this.value);
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_NEEDED_TALK_POWER : PermissionType.B_CHANNEL_MODIFY_NEEDED_TALK_POWER).granted(1));
|
|
let orderTag = tag.find(".order_id");
|
|
for (let channel of (parent ? parent.children() : globalClient.channelTree.rootChannel()))
|
|
$.spawn("option").attr("channelId", channel.channelId.toString()).text(channel.channelName()).appendTo(orderTag);
|
|
orderTag.change(function () {
|
|
let selected = $(this.options.item(this.selectedIndex));
|
|
properties.channel_order = parseInt(selected.attr("channelId"));
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(create ? PermissionType.B_CHANNEL_CREATE_WITH_SORTORDER : PermissionType.B_CHANNEL_MODIFY_SORTORDER).granted(1));
|
|
orderTag.find("option").last().prop("selected", true);
|
|
}
|
|
function applyPermissionListener(properties, tag, button, permissions, channel) {
|
|
let apply_permissions = (channel_permissions) => {
|
|
console.log(_translations.K4OJG2tR || (_translations.K4OJG2tR = tr("Got permissions: %o")), channel_permissions);
|
|
let required_power = -2;
|
|
for (let cperm of channel_permissions)
|
|
if (cperm.type.name == PermissionType.I_CHANNEL_NEEDED_MODIFY_POWER) {
|
|
required_power = cperm.value;
|
|
break;
|
|
}
|
|
tag.find("input[permission]").each((index, _element) => {
|
|
let element = $(_element);
|
|
let permission = permissions.resolveInfo(element.attr("permission"));
|
|
if (!permission) {
|
|
log.error(LogCategory.PERMISSIONS, _translations.EXs5RdoR || (_translations.EXs5RdoR = tr("Failed to resolve channel permission for name %o")), element.attr("permission"));
|
|
element.prop("disabled", true);
|
|
return;
|
|
}
|
|
let old_value = 0;
|
|
element.on("click keyup", () => {
|
|
console.log(_translations.liNig9Yy || (_translations.liNig9Yy = tr("Permission triggered! %o")), element.val() != old_value);
|
|
element.prop("changed", element.val() != old_value);
|
|
});
|
|
for (let cperm of channel_permissions)
|
|
if (cperm.type == permission) {
|
|
element.val(old_value = cperm.value);
|
|
return;
|
|
}
|
|
element.val(0);
|
|
});
|
|
if (!permissions.neededPermission(PermissionType.I_CHANNEL_MODIFY_POWER).granted(required_power, false)) {
|
|
tag.find("input[permission]").prop("disabled", false); //No permissions
|
|
}
|
|
};
|
|
if (channel) {
|
|
permissions.requestChannelPermissions(channel.getChannelId()).then(apply_permissions).catch((error) => {
|
|
tag.find("input[permission]").prop("disabled", true);
|
|
console.log("Failed to receive channel permissions (%o)", error);
|
|
});
|
|
}
|
|
else
|
|
apply_permissions([]);
|
|
}
|
|
function applyAudioListener(properties, tag, button, channel) {
|
|
let update_template = () => {
|
|
let codec = properties.channel_codec;
|
|
if (!codec && channel)
|
|
codec = channel.properties.channel_codec;
|
|
if (!codec)
|
|
return;
|
|
let quality = properties.channel_codec_quality;
|
|
if (!quality && channel)
|
|
quality = channel.properties.channel_codec_quality;
|
|
if (!quality)
|
|
return;
|
|
if (codec == 4 && quality == 4)
|
|
tag.find("input[name=\"voice_template\"][value=\"voice_mobile\"]").prop("checked", true);
|
|
else if (codec == 4 && quality == 6)
|
|
tag.find("input[name=\"voice_template\"][value=\"voice_desktop\"]").prop("checked", true);
|
|
else if (codec == 5 && quality == 6)
|
|
tag.find("input[name=\"voice_template\"][value=\"music\"]").prop("checked", true);
|
|
else
|
|
tag.find("input[name=\"voice_template\"][value=\"custom\"]").prop("checked", true);
|
|
};
|
|
let change_codec = codec => {
|
|
if (properties.channel_codec == codec)
|
|
return;
|
|
tag.find(".voice_codec option").prop("selected", false).eq(codec).prop("selected", true);
|
|
properties.channel_codec = codec;
|
|
update_template();
|
|
};
|
|
let quality_slider = tag.find(".voice_quality_slider");
|
|
let quality_number = tag.find(".voice_quality_number");
|
|
let change_quality = (quality) => {
|
|
if (properties.channel_codec_quality == quality)
|
|
return;
|
|
properties.channel_codec_quality = quality;
|
|
if (quality_slider.val() != quality)
|
|
quality_slider.val(quality);
|
|
if (parseInt(quality_number.text()) != quality)
|
|
quality_number.text(quality);
|
|
update_template();
|
|
};
|
|
tag.find("input[name=\"voice_template\"]").change(function () {
|
|
switch (this.value) {
|
|
case "custom":
|
|
break;
|
|
case "music":
|
|
change_codec(5);
|
|
change_quality(6);
|
|
break;
|
|
case "voice_desktop":
|
|
change_codec(4);
|
|
change_quality(6);
|
|
break;
|
|
case "voice_mobile":
|
|
change_codec(4);
|
|
change_quality(4);
|
|
break;
|
|
}
|
|
});
|
|
tag.find("input[name=\"voice_template\"][value=\"voice_mobile\"]")
|
|
.prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_MODIFY_WITH_CODEC_OPUSVOICE).granted(1));
|
|
tag.find("input[name=\"voice_template\"][value=\"voice_desktop\"]")
|
|
.prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_MODIFY_WITH_CODEC_OPUSVOICE).granted(1));
|
|
tag.find("input[name=\"voice_template\"][value=\"music\"]")
|
|
.prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_MODIFY_WITH_CODEC_OPUSMUSIC).granted(1));
|
|
let codecs = tag.find(".voice_codec option");
|
|
codecs.eq(0).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_MODIFY_WITH_CODEC_SPEEX8).granted(1));
|
|
codecs.eq(1).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_MODIFY_WITH_CODEC_SPEEX16).granted(1));
|
|
codecs.eq(2).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_MODIFY_WITH_CODEC_SPEEX32).granted(1));
|
|
codecs.eq(3).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_MODIFY_WITH_CODEC_CELTMONO48).granted(1));
|
|
codecs.eq(4).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_MODIFY_WITH_CODEC_OPUSVOICE).granted(1));
|
|
codecs.eq(5).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_MODIFY_WITH_CODEC_OPUSMUSIC).granted(1));
|
|
tag.find(".voice_codec").change(function () {
|
|
if ($(this.item(this.selectedIndex)).prop("disabled"))
|
|
return false;
|
|
change_codec(this.selectedIndex);
|
|
});
|
|
if (!channel) {
|
|
change_codec(4);
|
|
change_quality(6);
|
|
}
|
|
else {
|
|
change_codec(channel.properties.channel_codec);
|
|
change_quality(channel.properties.channel_codec_quality);
|
|
}
|
|
update_template();
|
|
quality_slider.on('input', event => change_quality(parseInt(quality_slider.val())));
|
|
}
|
|
function applyAdvancedListener(properties, tag, button, channel) {
|
|
tag.find(".channel_name_phonetic").change(function () {
|
|
properties.channel_topic = this.value;
|
|
});
|
|
tag.find(".channel_delete_delay").change(function () {
|
|
properties.channel_delete_delay = parseInt(this.value);
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_TEMP_DELETE_DELAY).granted(1));
|
|
tag.find(".channel_codec_is_unencrypted").change(function () {
|
|
properties.channel_codec_is_unencrypted = parseInt(this.value) == 0;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_MODIFY_MAKE_CODEC_ENCRYPTED).granted(1));
|
|
{
|
|
let tag_infinity = tag.find("input[name=\"max_users\"][value=\"infinity\"]");
|
|
let tag_limited = tag.find("input[name=\"max_users\"][value=\"limited\"]");
|
|
let tag_limited_value = tag.find(".channel_maxclients");
|
|
if (!globalClient.permissions.neededPermission(!channel ? PermissionType.B_CHANNEL_CREATE_WITH_MAXCLIENTS : PermissionType.B_CHANNEL_MODIFY_MAXCLIENTS).granted(1)) {
|
|
tag_infinity.prop("disabled", true);
|
|
tag_limited.prop("disabled", true);
|
|
tag_limited_value.prop("disabled", true);
|
|
}
|
|
else {
|
|
tag.find("input[name=\"max_users\"]").change(function () {
|
|
console.log(this.value);
|
|
let infinity = this.value == "infinity";
|
|
tag_limited_value.prop("disabled", infinity);
|
|
properties.channel_flag_maxclients_unlimited = infinity;
|
|
});
|
|
tag_limited_value.change(event => properties.channel_maxclients = parseInt(tag_limited_value.val()));
|
|
tag.find("input[name=\"max_users\"]:checked").trigger('change');
|
|
}
|
|
}
|
|
{
|
|
let tag_inherited = tag.find("input[name=\"max_users_family\"][value=\"inherited\"]");
|
|
let tag_infinity = tag.find("input[name=\"max_users_family\"][value=\"infinity\"]");
|
|
let tag_limited = tag.find("input[name=\"max_users_family\"][value=\"limited\"]");
|
|
let tag_limited_value = tag.find(".channel_maxfamilyclients");
|
|
if (!globalClient.permissions.neededPermission(!channel ? PermissionType.B_CHANNEL_CREATE_WITH_MAXCLIENTS : PermissionType.B_CHANNEL_MODIFY_MAXCLIENTS).granted(1)) {
|
|
tag_inherited.prop("disabled", true);
|
|
tag_infinity.prop("disabled", true);
|
|
tag_limited.prop("disabled", true);
|
|
tag_limited_value.prop("disabled", true);
|
|
}
|
|
else {
|
|
tag.find("input[name=\"max_users_family\"]").change(function () {
|
|
console.log(this.value);
|
|
tag_limited_value.prop("disabled", this.value != "limited");
|
|
properties.channel_flag_maxfamilyclients_unlimited = this.value == "infinity";
|
|
properties.channel_flag_maxfamilyclients_inherited = this.value == "inherited";
|
|
});
|
|
tag_limited_value.change(event => properties.channel_maxfamilyclients = parseInt(tag_limited_value.val()));
|
|
tag.find("input[name=\"max_users_family\"]:checked").trigger('change');
|
|
}
|
|
}
|
|
}
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["8dcbd8a70cd98a2257e1a14cbf1cf6645d3472a77e9fb1223c85f0eb8b75b0a5"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["8dcbd8a70cd98a2257e1a14cbf1cf6645d3472a77e9fb1223c85f0eb8b75b0a5"] = "8dcbd8a70cd98a2257e1a14cbf1cf6645d3472a77e9fb1223c85f0eb8b75b0a5";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "ic5s4uAG", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (92,23)" }, { name: "Im6kkByq", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (222,27)" }, { name: "wnjiw4ne", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (434,21)" }, { name: "ltEIwecC", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (437,21)" }, { name: "vf_m4UWD", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (442,21)" }, { name: "idyf3ak0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (448,23)" }, { name: "tNuuZtyu", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (450,38)" }, { name: "_R2YC2dC", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (450,58)" }, { name: "Bv07ZFZd", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (466,19)" }, { name: "vWLAAncQ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (481,23)" }, { name: "KhxDzhtu", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (483,38)" }, { name: "RjdBTdS1", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (483,71)" }, { name: "P5GiWVS7", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (501,27)" }, { name: "k9P4QCzP", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (503,42)" }, { name: "SMlzjZbN", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (503,74)" }, { name: "muNp88F6", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (518,27)" }, { name: "fmOFFQTy", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (539,27)" }, { name: "wDkblViI", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (545,90)" }, { name: "FgpUp2mr", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (547,43)" }, { name: "_5X6xyU0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (599,44)" }, { name: "D_jouOXj", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (603,52)" }, { name: "uTsNcd9d", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/view.ts (625,49)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../voice/VoiceHandler.ts" />
|
|
/// <reference path="../client.ts" />
|
|
/// <reference path="../contextMenu.ts" />
|
|
/// <reference path="../proto.ts" />
|
|
/// <reference path="channel.ts" />
|
|
/// <reference path="client.ts" />
|
|
/// <reference path="modal/ModalCreateChannel.ts" />
|
|
class ChannelTree {
|
|
constructor(client, htmlTree) {
|
|
this.currently_selected = undefined;
|
|
this.currently_selected_context_callback = undefined;
|
|
this._tree_detached = false;
|
|
document.addEventListener("touchstart", function () { }, true);
|
|
this.client = client;
|
|
this.htmlTree = htmlTree;
|
|
this.htmlTree_parent = this.htmlTree.parent();
|
|
this.client_mover = new ClientMover(this);
|
|
this.reset();
|
|
if (!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
|
|
this.htmlTree.parent().on("contextmenu", (event) => {
|
|
if (event.isDefaultPrevented())
|
|
return;
|
|
for (const element of document.elementsFromPoint(event.pageX, event.pageY))
|
|
if (element.classList.contains("channelLine") || element.classList.contains("client"))
|
|
return;
|
|
event.preventDefault();
|
|
if ($.isArray(this.currently_selected)) { //Multiselect
|
|
(this.currently_selected_context_callback || ((_) => null))(event);
|
|
}
|
|
else {
|
|
this.onSelect(undefined);
|
|
this.showContextMenu(event.pageX, event.pageY);
|
|
}
|
|
});
|
|
}
|
|
this.htmlTree.on('resize', this.handle_resized.bind(this));
|
|
/* TODO release these events again when ChannelTree get deinitialized */
|
|
$(document).on('click', event => {
|
|
if (this.selected_event != event.originalEvent)
|
|
this.selected_event = undefined;
|
|
});
|
|
$(document).on('keydown', this.handle_key_press.bind(this));
|
|
this.htmlTree.on('click', event => {
|
|
{
|
|
this.selected_event = event.originalEvent;
|
|
}
|
|
});
|
|
}
|
|
hide_channel_tree() {
|
|
this.htmlTree.detach();
|
|
this._tree_detached = true;
|
|
}
|
|
show_channel_tree() {
|
|
this._tree_detached = false;
|
|
this.htmlTree.appendTo(this.htmlTree_parent);
|
|
this.channels.forEach(e => e.recalculate_repetitive_name());
|
|
}
|
|
showContextMenu(x, y, on_close = undefined) {
|
|
let channelCreate = this.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_TEMPORARY).granted(1) ||
|
|
this.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_SEMI_PERMANENT).granted(1) ||
|
|
this.client.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_PERMANENT).granted(1);
|
|
spawn_context_menu(x, y, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-channel_create",
|
|
name: _translations.ic5s4uAG || (_translations.ic5s4uAG = tr("Create channel")),
|
|
invalidPermission: !channelCreate,
|
|
callback: () => this.spawnCreateChannel()
|
|
}, MenuEntry.CLOSE(on_close));
|
|
}
|
|
initialiseHead(serverName, address) {
|
|
this.server = new ServerEntry(this, serverName, address);
|
|
this.server.htmlTag.appendTo(this.htmlTree);
|
|
this.server.initializeListener();
|
|
}
|
|
__deleteAnimation(element) {
|
|
let tag = element instanceof ChannelEntry ? element.rootTag() : element.tag;
|
|
this.htmlTree.find(tag).fadeOut("slow", () => {
|
|
tag.remove();
|
|
});
|
|
}
|
|
rootChannel() {
|
|
return this.channels.filter(e => e.parent == undefined);
|
|
}
|
|
deleteChannel(channel) {
|
|
const _this = this;
|
|
for (let index = 0; index < this.channels.length; index++) {
|
|
let entry = this.channels[index];
|
|
let currentEntry = this.channels[index];
|
|
while (currentEntry != undefined && currentEntry != null) {
|
|
if (currentEntry == channel) {
|
|
_this.channels.remove(entry);
|
|
_this.__deleteAnimation(entry);
|
|
entry.channelTree = null;
|
|
index--;
|
|
break;
|
|
}
|
|
else
|
|
currentEntry = currentEntry.parent_channel();
|
|
}
|
|
}
|
|
this.channels.remove(channel);
|
|
this.__deleteAnimation(channel);
|
|
channel.channelTree = null;
|
|
if (channel.channel_previous)
|
|
channel.channel_previous.channel_next = channel.channel_next;
|
|
if (channel.channel_next)
|
|
channel.channel_next.channel_previous = channel.channel_previous;
|
|
if (channel == this.channel_first)
|
|
this.channel_first = channel.channel_next;
|
|
if (channel == this.channel_last)
|
|
this.channel_last = channel.channel_previous;
|
|
}
|
|
insertChannel(channel) {
|
|
channel.channelTree = this;
|
|
this.channels.push(channel);
|
|
let elm = undefined;
|
|
let tag = this.htmlTree;
|
|
let previous_channel = null;
|
|
if (channel.hasParent()) {
|
|
let parent = channel.parent_channel();
|
|
let siblings = parent.children();
|
|
if (siblings.length == 0) {
|
|
elm = parent.rootTag();
|
|
previous_channel = null;
|
|
}
|
|
else {
|
|
previous_channel = siblings.last();
|
|
elm = previous_channel.tag;
|
|
}
|
|
tag = parent.siblingTag();
|
|
}
|
|
else {
|
|
previous_channel = this.channel_last;
|
|
if (!this.channel_last)
|
|
this.channel_last = channel;
|
|
if (!this.channel_first)
|
|
this.channel_first = channel;
|
|
}
|
|
channel.channel_previous = previous_channel;
|
|
channel.channel_next = undefined;
|
|
if (previous_channel) {
|
|
channel.channel_next = previous_channel.channel_next;
|
|
previous_channel.channel_next = channel;
|
|
if (channel.channel_next)
|
|
channel.channel_next.channel_previous = channel;
|
|
}
|
|
let entry = channel.rootTag();
|
|
if (!this._tree_detached)
|
|
entry.css({ display: "none" }).fadeIn("slow");
|
|
entry.appendTo(tag);
|
|
if (elm != undefined)
|
|
elm.after(entry);
|
|
if (channel.channel_previous == channel) /* shall never happen */
|
|
channel.channel_previous = undefined;
|
|
if (channel.channel_next == channel) /* shall never happen */
|
|
channel.channel_next = undefined;
|
|
channel.initializeListener();
|
|
channel.update_family_index();
|
|
}
|
|
findChannel(channelId) {
|
|
for (let index = 0; index < this.channels.length; index++)
|
|
if (this.channels[index].getChannelId() == channelId)
|
|
return this.channels[index];
|
|
return undefined;
|
|
}
|
|
find_channel_by_name(name, parent, force_parent = true) {
|
|
for (let index = 0; index < this.channels.length; index++)
|
|
if (this.channels[index].channelName() == name && (!force_parent || parent == this.channels[index].parent))
|
|
return this.channels[index];
|
|
return undefined;
|
|
}
|
|
moveChannel(channel, channel_previous, parent) {
|
|
if (channel_previous != null && channel_previous.parent != parent) {
|
|
console.error(_translations.Im6kkByq || (_translations.Im6kkByq = tr("Invalid channel move (different parents! (%o|%o)")), channel_previous.parent, parent);
|
|
return;
|
|
}
|
|
if (channel.channel_next)
|
|
channel.channel_next.channel_previous = channel.channel_previous;
|
|
if (channel.channel_previous)
|
|
channel.channel_previous.channel_next = channel.channel_next;
|
|
if (channel == this.channel_last)
|
|
this.channel_last = channel.channel_previous;
|
|
if (channel == this.channel_first)
|
|
this.channel_first = channel.channel_next;
|
|
channel.channel_next = undefined;
|
|
channel.channel_previous = channel_previous;
|
|
channel.parent = parent;
|
|
if (channel_previous) {
|
|
if (channel_previous == this.channel_last)
|
|
this.channel_last = channel;
|
|
channel.channel_next = channel_previous.channel_next;
|
|
channel_previous.channel_next = channel;
|
|
channel_previous.rootTag().after(channel.rootTag());
|
|
if (channel.channel_next)
|
|
channel.channel_next.channel_previous = channel;
|
|
}
|
|
else {
|
|
if (parent) {
|
|
let children = parent.children();
|
|
if (children.length <= 1) { //Self should be already in there
|
|
let left = channel.rootTag();
|
|
left.appendTo(parent.siblingTag());
|
|
channel.channel_next = undefined;
|
|
}
|
|
else {
|
|
channel.channel_previous = undefined;
|
|
channel.rootTag().prependTo(parent.siblingTag());
|
|
channel.channel_next = children[1]; /* children 0 shall be the channel itself */
|
|
channel.channel_next.channel_previous = channel;
|
|
}
|
|
}
|
|
else {
|
|
this.htmlTree.find(".server").after(channel.rootTag());
|
|
channel.channel_next = this.channel_first;
|
|
if (this.channel_first)
|
|
this.channel_first.channel_previous = channel;
|
|
this.channel_first = channel;
|
|
}
|
|
}
|
|
channel.update_family_index();
|
|
channel.children(true).forEach(e => e.update_family_index());
|
|
channel.clients(true).forEach(e => e.update_family_index());
|
|
if (channel.channel_previous == channel) { /* shall never happen */
|
|
channel.channel_previous = undefined;
|
|
debugger;
|
|
}
|
|
if (channel.channel_next == channel) { /* shall never happen */
|
|
channel.channel_next = undefined;
|
|
debugger;
|
|
}
|
|
}
|
|
deleteClient(client) {
|
|
this.clients.remove(client);
|
|
this.__deleteAnimation(client);
|
|
client.onDelete();
|
|
}
|
|
insertClient(client, channel) {
|
|
let newClient = this.findClient(client.clientId());
|
|
if (newClient)
|
|
client = newClient; //Got new client :)
|
|
else
|
|
this.clients.push(client);
|
|
client.channelTree = this;
|
|
client["_channel"] = channel;
|
|
let tag = client.tag;
|
|
if (!this._show_queries && client.properties.client_type == ClientType.CLIENT_QUERY)
|
|
client.tag.hide();
|
|
else if (!this._tree_detached)
|
|
tag.css("display", "none").fadeIn("slow");
|
|
tag.appendTo(channel.clientTag());
|
|
client.currentChannel().reorderClients();
|
|
channel.updateChannelTypeIcon();
|
|
client.update_family_index();
|
|
return client;
|
|
}
|
|
registerClient(client) {
|
|
this.clients.push(client);
|
|
client.channelTree = this;
|
|
}
|
|
moveClient(client, channel) {
|
|
let oldChannel = client.currentChannel();
|
|
client["_channel"] = channel;
|
|
let tag = client.tag;
|
|
tag.detach();
|
|
tag.appendTo(client.currentChannel().clientTag());
|
|
if (oldChannel) {
|
|
oldChannel.updateChannelTypeIcon();
|
|
}
|
|
if (client.currentChannel()) {
|
|
client.currentChannel().reorderClients();
|
|
client.currentChannel().updateChannelTypeIcon();
|
|
}
|
|
client.updateClientStatusIcons();
|
|
client.update_family_index();
|
|
}
|
|
findClient(clientId) {
|
|
for (let index = 0; index < this.clients.length; index++) {
|
|
if (this.clients[index].clientId() == clientId)
|
|
return this.clients[index];
|
|
}
|
|
return undefined;
|
|
}
|
|
find_client_by_dbid(client_dbid) {
|
|
for (let index = 0; index < this.clients.length; index++) {
|
|
if (this.clients[index].properties.client_database_id == client_dbid)
|
|
return this.clients[index];
|
|
}
|
|
return undefined;
|
|
}
|
|
find_client_by_unique_id(unique_id) {
|
|
for (let index = 0; index < this.clients.length; index++) {
|
|
if (this.clients[index].properties.client_unique_identifier == unique_id)
|
|
return this.clients[index];
|
|
}
|
|
return undefined;
|
|
}
|
|
static same_selected_type(a, b) {
|
|
if (a instanceof ChannelEntry)
|
|
return b instanceof ChannelEntry;
|
|
if (a instanceof ClientEntry)
|
|
return b instanceof ClientEntry;
|
|
if (a instanceof ServerEntry)
|
|
return b instanceof ServerEntry;
|
|
return a == b;
|
|
}
|
|
onSelect(entry, enforce_single, flag_shift) {
|
|
console.log("Select: " + entry);
|
|
if (this.currently_selected && (ppt.key_pressed(ppt.SpecialKey.SHIFT) || flag_shift) && entry instanceof ClientEntry) { //Currently we're only supporting client multiselects :D
|
|
if (!entry)
|
|
return; //Nowhere
|
|
if ($.isArray(this.currently_selected)) {
|
|
if (!ChannelTree.same_selected_type(this.currently_selected[0], entry))
|
|
return; //Not the same type
|
|
}
|
|
else if (ChannelTree.same_selected_type(this.currently_selected, entry)) {
|
|
this.currently_selected = [this.currently_selected];
|
|
}
|
|
if (entry instanceof ChannelEntry)
|
|
this.currently_selected_context_callback = this.callback_multiselect_channel.bind(this);
|
|
if (entry instanceof ClientEntry)
|
|
this.currently_selected_context_callback = this.callback_multiselect_client.bind(this);
|
|
}
|
|
else
|
|
this.currently_selected = undefined;
|
|
if (!$.isArray(this.currently_selected) || enforce_single) {
|
|
this.currently_selected = entry;
|
|
this.htmlTree.find(".selected").each(function (idx, e) {
|
|
$(e).removeClass("selected");
|
|
});
|
|
}
|
|
else {
|
|
for (const e of this.currently_selected)
|
|
if (e == entry) {
|
|
this.currently_selected.remove(e);
|
|
if (entry instanceof ChannelEntry)
|
|
entry.channelTag().removeClass("selected");
|
|
else if (entry instanceof ClientEntry)
|
|
entry.tag.removeClass("selected");
|
|
else if (entry instanceof ServerEntry)
|
|
entry.htmlTag.removeClass("selected");
|
|
if (this.currently_selected.length == 1)
|
|
this.currently_selected = this.currently_selected[0];
|
|
else if (this.currently_selected.length == 0)
|
|
this.currently_selected = undefined;
|
|
//Already selected
|
|
return;
|
|
}
|
|
this.currently_selected.push(entry);
|
|
}
|
|
if (entry instanceof ChannelEntry)
|
|
entry.channelTag().addClass("selected");
|
|
else if (entry instanceof ClientEntry)
|
|
entry.tag.addClass("selected");
|
|
else if (entry instanceof ServerEntry)
|
|
entry.htmlTag.addClass("selected");
|
|
this.client.selectInfo.setCurrentSelected($.isArray(this.currently_selected) ? undefined : entry);
|
|
}
|
|
callback_multiselect_channel(event) {
|
|
console.log(_translations.wnjiw4ne || (_translations.wnjiw4ne = tr("Multiselect channel")));
|
|
}
|
|
callback_multiselect_client(event) {
|
|
console.log(_translations.ltEIwecC || (_translations.ltEIwecC = tr("Multiselect client")));
|
|
const clients = this.currently_selected;
|
|
const music_only = clients.map(e => e instanceof MusicClientEntry ? 0 : 1).reduce((a, b) => a + b, 0) == 0;
|
|
const music_entry = clients.map(e => e instanceof MusicClientEntry ? 1 : 0).reduce((a, b) => a + b, 0) > 0;
|
|
const local_client = clients.map(e => e instanceof LocalClientEntry ? 1 : 0).reduce((a, b) => a + b, 0) > 0;
|
|
console.log(_translations.vf_m4UWD || (_translations.vf_m4UWD = tr("Music only: %o | Container music: %o | Container local: %o")), music_entry, music_entry, local_client);
|
|
let entries = [];
|
|
if (!music_entry && !local_client) { //Music bots or local client cant be poked
|
|
entries.push({
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-poke",
|
|
name: _translations.idyf3ak0 || (_translations.idyf3ak0 = tr("Poke clients")),
|
|
callback: () => {
|
|
createInputModal(_translations.tNuuZtyu || (_translations.tNuuZtyu = tr("Poke clients")), _translations._R2YC2dC || (_translations._R2YC2dC = tr("Poke message:<br>")), text => true, result => {
|
|
if (typeof (result) === "string") {
|
|
for (const client of this.currently_selected)
|
|
this.client.serverConnection.send_command("clientpoke", {
|
|
clid: client.clientId(),
|
|
msg: result
|
|
});
|
|
}
|
|
}, { width: 400, maxLength: 512 }).open();
|
|
}
|
|
});
|
|
}
|
|
entries.push({
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-move_client_to_own_channel",
|
|
name: _translations.Bv07ZFZd || (_translations.Bv07ZFZd = tr("Move clients to your channel")),
|
|
callback: () => {
|
|
const target = this.client.getClient().currentChannel().getChannelId();
|
|
for (const client of clients)
|
|
this.client.serverConnection.send_command("clientmove", {
|
|
clid: client.clientId(),
|
|
cid: target
|
|
});
|
|
}
|
|
});
|
|
if (!local_client) { //local client cant be kicked and/or banned or kicked
|
|
entries.push(MenuEntry.HR());
|
|
entries.push({
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-kick_channel",
|
|
name: _translations.vWLAAncQ || (_translations.vWLAAncQ = tr("Kick clients from channel")),
|
|
callback: () => {
|
|
createInputModal(_translations.KhxDzhtu || (_translations.KhxDzhtu = tr("Kick clients from channel")), _translations.RjdBTdS1 || (_translations.RjdBTdS1 = tr("Kick reason:<br>")), text => true, result => {
|
|
if (result) {
|
|
for (const client of clients)
|
|
this.client.serverConnection.send_command("clientkick", {
|
|
clid: client.clientId(),
|
|
reasonid: ViewReasonId.VREASON_CHANNEL_KICK,
|
|
reasonmsg: result
|
|
});
|
|
}
|
|
}, { width: 400, maxLength: 255 }).open();
|
|
}
|
|
});
|
|
if (!music_entry) { //Music bots cant be banned or kicked
|
|
entries.push({
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-kick_server",
|
|
name: _translations.P5GiWVS7 || (_translations.P5GiWVS7 = tr("Kick clients fom server")),
|
|
callback: () => {
|
|
createInputModal(_translations.k9P4QCzP || (_translations.k9P4QCzP = tr("Kick clients from server")), _translations.SMlzjZbN || (_translations.SMlzjZbN = tr("Kick reason:<br>")), text => true, result => {
|
|
if (result) {
|
|
for (const client of clients)
|
|
this.client.serverConnection.send_command("clientkick", {
|
|
clid: client.clientId(),
|
|
reasonid: ViewReasonId.VREASON_SERVER_KICK,
|
|
reasonmsg: result
|
|
});
|
|
}
|
|
}, { width: 400, maxLength: 255 }).open();
|
|
}
|
|
}, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-ban_client",
|
|
name: _translations.muNp88F6 || (_translations.muNp88F6 = tr("Ban clients")),
|
|
invalidPermission: !this.client.permissions.neededPermission(PermissionType.I_CLIENT_BAN_MAX_BANTIME).granted(1),
|
|
callback: () => {
|
|
Modals.spawnBanClient((clients).map(entry => entry.clientNickName()), (data) => {
|
|
for (const client of clients)
|
|
this.client.serverConnection.send_command("banclient", {
|
|
uid: client.properties.client_unique_identifier,
|
|
banreason: data.reason,
|
|
time: data.length
|
|
}, {
|
|
flagset: [data.no_ip ? "no-ip" : "", data.no_hwid ? "no-hardware-id" : "", data.no_name ? "no-nickname" : ""]
|
|
}).then(() => {
|
|
sound.play(Sound.USER_BANNED);
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
if (music_only) {
|
|
entries.push(MenuEntry.HR());
|
|
entries.push({
|
|
name: _translations.fmOFFQTy || (_translations.fmOFFQTy = tr("Delete bots")),
|
|
icon: "client-delete",
|
|
disabled: false,
|
|
callback: () => {
|
|
const param_string = clients.map((_, index) => "{" + index + "}").join(', ');
|
|
const param_values = clients.map(client => client.createChatTag(true));
|
|
const tag = $.spawn("div").append(...MessageHelper.formatMessage((_translations.wDkblViI || (_translations.wDkblViI = tr("Do you really want to delete "))) + param_string, ...param_values));
|
|
const tag_container = $.spawn("div").append(tag);
|
|
Modals.spawnYesNo(_translations.FgpUp2mr || (_translations.FgpUp2mr = tr("Are you sure?")), tag_container, result => {
|
|
if (result) {
|
|
for (const client of clients)
|
|
this.client.serverConnection.send_command("musicbotdelete", {
|
|
botid: client.properties.client_database_id
|
|
});
|
|
}
|
|
});
|
|
},
|
|
type: MenuEntryType.ENTRY
|
|
});
|
|
}
|
|
}
|
|
spawn_context_menu(event.pageX, event.pageY, ...entries);
|
|
}
|
|
clientsByGroup(group) {
|
|
let result = [];
|
|
for (let client of this.clients) {
|
|
if (client.groupAssigned(group))
|
|
result.push(client);
|
|
}
|
|
return result;
|
|
}
|
|
clientsByChannel(channel) {
|
|
let result = [];
|
|
for (let client of this.clients) {
|
|
if (client.currentChannel() == channel)
|
|
result.push(client);
|
|
}
|
|
return result;
|
|
}
|
|
reset() {
|
|
this.server = null;
|
|
this.clients = [];
|
|
this.channels = [];
|
|
this.htmlTree.children().detach(); //Do not remove the listener!
|
|
this.channel_first = undefined;
|
|
this.channel_last = undefined;
|
|
}
|
|
spawnCreateChannel(parent) {
|
|
Modals.createChannelModal(undefined, parent, this.client.permissions, (properties, permissions) => {
|
|
if (!properties)
|
|
return;
|
|
properties["cpid"] = parent ? parent.channelId : 0;
|
|
log.debug(LogCategory.CHANNEL, _translations._5X6xyU0 || (_translations._5X6xyU0 = tr("Creating a new channel.\nProperties: %o\nPermissions: %o")), properties);
|
|
this.client.serverConnection.send_command("channelcreate", properties).then(() => {
|
|
let channel = this.find_channel_by_name(properties.channel_name, parent, true);
|
|
if (!channel) {
|
|
log.error(LogCategory.CHANNEL, _translations.D_jouOXj || (_translations.D_jouOXj = tr("Failed to resolve channel after creation. Could not apply permissions!")));
|
|
return;
|
|
}
|
|
if (permissions && permissions.length > 0) {
|
|
let perms = [];
|
|
for (let perm of permissions) {
|
|
perms.push({
|
|
permvalue: perm.value,
|
|
permnegated: false,
|
|
permskip: false,
|
|
permid: perm.type.id
|
|
});
|
|
}
|
|
perms[0]["cid"] = channel.channelId;
|
|
return this.client.serverConnection.send_command("channeladdperm", perms, {
|
|
flagset: ["continueonerror"]
|
|
}).then(() => new Promise(resolve => { resolve(channel); }));
|
|
}
|
|
return new Promise(resolve => { resolve(channel); });
|
|
}).then(channel => {
|
|
chat.serverChat().appendMessage(_translations.uTsNcd9d || (_translations.uTsNcd9d = tr("Channel {} successfully created!")), true, channel.generate_tag(true));
|
|
sound.play(Sound.CHANNEL_CREATED);
|
|
});
|
|
});
|
|
}
|
|
handle_resized() {
|
|
for (let channel of this.channels)
|
|
channel.handle_frame_resized();
|
|
}
|
|
select_next_channel(channel, select_client) {
|
|
if (select_client) {
|
|
const clients = channel.clients_ordered();
|
|
if (clients.length > 0) {
|
|
this.onSelect(clients[0], true);
|
|
return;
|
|
}
|
|
}
|
|
const children = channel.children();
|
|
if (children.length > 0) {
|
|
this.onSelect(children[0], true);
|
|
return;
|
|
}
|
|
const next = channel.channel_next;
|
|
if (next) {
|
|
this.onSelect(next, true);
|
|
return;
|
|
}
|
|
let parent = channel.parent_channel();
|
|
while (parent) {
|
|
const p_next = parent.channel_next;
|
|
if (p_next) {
|
|
this.onSelect(p_next, true);
|
|
return;
|
|
}
|
|
parent = parent.parent_channel();
|
|
}
|
|
}
|
|
handle_key_press(event) {
|
|
if (!this.selected_event || !this.currently_selected || $.isArray(this.currently_selected))
|
|
return;
|
|
if (event.keyCode == 38 /* ArrowUp */) {
|
|
event.preventDefault();
|
|
if (this.currently_selected instanceof ChannelEntry) {
|
|
let previous = this.currently_selected.channel_previous;
|
|
if (previous) {
|
|
while (true) {
|
|
const siblings = previous.children();
|
|
if (siblings.length == 0)
|
|
break;
|
|
previous = siblings.last();
|
|
}
|
|
const clients = previous.clients_ordered();
|
|
if (clients.length > 0) {
|
|
this.onSelect(clients.last(), true);
|
|
return;
|
|
}
|
|
else {
|
|
this.onSelect(previous, true);
|
|
return;
|
|
}
|
|
}
|
|
else if (this.currently_selected.hasParent()) {
|
|
const channel = this.currently_selected.parent_channel();
|
|
const clients = channel.clients_ordered();
|
|
if (clients.length > 0) {
|
|
this.onSelect(clients.last(), true);
|
|
return;
|
|
}
|
|
else {
|
|
this.onSelect(channel, true);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
this.onSelect(this.server, true);
|
|
}
|
|
else if (this.currently_selected instanceof ClientEntry) {
|
|
const channel = this.currently_selected.currentChannel();
|
|
const clients = channel.clients_ordered();
|
|
const index = clients.indexOf(this.currently_selected);
|
|
if (index > 0) {
|
|
this.onSelect(clients[index - 1], true);
|
|
return;
|
|
}
|
|
this.onSelect(channel, true);
|
|
return;
|
|
}
|
|
}
|
|
else if (event.keyCode == 40 /* ArrowDown */) {
|
|
event.preventDefault();
|
|
if (this.currently_selected instanceof ChannelEntry) {
|
|
this.select_next_channel(this.currently_selected, true);
|
|
}
|
|
else if (this.currently_selected instanceof ClientEntry) {
|
|
const channel = this.currently_selected.currentChannel();
|
|
const clients = channel.clients_ordered();
|
|
const index = clients.indexOf(this.currently_selected);
|
|
if (index + 1 < clients.length) {
|
|
this.onSelect(clients[index + 1], true);
|
|
return;
|
|
}
|
|
this.select_next_channel(channel, false);
|
|
}
|
|
else if (this.currently_selected instanceof ServerEntry)
|
|
this.onSelect(this.channel_first, true);
|
|
}
|
|
else if (event.keyCode == 13 /* Enter */) {
|
|
if (this.currently_selected instanceof ChannelEntry) {
|
|
this.currently_selected.joinChannel();
|
|
}
|
|
}
|
|
}
|
|
toggle_server_queries(flag) {
|
|
if (this._show_queries == flag)
|
|
return;
|
|
this._show_queries = flag;
|
|
const channels = [];
|
|
for (const client of this.clients)
|
|
if (client.properties.client_type == ClientType.CLIENT_QUERY) {
|
|
if (this._show_queries)
|
|
client.tag.show();
|
|
else
|
|
client.tag.hide();
|
|
if (channels.indexOf(client.currentChannel()) == -1)
|
|
channels.push(client.currentChannel());
|
|
}
|
|
}
|
|
get_first_channel() {
|
|
return this.channel_first;
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["151ae612934d91357c22d60a4d6af0e9c521ac18c46cbfa0f9d312cf353292a3"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["151ae612934d91357c22d60a4d6af0e9c521ac18c46cbfa0f9d312cf353292a3"] = "151ae612934d91357c22d60a4d6af0e9c521ac18c46cbfa0f9d312cf353292a3";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="client.ts" />
|
|
if (typeof (customElements) !== "undefined") {
|
|
try {
|
|
class X_Properties extends HTMLElement {
|
|
}
|
|
class X_Property extends HTMLElement {
|
|
}
|
|
customElements.define('x-properties', X_Properties, { extends: 'div' });
|
|
customElements.define('x-property', X_Property, { extends: 'div' });
|
|
}
|
|
catch (error) {
|
|
console.warn("failed to define costum elements");
|
|
}
|
|
}
|
|
class StaticSettings {
|
|
static get instance() {
|
|
if (!this._instance)
|
|
this._instance = new StaticSettings(true);
|
|
return this._instance;
|
|
}
|
|
static transformStO(input, _default) {
|
|
if (typeof input === "undefined")
|
|
return _default;
|
|
if (typeof _default === "string")
|
|
return input;
|
|
else if (typeof _default === "number")
|
|
return parseInt(input);
|
|
else if (typeof _default === "boolean")
|
|
return (input == "1" || input == "true");
|
|
else if (typeof _default === "undefined")
|
|
return input;
|
|
return JSON.parse(input);
|
|
}
|
|
static transformOtS(input) {
|
|
if (typeof input === "string")
|
|
return input;
|
|
else if (typeof input === "number")
|
|
return input.toString();
|
|
else if (typeof input === "boolean")
|
|
return input ? "1" : "0";
|
|
else if (typeof input === "undefined")
|
|
return undefined;
|
|
return JSON.stringify(input);
|
|
}
|
|
constructor(_reserved = undefined) {
|
|
if (_reserved && !StaticSettings._instance) {
|
|
this._staticPropsTag = $("#properties");
|
|
this.initializeStatic();
|
|
}
|
|
else {
|
|
this._handle = StaticSettings.instance;
|
|
}
|
|
}
|
|
initializeStatic() {
|
|
location.search.substr(1).split("&").forEach(part => {
|
|
let item = part.split("=");
|
|
$("<x-property></x-property>")
|
|
.attr("key", item[0])
|
|
.attr("value", item[1])
|
|
.appendTo(this._staticPropsTag);
|
|
});
|
|
}
|
|
static(key, _default) {
|
|
if (this._handle)
|
|
return this._handle.static(key, _default);
|
|
let result = this._staticPropsTag.find("[key='" + key + "']");
|
|
return StaticSettings.transformStO(result.length > 0 ? decodeURIComponent(result.last().attr("value")) : undefined, _default);
|
|
}
|
|
deleteStatic(key) {
|
|
if (this._handle) {
|
|
this._handle.deleteStatic(key);
|
|
return;
|
|
}
|
|
let result = this._staticPropsTag.find("[key='" + key + "']");
|
|
if (result.length != 0)
|
|
result.detach();
|
|
}
|
|
}
|
|
class Settings extends StaticSettings {
|
|
constructor() {
|
|
super();
|
|
this.cacheGlobal = {};
|
|
this.cacheServer = {};
|
|
this.updated = false;
|
|
this.cacheGlobal = JSON.parse(localStorage.getItem("settings.global"));
|
|
if (!this.cacheGlobal)
|
|
this.cacheGlobal = {};
|
|
this.saveWorker = setInterval(() => {
|
|
if (this.updated)
|
|
this.save();
|
|
}, 5 * 1000);
|
|
}
|
|
static_global(key, _default) {
|
|
let _static = this.static(key);
|
|
if (_static)
|
|
return StaticSettings.transformStO(_static, _default);
|
|
return this.global(key, _default);
|
|
}
|
|
global(key, _default) {
|
|
let result = this.cacheGlobal[key];
|
|
return StaticSettings.transformStO(result, _default);
|
|
}
|
|
server(key, _default) {
|
|
let result = this.cacheServer[key];
|
|
return StaticSettings.transformStO(result, _default);
|
|
}
|
|
changeGlobal(key, value) {
|
|
if (this.cacheGlobal[key] == value)
|
|
return;
|
|
this.updated = true;
|
|
this.cacheGlobal[key] = StaticSettings.transformOtS(value);
|
|
if (Settings.UPDATE_DIRECT)
|
|
this.save();
|
|
}
|
|
changeServer(key, value) {
|
|
if (this.cacheServer[key] == value)
|
|
return;
|
|
this.updated = true;
|
|
this.cacheServer[key] = StaticSettings.transformOtS(value);
|
|
if (Settings.UPDATE_DIRECT)
|
|
this.save();
|
|
}
|
|
setServer(server) {
|
|
if (this.currentServer) {
|
|
this.save();
|
|
this.cacheServer = {};
|
|
this.currentServer = undefined;
|
|
}
|
|
this.currentServer = server;
|
|
if (this.currentServer) {
|
|
let serverId = this.currentServer.properties.virtualserver_unique_identifier;
|
|
this.cacheServer = JSON.parse(localStorage.getItem("settings.server_" + serverId));
|
|
if (!this.cacheServer)
|
|
this.cacheServer = {};
|
|
}
|
|
}
|
|
save() {
|
|
this.updated = false;
|
|
if (this.currentServer) {
|
|
let serverId = this.currentServer.properties.virtualserver_unique_identifier;
|
|
let server = JSON.stringify(this.cacheServer);
|
|
localStorage.setItem("settings.server_" + serverId, server);
|
|
}
|
|
let global = JSON.stringify(this.cacheGlobal);
|
|
localStorage.setItem("settings.global", global);
|
|
}
|
|
}
|
|
Settings.KEY_DISABLE_CONTEXT_MENU = "disableContextMenu";
|
|
Settings.KEY_DISABLE_UNLOAD_DIALOG = "disableUnloadDialog";
|
|
Settings.UPDATE_DIRECT = true;
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["5d36be1b22073610ea6ef1da2b21930a0adbcf36af90d5700bd24d85808d3fe6"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["5d36be1b22073610ea6ef1da2b21930a0adbcf36af90d5700bd24d85808d3fe6"] = "5d36be1b22073610ea6ef1da2b21930a0adbcf36af90d5700bd24d85808d3fe6";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/*
|
|
Copyright (C) 2011 Patrick Gillespie, http://patorjk.com/
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
THE SOFTWARE.
|
|
*/
|
|
/*
|
|
Extendible BBCode Parser v1.0.0
|
|
By Patrick Gillespie (patorjk@gmail.com)
|
|
Website: http://patorjk.com/
|
|
|
|
This module allows you to parse BBCode and to extend to the mark-up language
|
|
to add in your own tags.
|
|
*/
|
|
var XBBCODE;
|
|
(function (XBBCODE) {
|
|
// -----------------------------------------------------------------------------
|
|
// Set up private variables
|
|
// -----------------------------------------------------------------------------
|
|
const urlPattern = /^(?:https?|file|c):(?:\/{1,3}|\\{1})[-a-zA-Z0-9:;,@#%&()~_?\+=\/\\\.]*$/, colorNamePattern = /^(?:aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dodgerblue|firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|gray|green|greenyellow|honeydew|hotpink|indianred|indigo|ivory|khaki|lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgray|lightgreen|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightsteelblue|lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|purple|red|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|violet|wheat|white|whitesmoke|yellow|yellowgreen)$/, colorCodePattern = /^#?[a-fA-F0-9]{6}$/, emailPattern = /[^\s@]+@[^\s@]+\.[^\s@]+/, fontFacePattern = /^([a-z][a-z0-9_]+|"[a-z][a-z0-9_\s]+")$/i;
|
|
let tagList, tagsNoParseList = [], bbRegExp, pbbRegExp, pbbRegExp2, openTags, closeTags;
|
|
/* -----------------------------------------------------------------------------
|
|
* _tags
|
|
* This object contains a list of _tags that your code will be able to understand.
|
|
* Each tag object has the following properties:
|
|
*
|
|
* openTag - A function that takes in the tag's parameters (if any) and its
|
|
* contents, and returns what its HTML open tag should be.
|
|
* Example: [color=red]test[/color] would take in "=red" as a
|
|
* parameter input, and "test" as a content input.
|
|
* It should be noted that any BBCode inside of "content" will have
|
|
* been processed by the time it enter the openTag function.
|
|
*
|
|
* closeTag - A function that takes in the tag's parameters (if any) and its
|
|
* contents, and returns what its HTML close tag should be.
|
|
*
|
|
* displayContent - Defaults to true. If false, the content for the tag will
|
|
* not be displayed. This is useful for _tags like IMG where
|
|
* its contents are actually a parameter input.
|
|
*
|
|
* restrictChildrenTo - A list of BBCode _tags which are allowed to be nested
|
|
* within this BBCode tag. If this property is omitted,
|
|
* any BBCode tag may be nested within the tag.
|
|
*
|
|
* restrictParentsTo - A list of BBCode _tags which are allowed to be parents of
|
|
* this BBCode tag. If this property is omitted, any BBCode
|
|
* tag may be a parent of the tag.
|
|
*
|
|
* noParse - true or false. If true, none of the content WITHIN this tag will be
|
|
* parsed by the XBBCode parser.
|
|
*
|
|
*
|
|
*
|
|
* LIMITIONS on adding NEW TAGS:
|
|
* - Tag names should be alphanumeric (including underscores) and all _tags should have an opening tag
|
|
* and a closing tag.
|
|
* The [*] tag is an exception because it was already a standard
|
|
* bbcode tag. Technecially _tags don't *have* to be alphanumeric, but since
|
|
* regular expressions are used to parse the text, if you use a non-alphanumeric
|
|
* tag names, just make sure the tag name gets escaped properly (if needed).
|
|
* --------------------------------------------------------------------------- */
|
|
let _tags = {
|
|
"b": {
|
|
openTag: function (params, content) {
|
|
return '<span class="xbbcode-b">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
}
|
|
},
|
|
/*
|
|
This tag does nothing and is here mostly to be used as a classification for
|
|
the bbcode input when evaluating parent-child tag relationships
|
|
*/
|
|
"bbcode": {
|
|
openTag: function (params, content) {
|
|
return '';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '';
|
|
}
|
|
},
|
|
"center": {
|
|
openTag: function (params, content) {
|
|
return '<span class="xbbcode-center">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
}
|
|
},
|
|
"code": {
|
|
openTag: function (params, content) {
|
|
return '<span class="xbbcode-code">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
},
|
|
noParse: true
|
|
},
|
|
"color": {
|
|
openTag: function (params, content) {
|
|
params = params || '';
|
|
var colorCode = (params.substr(1)).toLowerCase() || "black";
|
|
colorNamePattern.lastIndex = 0;
|
|
colorCodePattern.lastIndex = 0;
|
|
if (!colorNamePattern.test(colorCode)) {
|
|
if (!colorCodePattern.test(colorCode)) {
|
|
colorCode = "black";
|
|
}
|
|
else {
|
|
if (colorCode.substr(0, 1) !== "#") {
|
|
colorCode = "#" + colorCode;
|
|
}
|
|
}
|
|
}
|
|
return '<span style="color:' + colorCode + '">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
}
|
|
},
|
|
"email": {
|
|
openTag: function (params, content) {
|
|
var myEmail;
|
|
if (!params) {
|
|
myEmail = content.replace(/<.*?>/g, "");
|
|
}
|
|
else {
|
|
myEmail = params.substr(1);
|
|
}
|
|
emailPattern.lastIndex = 0;
|
|
if (!emailPattern.test(myEmail)) {
|
|
return '<a>';
|
|
}
|
|
return '<a href="mailto:' + myEmail + '">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</a>';
|
|
}
|
|
},
|
|
"face": {
|
|
openTag: function (params, content) {
|
|
params = params || '';
|
|
var faceCode = params.substr(1) || "inherit";
|
|
fontFacePattern.lastIndex = 0;
|
|
if (!fontFacePattern.test(faceCode)) {
|
|
faceCode = "inherit";
|
|
}
|
|
return '<span style="font-family:' + faceCode + '">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
}
|
|
},
|
|
"font": {
|
|
openTag: function (params, content) {
|
|
params = params || '';
|
|
var faceCode = params.substr(1) || "inherit";
|
|
fontFacePattern.lastIndex = 0;
|
|
if (!fontFacePattern.test(faceCode)) {
|
|
faceCode = "inherit";
|
|
}
|
|
return '<span style="font-family:' + faceCode + '">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
}
|
|
},
|
|
"i": {
|
|
openTag: function (params, content) {
|
|
return '<span class="xbbcode-i">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
}
|
|
},
|
|
"img": {
|
|
openTag: function (params, content) {
|
|
var myUrl = content;
|
|
urlPattern.lastIndex = 0;
|
|
if (!urlPattern.test(myUrl)) {
|
|
myUrl = "";
|
|
}
|
|
return '<img src="' + myUrl + '" />';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '';
|
|
},
|
|
displayContent: false
|
|
},
|
|
"justify": {
|
|
openTag: function (params, content) {
|
|
return '<span class="xbbcode-justify">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
}
|
|
},
|
|
"large": {
|
|
openTag: function (params, content) {
|
|
params = params || '';
|
|
var colorCode = params.substr(1) || "inherit";
|
|
colorNamePattern.lastIndex = 0;
|
|
colorCodePattern.lastIndex = 0;
|
|
if (!colorNamePattern.test(colorCode)) {
|
|
if (!colorCodePattern.test(colorCode)) {
|
|
colorCode = "inherit";
|
|
}
|
|
else {
|
|
if (colorCode.substr(0, 1) !== "#") {
|
|
colorCode = "#" + colorCode;
|
|
}
|
|
}
|
|
}
|
|
return '<span class="xbbcode-size-36" style="color:' + colorCode + '">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
}
|
|
},
|
|
"left": {
|
|
openTag: function (params, content) {
|
|
return '<span class="xbbcode-left">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
}
|
|
},
|
|
"li": {
|
|
openTag: function (params, content) {
|
|
return "<li>";
|
|
},
|
|
closeTag: function (params, content) {
|
|
return "</li>";
|
|
},
|
|
restrictParentsTo: ["list", "ul", "ol"]
|
|
},
|
|
"list": {
|
|
openTag: function (params, content) {
|
|
return '<ul>';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</ul>';
|
|
},
|
|
restrictChildrenTo: ["*", "li"]
|
|
},
|
|
"noparse": {
|
|
openTag: function (params, content) {
|
|
return '';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '';
|
|
},
|
|
noParse: true
|
|
},
|
|
"ol": {
|
|
openTag: function (params, content) {
|
|
return '<ol>';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</ol>';
|
|
},
|
|
restrictChildrenTo: ["*", "li"]
|
|
},
|
|
"php": {
|
|
openTag: function (params, content) {
|
|
return '<span class="xbbcode-code">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
},
|
|
noParse: true
|
|
},
|
|
"quote": {
|
|
openTag: function (params, content) {
|
|
return '<blockquote class="xbbcode-blockquote">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</blockquote>';
|
|
}
|
|
},
|
|
"right": {
|
|
openTag: function (params, content) {
|
|
return '<span class="xbbcode-right">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
}
|
|
},
|
|
"s": {
|
|
openTag: function (params, content) {
|
|
return '<span class="xbbcode-s">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
}
|
|
},
|
|
"size": {
|
|
openTag: function (params, content) {
|
|
params = params || '';
|
|
var mySize = parseInt(params.substr(1), 10) || 0;
|
|
if (mySize < 4 || mySize > 40) {
|
|
mySize = 14;
|
|
}
|
|
return '<span class="xbbcode-size-' + mySize + '">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
}
|
|
},
|
|
"small": {
|
|
openTag: function (params, content) {
|
|
params = params || '';
|
|
var colorCode = params.substr(1) || "inherit";
|
|
colorNamePattern.lastIndex = 0;
|
|
colorCodePattern.lastIndex = 0;
|
|
if (!colorNamePattern.test(colorCode)) {
|
|
if (!colorCodePattern.test(colorCode)) {
|
|
colorCode = "inherit";
|
|
}
|
|
else {
|
|
if (colorCode.substr(0, 1) !== "#") {
|
|
colorCode = "#" + colorCode;
|
|
}
|
|
}
|
|
}
|
|
return '<span class="xbbcode-size-10" style="color:' + colorCode + '">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
}
|
|
},
|
|
"sub": {
|
|
openTag: function (params, content) {
|
|
return '<sub>';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</sub>';
|
|
}
|
|
},
|
|
"sup": {
|
|
openTag: function (params, content) {
|
|
return '<sup>';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</sup>';
|
|
}
|
|
},
|
|
"table": {
|
|
openTag: function (params, content) {
|
|
return '<table class="xbbcode-table">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</table>';
|
|
},
|
|
restrictChildrenTo: ["tbody", "thead", "tfoot", "tr"]
|
|
},
|
|
"tbody": {
|
|
openTag: function (params, content) {
|
|
return '<tbody>';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</tbody>';
|
|
},
|
|
restrictChildrenTo: ["tr"],
|
|
restrictParentsTo: ["table"]
|
|
},
|
|
"tfoot": {
|
|
openTag: function (params, content) {
|
|
return '<tfoot>';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</tfoot>';
|
|
},
|
|
restrictChildrenTo: ["tr"],
|
|
restrictParentsTo: ["table"]
|
|
},
|
|
"thead": {
|
|
openTag: function (params, content) {
|
|
return '<thead class="xbbcode-thead">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</thead>';
|
|
},
|
|
restrictChildrenTo: ["tr"],
|
|
restrictParentsTo: ["table"]
|
|
},
|
|
"td": {
|
|
openTag: function (params, content) {
|
|
return '<td class="xbbcode-td">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</td>';
|
|
},
|
|
restrictParentsTo: ["tr"]
|
|
},
|
|
"th": {
|
|
openTag: function (params, content) {
|
|
return '<th class="xbbcode-th">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</th>';
|
|
},
|
|
restrictParentsTo: ["tr"]
|
|
},
|
|
"tr": {
|
|
openTag: function (params, content) {
|
|
return '<tr class="xbbcode-tr">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</tr>';
|
|
},
|
|
restrictChildrenTo: ["td", "th"],
|
|
restrictParentsTo: ["table", "tbody", "tfoot", "thead"]
|
|
},
|
|
"u": {
|
|
openTag: function (params, content) {
|
|
return '<span class="xbbcode-u">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</span>';
|
|
}
|
|
},
|
|
"ul": {
|
|
openTag: function (params, content) {
|
|
return '<ul>';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</ul>';
|
|
},
|
|
restrictChildrenTo: ["*", "li"]
|
|
},
|
|
"url": {
|
|
openTag: function (params, content) {
|
|
let myUrl;
|
|
if (!params) {
|
|
myUrl = content.replace(/<.*?>/g, "");
|
|
}
|
|
else {
|
|
myUrl = params.substr(1);
|
|
}
|
|
urlPattern.lastIndex = 0;
|
|
if (!urlPattern.test(myUrl)) {
|
|
myUrl = "#";
|
|
}
|
|
return '<a href="' + myUrl + '" target="_blank">';
|
|
},
|
|
closeTag: function (params, content) {
|
|
return '</a>';
|
|
}
|
|
},
|
|
"hr": {
|
|
openTag: (params, content) => {
|
|
return "<hr/>";
|
|
},
|
|
closeTag: (params, content) => {
|
|
return "";
|
|
}
|
|
},
|
|
/*
|
|
The [*] tag is special since the user does not define a closing [/*] tag when writing their bbcode.
|
|
Instead this module parses the code and adds the closing [/*] tag in for them. None of the _tags you
|
|
add will act like this and this tag is an exception to the others.
|
|
*/
|
|
"*": {
|
|
openTag: function (params, content) {
|
|
return "<li>";
|
|
},
|
|
closeTag: function (params, content) {
|
|
return "</li>";
|
|
},
|
|
restrictParentsTo: ["list", "ul", "ol"]
|
|
}
|
|
};
|
|
// create tag list and lookup fields
|
|
function initTags() {
|
|
tagList = [];
|
|
let prop, ii, len;
|
|
for (prop in _tags) {
|
|
if (_tags.hasOwnProperty(prop)) {
|
|
if (prop === "*") {
|
|
tagList.push("\\" + prop);
|
|
}
|
|
else {
|
|
tagList.push(prop);
|
|
if (_tags[prop].noParse) {
|
|
tagsNoParseList.push(prop);
|
|
}
|
|
}
|
|
_tags[prop].validChildLookup = {};
|
|
_tags[prop].validParentLookup = {};
|
|
_tags[prop].restrictParentsTo = _tags[prop].restrictParentsTo || [];
|
|
_tags[prop].restrictChildrenTo = _tags[prop].restrictChildrenTo || [];
|
|
len = _tags[prop].restrictChildrenTo.length;
|
|
for (ii = 0; ii < len; ii++) {
|
|
_tags[prop].validChildLookup[_tags[prop].restrictChildrenTo[ii]] = true;
|
|
}
|
|
len = _tags[prop].restrictParentsTo.length;
|
|
for (ii = 0; ii < len; ii++) {
|
|
_tags[prop].validParentLookup[_tags[prop].restrictParentsTo[ii]] = true;
|
|
}
|
|
}
|
|
}
|
|
bbRegExp = new RegExp("<bbcl=([0-9]+) (" + tagList.join("|") + ")([ =][^>]*?)?>((?:.|[\\r\\n])*?)<bbcl=\\1 /\\2>", "gi");
|
|
pbbRegExp = new RegExp("\\[(" + tagList.join("|") + ")([ =][^\\]]*?)?\\]([^\\[]*?)\\[/\\1\\]", "gi");
|
|
pbbRegExp2 = new RegExp("\\[(" + tagsNoParseList.join("|") + ")([ =][^\\]]*?)?\\]([\\s\\S]*?)\\[/\\1\\]", "gi");
|
|
// create the regex for escaping ['s that aren't apart of _tags
|
|
(function () {
|
|
var closeTagList = [];
|
|
for (var ii = 0; ii < tagList.length; ii++) {
|
|
if (tagList[ii] !== "\\*") { // the * tag doesn't have an offical closing tag
|
|
closeTagList.push("/" + tagList[ii]);
|
|
}
|
|
}
|
|
openTags = new RegExp("(\\[)((?:" + tagList.join("|") + ")(?:[ =][^\\]]*?)?)(\\])", "gi");
|
|
closeTags = new RegExp("(\\[)(" + closeTagList.join("|") + ")(\\])", "gi");
|
|
})();
|
|
}
|
|
initTags();
|
|
// -----------------------------------------------------------------------------
|
|
// private functions
|
|
// -----------------------------------------------------------------------------
|
|
function checkParentChildRestrictions(parentTag, bbcode, bbcodeLevel, tagName, tagParams, tagContents, errQueue) {
|
|
errQueue = errQueue || [];
|
|
bbcodeLevel++;
|
|
// get a list of all of the child _tags to this tag
|
|
var reTagNames = new RegExp("(<bbcl=" + bbcodeLevel + " )(" + tagList.join("|") + ")([ =>])", "gi"), reTagNamesParts = new RegExp("(<bbcl=" + bbcodeLevel + " )(" + tagList.join("|") + ")([ =>])", "i"), matchingTags = tagContents.match(reTagNames) || [], cInfo, errStr, ii, childTag, pInfo = _tags[parentTag] || {};
|
|
reTagNames.lastIndex = 0;
|
|
if (!matchingTags) {
|
|
tagContents = "";
|
|
}
|
|
for (ii = 0; ii < matchingTags.length; ii++) {
|
|
reTagNamesParts.lastIndex = 0;
|
|
childTag = (matchingTags[ii].match(reTagNamesParts))[2].toLowerCase();
|
|
if (pInfo && pInfo.restrictChildrenTo && pInfo.restrictChildrenTo.length > 0) {
|
|
if (!pInfo.validChildLookup[childTag]) {
|
|
errStr = "The tag \"" + childTag + "\" is not allowed as a child of the tag \"" + parentTag + "\".";
|
|
errQueue.push(errStr);
|
|
}
|
|
}
|
|
cInfo = _tags[childTag] || {};
|
|
if (cInfo.restrictParentsTo.length > 0) {
|
|
if (!cInfo.validParentLookup[parentTag]) {
|
|
errStr = "The tag \"" + parentTag + "\" is not allowed as a parent of the tag \"" + childTag + "\".";
|
|
errQueue.push(errStr);
|
|
}
|
|
}
|
|
}
|
|
tagContents = tagContents.replace(bbRegExp, function (matchStr, bbcodeLevel, tagName, tagParams, tagContents) {
|
|
errQueue = checkParentChildRestrictions(tagName.toLowerCase(), matchStr, bbcodeLevel, tagName, tagParams, tagContents, errQueue);
|
|
return matchStr;
|
|
});
|
|
return errQueue;
|
|
}
|
|
/*
|
|
This function updates or adds a piece of metadata to each tag called "bbcl" which
|
|
indicates how deeply nested a particular tag was in the bbcode. This property is removed
|
|
from the HTML code _tags at the end of the processing.
|
|
*/
|
|
function updateTagDepths(tagContents) {
|
|
tagContents = tagContents.replace(/\<([^\>][^\>]*?)\>/gi, function (matchStr, subMatchStr) {
|
|
var bbCodeLevel = subMatchStr.match(/^bbcl=([0-9]+) /);
|
|
if (bbCodeLevel === null) {
|
|
return "<bbcl=0 " + subMatchStr + ">";
|
|
}
|
|
else {
|
|
return "<" + subMatchStr.replace(/^(bbcl=)([0-9]+)/, function (matchStr, m1, m2) {
|
|
return m1 + (parseInt(m2, 10) + 1);
|
|
}) + ">";
|
|
}
|
|
});
|
|
return tagContents;
|
|
}
|
|
/*
|
|
This function removes the metadata added by the updateTagDepths function
|
|
*/
|
|
function unprocess(tagContent) {
|
|
return tagContent.replace(/<bbcl=[0-9]+ \/\*>/gi, "").replace(/<bbcl=[0-9]+ /gi, "[").replace(/>/gi, "]");
|
|
}
|
|
var replaceFunct = function (matchStr, bbcodeLevel, tagName, tagParams, tagContents) {
|
|
tagName = tagName.toLowerCase();
|
|
var processedContent = _tags[tagName].noParse ? unprocess(tagContents) : tagContents.replace(bbRegExp, replaceFunct), openTag = _tags[tagName].openTag(tagParams, processedContent), closeTag = _tags[tagName].closeTag(tagParams, processedContent);
|
|
if (_tags[tagName].displayContent === false) {
|
|
processedContent = "";
|
|
}
|
|
return openTag + processedContent + closeTag;
|
|
};
|
|
function parse(config) {
|
|
var output = config.text;
|
|
output = output.replace(bbRegExp, replaceFunct);
|
|
return output;
|
|
}
|
|
/*
|
|
The star tag [*] is special in that it does not use a closing tag. Since this parser requires that _tags to have a closing
|
|
tag, we must pre-process the input and add in closing _tags [/*] for the star tag.
|
|
We have a little levaridge in that we know the text we're processing wont contain the <> characters (they have been
|
|
changed into their HTML entity form to prevent XSS and code injection), so we can use those characters as markers to
|
|
help us define boundaries and figure out where to place the [/*] _tags.
|
|
*/
|
|
function fixStarTag(text) {
|
|
text = text.replace(/\[(?!\*[ =\]]|list([ =][^\]]*)?\]|\/list[\]])/ig, "<");
|
|
text = text.replace(/\[(?=list([ =][^\]]*)?\]|\/list[\]])/ig, ">");
|
|
while (text !== (text = text.replace(/>list([ =][^\]]*)?\]([^>]*?)(>\/list])/gi, function (matchStr, contents, endTag) {
|
|
var innerListTxt = matchStr;
|
|
while (innerListTxt !== (innerListTxt = innerListTxt.replace(/\[\*\]([^\[]*?)(\[\*\]|>\/list])/i, function (matchStr, contents, endTag) {
|
|
if (endTag.toLowerCase() === ">/list]") {
|
|
endTag = "</*]</list]";
|
|
}
|
|
else {
|
|
endTag = "</*][*]";
|
|
}
|
|
return "<*]" + contents + endTag;
|
|
})))
|
|
;
|
|
innerListTxt = innerListTxt.replace(/>/g, "<");
|
|
return innerListTxt;
|
|
})))
|
|
;
|
|
// add ['s for our _tags back in
|
|
text = text.replace(/</g, "[");
|
|
return text;
|
|
}
|
|
function addBbcodeLevels(text) {
|
|
while (text !== (text = text.replace(pbbRegExp, function (matchStr, tagName, tagParams, tagContents) {
|
|
matchStr = matchStr.replace(/\[/g, "<");
|
|
matchStr = matchStr.replace(/\]/g, ">");
|
|
return updateTagDepths(matchStr);
|
|
})))
|
|
;
|
|
return text;
|
|
}
|
|
// -----------------------------------------------------------------------------
|
|
// public functions
|
|
// -----------------------------------------------------------------------------
|
|
// API, Expose all available _tags
|
|
function tags() {
|
|
return _tags;
|
|
}
|
|
XBBCODE.tags = tags;
|
|
;
|
|
function addTags(...tags) {
|
|
for (const tag of tags)
|
|
_tags[tag.tag] = tag.function;
|
|
initTags();
|
|
}
|
|
XBBCODE.addTags = addTags;
|
|
;
|
|
class ProcessResult {
|
|
}
|
|
XBBCODE.ProcessResult = ProcessResult;
|
|
function process(config) {
|
|
let result = new ProcessResult();
|
|
result.errorQueue = [];
|
|
config.text = config.text.replace(/</g, "<"); // escape HTML tag brackets
|
|
config.text = config.text.replace(/>/g, ">"); // escape HTML tag brackets
|
|
config.text = config.text.replace(openTags, function (matchStr, openB, contents, closeB) {
|
|
return "<" + contents + ">";
|
|
});
|
|
config.text = config.text.replace(closeTags, function (matchStr, openB, contents, closeB) {
|
|
return "<" + contents + ">";
|
|
});
|
|
config.text = config.text.replace(/\[/g, "["); // escape ['s that aren't apart of _tags
|
|
config.text = config.text.replace(/\]/g, "]"); // escape ['s that aren't apart of _tags
|
|
config.text = config.text.replace(/</g, "["); // escape ['s that aren't apart of _tags
|
|
config.text = config.text.replace(/>/g, "]"); // escape ['s that aren't apart of _tags
|
|
// process _tags that don't have their content parsed
|
|
while (config.text !== (config.text = config.text.replace(pbbRegExp2, function (matchStr, tagName, tagParams, tagContents) {
|
|
tagContents = tagContents.replace(/\[/g, "[");
|
|
tagContents = tagContents.replace(/\]/g, "]");
|
|
tagParams = tagParams || "";
|
|
tagContents = tagContents || "";
|
|
return "[" + tagName + tagParams + "]" + tagContents + "[/" + tagName + "]";
|
|
})))
|
|
;
|
|
config.text = fixStarTag(config.text); // add in closing _tags for the [*] tag
|
|
config.text = config.text.replace(/\[hr](?!.*\[\/hr])/gmi, "[hr][/hr]"); /* fix hr tag */
|
|
config.text = addBbcodeLevels(config.text); // add in level metadata
|
|
result.errorQueue = checkParentChildRestrictions("bbcode", config.text, -1, "", "", config.text);
|
|
result.html = parse(config);
|
|
if (result.html.indexOf("[") !== -1 || result.html.indexOf("]") !== -1) {
|
|
result.errorQueue.push("Some _tags appear to be misaligned.");
|
|
}
|
|
if (config.removeMisalignedTags) {
|
|
result.html = result.html.replace(/\[.*?\]/g, "");
|
|
}
|
|
if (config.addInLineBreaks) {
|
|
result.html = '<div style="white-space:pre-wrap;" class="xbbcode">' + result.html + '</div>';
|
|
}
|
|
if (!config.escapeHtml) {
|
|
result.html = result.html.replace("[", "["); // put ['s back in
|
|
result.html = result.html.replace("]", "]"); // put ['s back in
|
|
}
|
|
if (result.errorQueue.length == 0) {
|
|
result.error = false;
|
|
result.errorQueue = undefined;
|
|
}
|
|
else {
|
|
result.error = true;
|
|
}
|
|
return result;
|
|
}
|
|
XBBCODE.process = process;
|
|
;
|
|
})(XBBCODE || (XBBCODE = {}));
|
|
// for node
|
|
if (typeof module !== "undefined") {
|
|
module.exports = XBBCODE;
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["7b297ca7625a51ff8c0e02125b8afcc7469dbd2971f36884c9d121b9f3df9433"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["7b297ca7625a51ff8c0e02125b8afcc7469dbd2971f36884c9d121b9f3df9433"] = "7b297ca7625a51ff8c0e02125b8afcc7469dbd2971f36884c9d121b9f3df9433";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "sYG_CjvV", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (95,21)" }, { name: "foGudfH1", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (143,30)" }, { name: "XUKsV23g", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (172,30)" }, { name: "AqbuoGOP", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (183,23)" }, { name: "MxJZzPra", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (436,49)" }, { name: "olQ_3zdj", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (438,60)" }, { name: "LqrvULtX", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (446,69)" }, { name: "EscvNJt1", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (466,54)" }, { name: "O7zlMfzk", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (466,112)" }, { name: "YQnthsII", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (479,54)" }, { name: "xB8wZniv", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (479,113)" }, { name: "aNEaYUft", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (491,50)" }, { name: "Fdt8TwbH", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (491,108)" }, { name: "nf70fBUO", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (514,50)" }, { name: "rpDxx1_J", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (514,83)" }, { name: "KS3oJM_V", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (523,50)" }, { name: "c_RawLvr", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (523,81)" }, { name: "DT6FshRi", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (535,50)" }, { name: "kL1M5jAc", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (535,77)" }, { name: "LkHqtJYO", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (537,50)" }, { name: "vBpIbVBl", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (537,83)" }, { name: "TIA5kbb9", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (700,25)" }, { name: "w6veI4_R", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (701,25)" }, { name: "PzHxNyIZ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/SelectedItemInfo.ts (702,25)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../client.ts" />
|
|
/// <reference path="../../../../vendor/bbcode/xbbcode.ts" />
|
|
class InfoManagerBase {
|
|
constructor() {
|
|
this.timers = [];
|
|
this.intervals = [];
|
|
}
|
|
resetTimers() {
|
|
for (let timer of this.timers)
|
|
clearTimeout(timer);
|
|
this.timers = [];
|
|
}
|
|
resetIntervals() {
|
|
for (let interval of this.intervals)
|
|
clearInterval(interval);
|
|
this.intervals = [];
|
|
}
|
|
registerTimer(timer) {
|
|
this.timers.push(timer);
|
|
}
|
|
registerInterval(interval) {
|
|
this.intervals.push(interval);
|
|
}
|
|
}
|
|
class InfoManager extends InfoManagerBase {
|
|
createFrame(handle, object, html_tag) {
|
|
this.handle = handle;
|
|
}
|
|
finalizeFrame(object, frame) {
|
|
this.resetIntervals();
|
|
this.resetTimers();
|
|
this.handle = undefined;
|
|
}
|
|
triggerUpdate() {
|
|
if (this.handle)
|
|
this.handle.update();
|
|
}
|
|
}
|
|
class InfoBar {
|
|
constructor(client, htmlTag) {
|
|
this._current_manager = undefined;
|
|
this.managers = [];
|
|
this.handle = client;
|
|
this._htmlTag = htmlTag;
|
|
this._tag_info = htmlTag.find(".container-select-info");
|
|
this._tag_banner = htmlTag.find(".container-banner");
|
|
this.managers.push(new MusicInfoManager());
|
|
this.managers.push(new ClientInfoManager());
|
|
this.managers.push(new ChannelInfoManager());
|
|
this.managers.push(new ServerInfoManager());
|
|
this.banner_manager = new Hostbanner(client, this._tag_banner);
|
|
}
|
|
setCurrentSelected(entry) {
|
|
if (this.current_selected == entry)
|
|
return;
|
|
if (this._current_manager) {
|
|
this._current_manager.finalizeFrame(this.current_selected, this._tag_info);
|
|
this._current_manager = null;
|
|
this.current_selected = null;
|
|
}
|
|
this._tag_info.empty();
|
|
this.current_selected = entry;
|
|
for (let manager of this.managers) {
|
|
if (manager.available(this.current_selected)) {
|
|
this._current_manager = manager;
|
|
break;
|
|
}
|
|
}
|
|
console.log(_translations.sYG_CjvV || (_translations.sYG_CjvV = tr("Using info manager: %o")), this._current_manager);
|
|
if (this._current_manager)
|
|
this._current_manager.createFrame(this, this.current_selected, this._tag_info);
|
|
}
|
|
get currentSelected() {
|
|
return this.current_selected;
|
|
}
|
|
update() {
|
|
if (this._current_manager && this.current_selected)
|
|
this._current_manager.updateFrame(this.current_selected, this._tag_info);
|
|
}
|
|
update_banner() {
|
|
this.banner_manager.update();
|
|
}
|
|
current_manager() { return this._current_manager; }
|
|
html_tag() { return this._htmlTag; }
|
|
}
|
|
class Hostbanner {
|
|
constructor(client, htmlTag) {
|
|
this.client = client;
|
|
this.html_tag = htmlTag;
|
|
}
|
|
update() {
|
|
if (this.updater) {
|
|
clearTimeout(this.updater);
|
|
this.updater = undefined;
|
|
}
|
|
const tag = this.generate_tag();
|
|
if (tag) {
|
|
tag.then(element => {
|
|
this.html_tag.empty();
|
|
this.html_tag.append(element).removeClass("disabled");
|
|
}).catch(error => {
|
|
console.warn(_translations.foGudfH1 || (_translations.foGudfH1 = tr("Failed to load hostbanner: %o")), error);
|
|
this.html_tag.empty().addClass("disabled");
|
|
});
|
|
}
|
|
else {
|
|
this.html_tag.empty().addClass("disabled");
|
|
}
|
|
}
|
|
generate_tag() {
|
|
if (!this.client.connected)
|
|
return undefined;
|
|
const server = this.client.channelTree.server;
|
|
if (!server)
|
|
return undefined;
|
|
if (!server.properties.virtualserver_hostbanner_gfx_url)
|
|
return undefined;
|
|
let properties = {};
|
|
for (let key in server.properties)
|
|
properties["property_" + key] = server.properties[key];
|
|
if (server.properties.virtualserver_hostbanner_gfx_interval > 0) {
|
|
const update_interval = Math.min(server.properties.virtualserver_hostbanner_gfx_interval, 60);
|
|
const update_timestamp = (Math.floor((Date.now() / 1000) / update_interval) * update_interval).toString();
|
|
try {
|
|
const url = new URL(server.properties.virtualserver_hostbanner_gfx_url);
|
|
if (url.search.length == 0)
|
|
properties["cache_tag"] = "?_ts=" + update_timestamp;
|
|
else
|
|
properties["cache_tag"] = "&_ts=" + update_timestamp;
|
|
}
|
|
catch (error) {
|
|
console.warn(_translations.XUKsV23g || (_translations.XUKsV23g = tr("Failed to parse banner URL: %o")), error);
|
|
properties["cache_tag"] = "&_ts=" + update_timestamp;
|
|
}
|
|
this.updater = setTimeout(() => this.update(), update_interval * 1000);
|
|
}
|
|
else {
|
|
properties["cache_tag"] = "";
|
|
}
|
|
const rendered = $("#tmpl_selected_hostbanner").renderTag(properties);
|
|
console.debug(_translations.AqbuoGOP || (_translations.AqbuoGOP = tr("Hostbanner has been loaded")));
|
|
return Promise.resolve(rendered);
|
|
/*
|
|
const image = rendered.find("img");
|
|
return new Promise<JQuery<HTMLElement>>((resolve, reject) => {
|
|
const node_image = image[0] as HTMLImageElement;
|
|
node_image.onload = () => {
|
|
console.debug(tr("Hostbanner has been loaded"));
|
|
if(server.properties.virtualserver_hostbanner_gfx_interval > 0)
|
|
this.updater = setTimeout(() => this.update(), Math.min(server.properties.virtualserver_hostbanner_gfx_interval, 60) * 1000);
|
|
resolve(rendered);
|
|
};
|
|
node_image.onerror = event => {
|
|
reject(event);
|
|
}
|
|
});
|
|
*/
|
|
}
|
|
}
|
|
class ClientInfoManager extends InfoManager {
|
|
available(object) {
|
|
return typeof object == "object" && object instanceof ClientEntry;
|
|
}
|
|
createFrame(handle, client, html_tag) {
|
|
super.createFrame(handle, client, html_tag);
|
|
client.updateClientVariables();
|
|
this.updateFrame(client, html_tag);
|
|
}
|
|
updateFrame(client, html_tag) {
|
|
this.resetIntervals();
|
|
html_tag.empty();
|
|
let properties = this.buildProperties(client);
|
|
let rendered = $("#tmpl_selected_client").renderTag(properties);
|
|
html_tag.append(rendered);
|
|
this.registerInterval(setInterval(() => {
|
|
html_tag.find(".update_onlinetime").text(formatDate(client.calculateOnlineTime()));
|
|
}, 1000));
|
|
}
|
|
buildProperties(client) {
|
|
let properties = {};
|
|
properties["client_name"] = client.createChatTag()[0];
|
|
properties["client_onlinetime"] = formatDate(client.calculateOnlineTime());
|
|
properties["sound_volume"] = client.audioController.volume * 100;
|
|
properties["client_is_query"] = client.properties.client_type == ClientType.CLIENT_QUERY;
|
|
properties["group_server"] = [];
|
|
for (let groupId of client.assignedServerGroupIds()) {
|
|
let group = client.channelTree.client.groups.serverGroup(groupId);
|
|
if (!group)
|
|
continue;
|
|
let group_property = {};
|
|
group_property["group_id"] = groupId;
|
|
group_property["group_name"] = group.name;
|
|
properties["group_server"].push(group_property);
|
|
properties["group_" + groupId + "_icon"] = client.channelTree.client.fileManager.icons.generateTag(group.properties.iconid);
|
|
}
|
|
let group = client.channelTree.client.groups.channelGroup(client.assignedChannelGroup());
|
|
if (group) {
|
|
properties["group_channel"] = group.id;
|
|
properties["group_" + group.id + "_name"] = group.name;
|
|
properties["group_" + group.id + "_icon"] = client.channelTree.client.fileManager.icons.generateTag(group.properties.iconid);
|
|
}
|
|
for (let key in client.properties)
|
|
properties["property_" + key] = client.properties[key];
|
|
if (client.properties.client_teaforum_id > 0) {
|
|
properties["teaspeak_forum"] = $.spawn("a")
|
|
.attr("href", "//forum.teaspeak.de/index.php?members/" + client.properties.client_teaforum_id)
|
|
.attr("target", "_blank")
|
|
.text(client.properties.client_teaforum_id);
|
|
}
|
|
if (client.properties.client_flag_avatar && client.properties.client_flag_avatar.length > 0) {
|
|
properties["client_avatar"] = client.channelTree.client.fileManager.avatars.generateTag(client);
|
|
}
|
|
return properties;
|
|
}
|
|
}
|
|
class ServerInfoManager extends InfoManager {
|
|
createFrame(handle, server, html_tag) {
|
|
super.createFrame(handle, server, html_tag);
|
|
if (server.shouldUpdateProperties())
|
|
server.updateProperties();
|
|
this.updateFrame(server, html_tag);
|
|
}
|
|
updateFrame(server, html_tag) {
|
|
this.resetIntervals();
|
|
html_tag.empty();
|
|
let properties = {};
|
|
properties["server_name"] = $.spawn("a").text(server.properties.virtualserver_name);
|
|
properties["server_onlinetime"] = formatDate(server.calculateUptime());
|
|
properties["server_address"] = server.remote_address.host + ":" + server.remote_address.port;
|
|
for (let key in server.properties)
|
|
properties["property_" + key] = server.properties[key];
|
|
let rendered = $("#tmpl_selected_server").renderTag([properties]);
|
|
this.registerInterval(setInterval(() => {
|
|
html_tag.find(".update_onlinetime").text(formatDate(server.calculateUptime()));
|
|
}, 1000));
|
|
{
|
|
let requestUpdate = rendered.find(".btn_update");
|
|
requestUpdate.prop("disabled", !server.shouldUpdateProperties());
|
|
requestUpdate.click(() => {
|
|
server.updateProperties();
|
|
this.triggerUpdate();
|
|
});
|
|
this.registerTimer(setTimeout(function () {
|
|
requestUpdate.prop("disabled", false);
|
|
}, server.nextInfoRequest - Date.now()));
|
|
}
|
|
html_tag.append(rendered);
|
|
}
|
|
available(object) {
|
|
return typeof object == "object" && object instanceof ServerEntry;
|
|
}
|
|
}
|
|
class ChannelInfoManager extends InfoManager {
|
|
createFrame(handle, channel, html_tag) {
|
|
super.createFrame(handle, channel, html_tag);
|
|
this.updateFrame(channel, html_tag);
|
|
}
|
|
updateFrame(channel, html_tag) {
|
|
this.resetIntervals();
|
|
html_tag.empty();
|
|
let properties = {};
|
|
properties["channel_name"] = channel.generate_tag(false);
|
|
properties["channel_type"] = ChannelType.normalize(channel.channelType());
|
|
properties["channel_clients"] = channel.channelTree.clientsByChannel(channel).length;
|
|
properties["channel_subscribed"] = true; //TODO
|
|
properties["server_encryption"] = channel.channelTree.server.properties.virtualserver_codec_encryption_mode;
|
|
for (let key in channel.properties)
|
|
properties["property_" + key] = channel.properties[key];
|
|
let tag_channel_description = $.spawn("div");
|
|
properties["bbcode_channel_description"] = tag_channel_description;
|
|
channel.getChannelDescription().then(description => {
|
|
let result = XBBCODE.process({
|
|
text: description,
|
|
escapeHtml: true,
|
|
addInLineBreaks: true
|
|
});
|
|
if (result.error) {
|
|
console.log("BBCode parse error: %o", result.errorQueue);
|
|
}
|
|
tag_channel_description.html(result.html)
|
|
.css("overflow-y", "auto")
|
|
.css("flex-grow", "1");
|
|
});
|
|
let rendered = $("#tmpl_selected_channel").renderTag([properties]);
|
|
html_tag.append(rendered);
|
|
}
|
|
available(object) {
|
|
return typeof object == "object" && object instanceof ChannelEntry;
|
|
}
|
|
}
|
|
function format_time(time) {
|
|
let hours = 0, minutes = 0, seconds = 0;
|
|
if (time >= 60 * 60) {
|
|
hours = Math.floor(time / (60 * 60));
|
|
time -= hours * 60 * 60;
|
|
}
|
|
if (time >= 60) {
|
|
minutes = Math.floor(time / 60);
|
|
time -= minutes * 60;
|
|
}
|
|
seconds = time;
|
|
if (hours > 9)
|
|
hours = hours.toString();
|
|
else if (hours > 0)
|
|
hours = '0' + hours.toString();
|
|
else
|
|
hours = '';
|
|
if (minutes > 9)
|
|
minutes = minutes.toString();
|
|
else if (minutes > 0)
|
|
minutes = '0' + minutes.toString();
|
|
else
|
|
minutes = '00';
|
|
if (seconds > 9)
|
|
seconds = seconds.toString();
|
|
else if (seconds > 0)
|
|
seconds = '0' + seconds.toString();
|
|
else
|
|
seconds = '00';
|
|
return (hours ? hours + ":" : "") + minutes + ':' + seconds;
|
|
}
|
|
var MusicPlayerState;
|
|
(function (MusicPlayerState) {
|
|
MusicPlayerState[MusicPlayerState["SLEEPING"] = 0] = "SLEEPING";
|
|
MusicPlayerState[MusicPlayerState["LOADING"] = 1] = "LOADING";
|
|
MusicPlayerState[MusicPlayerState["PLAYING"] = 2] = "PLAYING";
|
|
MusicPlayerState[MusicPlayerState["PAUSED"] = 3] = "PAUSED";
|
|
MusicPlayerState[MusicPlayerState["STOPPED"] = 4] = "STOPPED";
|
|
})(MusicPlayerState || (MusicPlayerState = {}));
|
|
class MusicInfoManager extends ClientInfoManager {
|
|
createFrame(handle, channel, html_tag) {
|
|
super.createFrame(handle, channel, html_tag);
|
|
this.updateFrame(channel, html_tag);
|
|
}
|
|
updateFrame(bot, html_tag) {
|
|
if (this.single_handler) {
|
|
this.handle.handle.serverConnection.command_handler_boss().remove_single_handler(this.single_handler);
|
|
this.single_handler = undefined;
|
|
}
|
|
this.resetIntervals();
|
|
html_tag.empty();
|
|
let properties = super.buildProperties(bot);
|
|
{ //Render info frame
|
|
if (bot.properties.player_state < MusicPlayerState.PLAYING) {
|
|
properties["music_player"] = $("#tmpl_music_frame_empty").renderTag().css("align-self", "center");
|
|
}
|
|
else {
|
|
let frame = $.spawn("div").text(_translations.MxJZzPra || (_translations.MxJZzPra = tr("loading...")));
|
|
properties["music_player"] = frame;
|
|
properties["song_url"] = $.spawn("a").text(_translations.olQ_3zdj || (_translations.olQ_3zdj = tr("loading...")));
|
|
bot.requestPlayerInfo().then(info => {
|
|
let timestamp = Date.now();
|
|
console.log(info);
|
|
let _frame = $("#tmpl_music_frame").renderTag({
|
|
song_name: info.player_title ? info.player_title :
|
|
info.song_url ? info.song_url : _translations.LqrvULtX || (_translations.LqrvULtX = tr("No title or url")),
|
|
song_url: info.song_url,
|
|
thumbnail: info.song_thumbnail && info.song_thumbnail.length > 0 ? info.song_thumbnail : undefined
|
|
}).css("align-self", "center");
|
|
properties["song_url"].text(info.song_url);
|
|
frame.replaceWith(_frame);
|
|
frame = _frame;
|
|
/* Play/Pause logic */
|
|
{
|
|
let button_play = frame.find(".button_play");
|
|
let button_pause = frame.find(".button_pause");
|
|
let button_stop = frame.find('.button_stop');
|
|
button_play.click(handler => {
|
|
if (!button_play.hasClass("active")) {
|
|
this.handle.handle.serverConnection.send_command("musicbotplayeraction", {
|
|
bot_id: bot.properties.client_database_id,
|
|
action: 1
|
|
}).then(updated => this.triggerUpdate()).catch(error => {
|
|
createErrorModal(_translations.EscvNJt1 || (_translations.EscvNJt1 = tr("Failed to execute play")), MessageHelper.formatMessage(_translations.O7zlMfzk || (_translations.O7zlMfzk = tr("Failed to execute play.<br>{}")), error)).open();
|
|
this.triggerUpdate();
|
|
});
|
|
}
|
|
button_pause.show();
|
|
button_play.hide();
|
|
});
|
|
button_pause.click(handler => {
|
|
if (!button_pause.hasClass("active")) {
|
|
this.handle.handle.serverConnection.send_command("musicbotplayeraction", {
|
|
bot_id: bot.properties.client_database_id,
|
|
action: 2
|
|
}).then(updated => this.triggerUpdate()).catch(error => {
|
|
createErrorModal(_translations.YQnthsII || (_translations.YQnthsII = tr("Failed to execute pause")), MessageHelper.formatMessage(_translations.xB8wZniv || (_translations.xB8wZniv = tr("Failed to execute pause.<br>{}")), error)).open();
|
|
this.triggerUpdate();
|
|
});
|
|
}
|
|
button_play.show();
|
|
button_pause.hide();
|
|
});
|
|
button_stop.click(handler => {
|
|
this.handle.handle.serverConnection.send_command("musicbotplayeraction", {
|
|
bot_id: bot.properties.client_database_id,
|
|
action: 0
|
|
}).then(updated => this.triggerUpdate()).catch(error => {
|
|
createErrorModal(_translations.aNEaYUft || (_translations.aNEaYUft = tr("Failed to execute stop")), MessageHelper.formatMessage(_translations.Fdt8TwbH || (_translations.Fdt8TwbH = tr("Failed to execute stop.<br>{}")), error)).open();
|
|
this.triggerUpdate();
|
|
});
|
|
});
|
|
if (bot.properties.player_state == 2) {
|
|
button_play.hide();
|
|
button_pause.show();
|
|
}
|
|
else if (bot.properties.player_state == 3) {
|
|
button_pause.hide();
|
|
button_play.show();
|
|
}
|
|
else if (bot.properties.player_state == 4) {
|
|
button_pause.hide();
|
|
button_play.show();
|
|
}
|
|
}
|
|
{ /* Button functions */
|
|
_frame.find(".btn-forward").click(() => {
|
|
this.handle.handle.serverConnection.send_command("musicbotplayeraction", {
|
|
bot_id: bot.properties.client_database_id,
|
|
action: 3
|
|
}).then(updated => this.triggerUpdate()).catch(error => {
|
|
createErrorModal(_translations.nf70fBUO || (_translations.nf70fBUO = tr("Failed to execute forward")), (_translations.rpDxx1_J || (_translations.rpDxx1_J = tr("Failed to execute pause.<br>{}"))).format(error)).open();
|
|
this.triggerUpdate();
|
|
});
|
|
});
|
|
_frame.find(".btn-rewind").click(() => {
|
|
this.handle.handle.serverConnection.send_command("musicbotplayeraction", {
|
|
bot_id: bot.properties.client_database_id,
|
|
action: 4
|
|
}).then(updated => this.triggerUpdate()).catch(error => {
|
|
createErrorModal(_translations.KS3oJM_V || (_translations.KS3oJM_V = tr("Failed to execute rewind")), (_translations.c_RawLvr || (_translations.c_RawLvr = tr("Failed to execute pause.<br>{}"))).format(error)).open();
|
|
this.triggerUpdate();
|
|
});
|
|
});
|
|
_frame.find(".btn-settings").click(() => {
|
|
this.handle.handle.serverConnection.command_helper.request_playlist_list().then(lists => {
|
|
for (const entry of lists) {
|
|
if (entry.playlist_id == bot.properties.client_playlist_id) {
|
|
Modals.spawnPlaylistEdit(bot.channelTree.client, entry);
|
|
return;
|
|
}
|
|
}
|
|
createErrorModal(_translations.DT6FshRi || (_translations.DT6FshRi = tr("Invalid permissions")), _translations.kL1M5jAc || (_translations.kL1M5jAc = tr("You don't have to see the bots playlist."))).open();
|
|
}).catch(error => {
|
|
createErrorModal(_translations.LkHqtJYO || (_translations.LkHqtJYO = tr("Failed to query playlist.")), _translations.vBpIbVBl || (_translations.vBpIbVBl = tr("Failed to query playlist info."))).open();
|
|
});
|
|
});
|
|
}
|
|
/* Required flip card javascript */
|
|
frame.find(".right").mouseenter(() => {
|
|
frame.find(".controls-overlay").addClass("flipped");
|
|
});
|
|
frame.find(".right").mouseleave(() => {
|
|
frame.find(".controls-overlay").removeClass("flipped");
|
|
});
|
|
/* Slider */
|
|
frame.find(".timeline .slider").on('mousedown', ev => {
|
|
let timeline = frame.find(".timeline");
|
|
let time = frame.find(".time");
|
|
let slider = timeline.find(".slider");
|
|
let slider_old = slider.css("margin-left");
|
|
let time_max = parseInt(timeline.attr("time-max"));
|
|
slider.prop("editing", true);
|
|
let target_timestamp = 0;
|
|
let move_handler = (event) => {
|
|
let max = timeline.width();
|
|
let current = event.pageX - timeline.offset().left - slider.width() / 2;
|
|
if (current < 0)
|
|
current = 0;
|
|
else if (current > max)
|
|
current = max;
|
|
target_timestamp = current / max * time_max;
|
|
time.text(format_time(Math.floor(target_timestamp / 1000)));
|
|
slider.css("margin-left", current / max * 100 + "%");
|
|
};
|
|
let finish_handler = event => {
|
|
console.log("Event (%i | %s): %o", event.button, event.type, event);
|
|
if (event.type == "mousedown" && event.button != 2)
|
|
return;
|
|
$(document).unbind("mousemove", move_handler);
|
|
$(document).unbind("mouseup mouseleave mousedown", finish_handler);
|
|
if (event.type != "mousedown") {
|
|
slider.prop("editing", false);
|
|
slider.prop("edited", true);
|
|
let current_timestamp = info.player_replay_index + Date.now() - timestamp;
|
|
this.handle.handle.serverConnection.send_command("musicbotplayeraction", {
|
|
bot_id: bot.properties.client_database_id,
|
|
action: current_timestamp > target_timestamp ? 6 : 5,
|
|
units: current_timestamp < target_timestamp ? target_timestamp - current_timestamp : current_timestamp - target_timestamp
|
|
}).then(() => this.triggerUpdate()).catch(error => {
|
|
slider.prop("edited", false);
|
|
});
|
|
}
|
|
else { //Restore old
|
|
event.preventDefault();
|
|
slider.css("margin-left", slider_old + "%");
|
|
}
|
|
};
|
|
$(document).on('mousemove', move_handler);
|
|
$(document).on('mouseup mouseleave mousedown', finish_handler);
|
|
ev.preventDefault();
|
|
return false;
|
|
});
|
|
{
|
|
frame.find(".timeline").attr("time-max", info.player_max_index);
|
|
let timeline = frame.find(".timeline");
|
|
let time_bar = timeline.find(".played");
|
|
let buffered_bar = timeline.find(".buffered");
|
|
let slider = timeline.find(".slider");
|
|
let player_time = _frame.find(".player_time");
|
|
let update_handler = (played, buffered) => {
|
|
let time_index = played || info.player_replay_index + (bot.properties.player_state == 2 ? Date.now() - timestamp : 0);
|
|
let buffered_index = buffered || 0;
|
|
time_bar.css("width", time_index / info.player_max_index * 100 + "%");
|
|
buffered_bar.css("width", buffered_index / info.player_max_index * 100 + "%");
|
|
if (!slider.prop("editing") && !slider.prop("edited")) {
|
|
player_time.text(format_time(Math.floor(time_index / 1000)));
|
|
slider.css("margin-left", time_index / info.player_max_index * 100 + "%");
|
|
}
|
|
};
|
|
let interval = setInterval(update_handler, 1000);
|
|
this.registerInterval(interval);
|
|
update_handler();
|
|
/* register subscription */
|
|
this.handle.handle.serverConnection.send_command("musicbotsetsubscription", { bot_id: bot.properties.client_database_id }).catch(error => {
|
|
console.error("Failed to subscribe to displayed music bot! Using pseudo timeline");
|
|
}).then(() => {
|
|
clearInterval(interval);
|
|
});
|
|
this.single_handler = {
|
|
command: "notifymusicstatusupdate",
|
|
function: command => {
|
|
const json = command.arguments[0];
|
|
update_handler(parseInt(json["player_replay_index"]), parseInt(json["player_buffered_index"]));
|
|
return false; /* do not unregister me! */
|
|
}
|
|
};
|
|
this.handle.handle.serverConnection.command_handler_boss().register_single_handler(this.single_handler);
|
|
}
|
|
});
|
|
}
|
|
const player = properties["music_player"];
|
|
const player_transformer = $.spawn("div").append(player);
|
|
player_transformer.css({
|
|
'display': 'block',
|
|
//'width': "100%",
|
|
'height': '100%'
|
|
});
|
|
properties["music_player"] = player_transformer;
|
|
}
|
|
let rendered = $("#tmpl_selected_music").renderTag([properties]);
|
|
html_tag.append(rendered);
|
|
{
|
|
const player = properties["music_player"];
|
|
const player_width = 400; //player.width();
|
|
const player_height = 400; //player.height();
|
|
const parent = player.parent();
|
|
parent.css({
|
|
'flex-grow': 1,
|
|
'display': 'flex',
|
|
'flex-direction': 'row',
|
|
'justify-content': 'space-around',
|
|
});
|
|
const padding = 14;
|
|
const scale_x = Math.min((parent.width() - padding) / player_width, 1.5);
|
|
const scale_y = Math.min((parent.height() - padding) / player_height, 1.5);
|
|
let scale = Math.min(scale_x, scale_y);
|
|
let translate_x = 50, translate_y = 50;
|
|
if (scale_x == scale_y && scale_x == scale) {
|
|
//Equal scale
|
|
}
|
|
else if (scale_x == scale) {
|
|
//We scale on the x-Axis
|
|
//We have to adjust the y-Axis
|
|
}
|
|
else {
|
|
//We scale on the y-Axis
|
|
//We have to adjust the x-Axis
|
|
}
|
|
//1 => 0 | 0
|
|
//1.5 => 0 | 25
|
|
//0.5 => 0 | -25
|
|
//const translate_x = scale_x != scale ? 0 : undefined || 50 - (50 * ((parent.width() - padding) / player_width));
|
|
//const translate_y = scale_y != scale || scale_y > 1 ? 0 : undefined || 50 - (50 * ((parent.height() - padding) / player_height));
|
|
const transform = ("translate(0%, " + (scale * 50 - 50) + "%) scale(" + scale.toPrecision(2) + ")");
|
|
console.log(_translations.TIA5kbb9 || (_translations.TIA5kbb9 = tr("Parents: %o | %o")), parent.width(), parent.height());
|
|
console.log(_translations.w6veI4_R || (_translations.w6veI4_R = tr("Player: %o | %o")), player_width, player_height);
|
|
console.log(_translations.PzHxNyIZ || (_translations.PzHxNyIZ = tr("Scale: %f => translate: %o | %o")), scale, translate_x, translate_y);
|
|
player.css({
|
|
transform: transform
|
|
});
|
|
console.log("Transform: " + transform);
|
|
}
|
|
this.registerInterval(setInterval(() => {
|
|
html_tag.find(".update_onlinetime").text(formatDate(bot.calculateOnlineTime()));
|
|
}, 1000));
|
|
}
|
|
update_local_volume(volume) {
|
|
this.handle.html_tag().find(".property-volume-local").text(Math.floor(volume * 100) + "%");
|
|
}
|
|
update_remote_volume(volume) {
|
|
this.handle.html_tag().find(".property-volume-remote").text(Math.floor(volume * 100) + "%");
|
|
}
|
|
available(object) {
|
|
return typeof object == "object" && object instanceof MusicClientEntry;
|
|
}
|
|
finalizeFrame(object, frame) {
|
|
if (this.single_handler) {
|
|
this.handle.handle.serverConnection.command_handler_boss().remove_single_handler(this.single_handler);
|
|
this.single_handler = undefined;
|
|
}
|
|
super.finalizeFrame(object, frame);
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["91941f6d856c806ef067a7da7d0f4da6489c18d3d9e6ea5633cb70445364127a"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["91941f6d856c806ef067a7da7d0f4da6489c18d3d9e6ea5633cb70445364127a"] = "91941f6d856c806ef067a7da7d0f4da6489c18d3d9e6ea5633cb70445364127a";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "yRMsT8NR", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ConnectionBase.ts (100,30)" }, { name: "ARnxHcil", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ConnectionBase.ts (129,35)" }, { name: "voFFeV9H", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ConnectionBase.ts (141,35)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var connection;
|
|
(function (connection_1) {
|
|
connection_1.CommandOptionDefaults = {
|
|
flagset: [],
|
|
process_result: true,
|
|
timeout: 1000
|
|
};
|
|
class AbstractServerConnection {
|
|
constructor(client) {
|
|
this.client = client;
|
|
this.command_helper = new connection_1.CommandHelper(this);
|
|
}
|
|
}
|
|
connection_1.AbstractServerConnection = AbstractServerConnection;
|
|
class AbstractVoiceConnection {
|
|
constructor(connection) {
|
|
this.connection = connection;
|
|
}
|
|
}
|
|
connection_1.AbstractVoiceConnection = AbstractVoiceConnection;
|
|
class ServerCommand {
|
|
}
|
|
connection_1.ServerCommand = ServerCommand;
|
|
class AbstractCommandHandler {
|
|
constructor(connection) {
|
|
this.volatile_handler_boss = false; /* if true than the command handler could be registered twice to two or more handlers */
|
|
this.ignore_consumed = false;
|
|
this.connection = connection;
|
|
}
|
|
}
|
|
connection_1.AbstractCommandHandler = AbstractCommandHandler;
|
|
class AbstractCommandHandlerBoss {
|
|
constructor(connection) {
|
|
this.command_handlers = [];
|
|
/* TODO: Timeout */
|
|
this.single_command_handler = [];
|
|
this.connection = connection;
|
|
}
|
|
register_handler(handler) {
|
|
if (!handler.volatile_handler_boss && handler.handler_boss)
|
|
throw "handler already registered";
|
|
this.command_handlers.remove(handler); /* just to be sure */
|
|
this.command_handlers.push(handler);
|
|
handler.handler_boss = this;
|
|
}
|
|
unregister_handler(handler) {
|
|
if (!handler.volatile_handler_boss && handler.handler_boss !== this) {
|
|
console.warn(_translations.yRMsT8NR || (_translations.yRMsT8NR = tr("Tried to unregister command handler which does not belong to the handler boss")));
|
|
return;
|
|
}
|
|
this.command_handlers.remove(handler);
|
|
handler.handler_boss = undefined;
|
|
}
|
|
register_single_handler(handler) {
|
|
this.single_command_handler.push(handler);
|
|
}
|
|
remove_single_handler(handler) {
|
|
this.single_command_handler.remove(handler);
|
|
}
|
|
handlers() {
|
|
return this.command_handlers;
|
|
}
|
|
invoke_handle(command) {
|
|
let flag_consumed = false;
|
|
for (const handler of this.command_handlers) {
|
|
try {
|
|
if (!flag_consumed || handler.ignore_consumed)
|
|
flag_consumed = flag_consumed || handler.handle_command(command);
|
|
}
|
|
catch (error) {
|
|
console.error(_translations.ARnxHcil || (_translations.ARnxHcil = tr("Failed to invoke command handler. Invocation results in an exception: %o")), error);
|
|
}
|
|
}
|
|
for (const handler of [...this.single_command_handler]) {
|
|
if (handler.command && handler.command != command.command)
|
|
continue;
|
|
try {
|
|
if (handler.function(command))
|
|
this.single_command_handler.remove(handler);
|
|
}
|
|
catch (error) {
|
|
console.error(_translations.voFFeV9H || (_translations.voFFeV9H = tr("Failed to invoke single command handler. Invocation results in an exception: %o")), error);
|
|
}
|
|
}
|
|
return flag_consumed;
|
|
}
|
|
}
|
|
connection_1.AbstractCommandHandlerBoss = AbstractCommandHandlerBoss;
|
|
})(connection || (connection = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["03b9f2276efe385ded09171572780068a757abad97b3501693214ccae5963ef4"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["03b9f2276efe385ded09171572780068a757abad97b3501693214ccae5963ef4"] = "03b9f2276efe385ded09171572780068a757abad97b3501693214ccae5963ef4";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "l6YeuZJB", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/PermissionManager.ts (386,44)" }, { name: "hiRWWQk0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/PermissionManager.ts (480,51)" }, { name: "KvTloMLv", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/PermissionManager.ts (552,75)" }, { name: "MSzE2M5g", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/PermissionManager.ts (559,30)" }, { name: "Icp51Xyn", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/PermissionManager.ts (573,23)" }, { name: "JCXF8tNn", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/PermissionManager.ts (578,43)" }, { name: "xW3OtQsi", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/PermissionManager.ts (587,47)" }, { name: "gqaXY6XV", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/PermissionManager.ts (596,75)" }, { name: "GQx2LqqU", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/PermissionManager.ts (612,55)" }, { name: "TU9ekKrB", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/PermissionManager.ts (641,43)" }, { name: "ODK68n4X", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/PermissionManager.ts (650,44)" }, { name: "REzpKcHE", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/PermissionManager.ts (770,44)" }, { name: "cFseHpLq", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/PermissionManager.ts (773,47)" }, { name: "q7zQFaQp", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/PermissionManager.ts (795,27)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../client.ts" />
|
|
/// <reference path="../connection/ConnectionBase.ts" />
|
|
var PermissionType;
|
|
(function (PermissionType) {
|
|
PermissionType["B_SERVERINSTANCE_HELP_VIEW"] = "b_serverinstance_help_view";
|
|
PermissionType["B_SERVERINSTANCE_VERSION_VIEW"] = "b_serverinstance_version_view";
|
|
PermissionType["B_SERVERINSTANCE_INFO_VIEW"] = "b_serverinstance_info_view";
|
|
PermissionType["B_SERVERINSTANCE_VIRTUALSERVER_LIST"] = "b_serverinstance_virtualserver_list";
|
|
PermissionType["B_SERVERINSTANCE_BINDING_LIST"] = "b_serverinstance_binding_list";
|
|
PermissionType["B_SERVERINSTANCE_PERMISSION_LIST"] = "b_serverinstance_permission_list";
|
|
PermissionType["B_SERVERINSTANCE_PERMISSION_FIND"] = "b_serverinstance_permission_find";
|
|
PermissionType["B_VIRTUALSERVER_CREATE"] = "b_virtualserver_create";
|
|
PermissionType["B_VIRTUALSERVER_DELETE"] = "b_virtualserver_delete";
|
|
PermissionType["B_VIRTUALSERVER_START_ANY"] = "b_virtualserver_start_any";
|
|
PermissionType["B_VIRTUALSERVER_STOP_ANY"] = "b_virtualserver_stop_any";
|
|
PermissionType["B_VIRTUALSERVER_CHANGE_MACHINE_ID"] = "b_virtualserver_change_machine_id";
|
|
PermissionType["B_VIRTUALSERVER_CHANGE_TEMPLATE"] = "b_virtualserver_change_template";
|
|
PermissionType["B_SERVERQUERY_LOGIN"] = "b_serverquery_login";
|
|
PermissionType["B_SERVERINSTANCE_TEXTMESSAGE_SEND"] = "b_serverinstance_textmessage_send";
|
|
PermissionType["B_SERVERINSTANCE_LOG_VIEW"] = "b_serverinstance_log_view";
|
|
PermissionType["B_SERVERINSTANCE_LOG_ADD"] = "b_serverinstance_log_add";
|
|
PermissionType["B_SERVERINSTANCE_STOP"] = "b_serverinstance_stop";
|
|
PermissionType["B_SERVERINSTANCE_MODIFY_SETTINGS"] = "b_serverinstance_modify_settings";
|
|
PermissionType["B_SERVERINSTANCE_MODIFY_QUERYGROUP"] = "b_serverinstance_modify_querygroup";
|
|
PermissionType["B_SERVERINSTANCE_MODIFY_TEMPLATES"] = "b_serverinstance_modify_templates";
|
|
PermissionType["B_VIRTUALSERVER_SELECT"] = "b_virtualserver_select";
|
|
PermissionType["B_VIRTUALSERVER_SELECT_GODMODE"] = "b_virtualserver_select_godmode";
|
|
PermissionType["B_VIRTUALSERVER_INFO_VIEW"] = "b_virtualserver_info_view";
|
|
PermissionType["B_VIRTUALSERVER_CONNECTIONINFO_VIEW"] = "b_virtualserver_connectioninfo_view";
|
|
PermissionType["B_VIRTUALSERVER_CHANNEL_LIST"] = "b_virtualserver_channel_list";
|
|
PermissionType["B_VIRTUALSERVER_CHANNEL_SEARCH"] = "b_virtualserver_channel_search";
|
|
PermissionType["B_VIRTUALSERVER_CLIENT_LIST"] = "b_virtualserver_client_list";
|
|
PermissionType["B_VIRTUALSERVER_CLIENT_SEARCH"] = "b_virtualserver_client_search";
|
|
PermissionType["B_VIRTUALSERVER_CLIENT_DBLIST"] = "b_virtualserver_client_dblist";
|
|
PermissionType["B_VIRTUALSERVER_CLIENT_DBSEARCH"] = "b_virtualserver_client_dbsearch";
|
|
PermissionType["B_VIRTUALSERVER_CLIENT_DBINFO"] = "b_virtualserver_client_dbinfo";
|
|
PermissionType["B_VIRTUALSERVER_PERMISSION_FIND"] = "b_virtualserver_permission_find";
|
|
PermissionType["B_VIRTUALSERVER_CUSTOM_SEARCH"] = "b_virtualserver_custom_search";
|
|
PermissionType["B_VIRTUALSERVER_START"] = "b_virtualserver_start";
|
|
PermissionType["B_VIRTUALSERVER_STOP"] = "b_virtualserver_stop";
|
|
PermissionType["B_VIRTUALSERVER_TOKEN_LIST"] = "b_virtualserver_token_list";
|
|
PermissionType["B_VIRTUALSERVER_TOKEN_ADD"] = "b_virtualserver_token_add";
|
|
PermissionType["B_VIRTUALSERVER_TOKEN_USE"] = "b_virtualserver_token_use";
|
|
PermissionType["B_VIRTUALSERVER_TOKEN_DELETE"] = "b_virtualserver_token_delete";
|
|
PermissionType["B_VIRTUALSERVER_LOG_VIEW"] = "b_virtualserver_log_view";
|
|
PermissionType["B_VIRTUALSERVER_LOG_ADD"] = "b_virtualserver_log_add";
|
|
PermissionType["B_VIRTUALSERVER_JOIN_IGNORE_PASSWORD"] = "b_virtualserver_join_ignore_password";
|
|
PermissionType["B_VIRTUALSERVER_NOTIFY_REGISTER"] = "b_virtualserver_notify_register";
|
|
PermissionType["B_VIRTUALSERVER_NOTIFY_UNREGISTER"] = "b_virtualserver_notify_unregister";
|
|
PermissionType["B_VIRTUALSERVER_SNAPSHOT_CREATE"] = "b_virtualserver_snapshot_create";
|
|
PermissionType["B_VIRTUALSERVER_SNAPSHOT_DEPLOY"] = "b_virtualserver_snapshot_deploy";
|
|
PermissionType["B_VIRTUALSERVER_PERMISSION_RESET"] = "b_virtualserver_permission_reset";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_NAME"] = "b_virtualserver_modify_name";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_WELCOMEMESSAGE"] = "b_virtualserver_modify_welcomemessage";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_MAXCLIENTS"] = "b_virtualserver_modify_maxclients";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_RESERVED_SLOTS"] = "b_virtualserver_modify_reserved_slots";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_PASSWORD"] = "b_virtualserver_modify_password";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_DEFAULT_SERVERGROUP"] = "b_virtualserver_modify_default_servergroup";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_DEFAULT_MUSICGROUP"] = "b_virtualserver_modify_default_musicgroup";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_DEFAULT_CHANNELGROUP"] = "b_virtualserver_modify_default_channelgroup";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_DEFAULT_CHANNELADMINGROUP"] = "b_virtualserver_modify_default_channeladmingroup";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_CHANNEL_FORCED_SILENCE"] = "b_virtualserver_modify_channel_forced_silence";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_COMPLAIN"] = "b_virtualserver_modify_complain";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_ANTIFLOOD"] = "b_virtualserver_modify_antiflood";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_FT_SETTINGS"] = "b_virtualserver_modify_ft_settings";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_FT_QUOTAS"] = "b_virtualserver_modify_ft_quotas";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_HOSTMESSAGE"] = "b_virtualserver_modify_hostmessage";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_HOSTBANNER"] = "b_virtualserver_modify_hostbanner";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_HOSTBUTTON"] = "b_virtualserver_modify_hostbutton";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_PORT"] = "b_virtualserver_modify_port";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_HOST"] = "b_virtualserver_modify_host";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_DEFAULT_MESSAGES"] = "b_virtualserver_modify_default_messages";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_AUTOSTART"] = "b_virtualserver_modify_autostart";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_NEEDED_IDENTITY_SECURITY_LEVEL"] = "b_virtualserver_modify_needed_identity_security_level";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_PRIORITY_SPEAKER_DIMM_MODIFICATOR"] = "b_virtualserver_modify_priority_speaker_dimm_modificator";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_LOG_SETTINGS"] = "b_virtualserver_modify_log_settings";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_MIN_CLIENT_VERSION"] = "b_virtualserver_modify_min_client_version";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_ICON_ID"] = "b_virtualserver_modify_icon_id";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_WEBLIST"] = "b_virtualserver_modify_weblist";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_CODEC_ENCRYPTION_MODE"] = "b_virtualserver_modify_codec_encryption_mode";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_TEMPORARY_PASSWORDS"] = "b_virtualserver_modify_temporary_passwords";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_TEMPORARY_PASSWORDS_OWN"] = "b_virtualserver_modify_temporary_passwords_own";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_CHANNEL_TEMP_DELETE_DELAY_DEFAULT"] = "b_virtualserver_modify_channel_temp_delete_delay_default";
|
|
PermissionType["B_VIRTUALSERVER_MODIFY_MUSIC_BOT_LIMIT"] = "b_virtualserver_modify_music_bot_limit";
|
|
PermissionType["I_CHANNEL_MIN_DEPTH"] = "i_channel_min_depth";
|
|
PermissionType["I_CHANNEL_MAX_DEPTH"] = "i_channel_max_depth";
|
|
PermissionType["B_CHANNEL_GROUP_INHERITANCE_END"] = "b_channel_group_inheritance_end";
|
|
PermissionType["I_CHANNEL_PERMISSION_MODIFY_POWER"] = "i_channel_permission_modify_power";
|
|
PermissionType["I_CHANNEL_NEEDED_PERMISSION_MODIFY_POWER"] = "i_channel_needed_permission_modify_power";
|
|
PermissionType["B_CHANNEL_INFO_VIEW"] = "b_channel_info_view";
|
|
PermissionType["B_CHANNEL_CREATE_CHILD"] = "b_channel_create_child";
|
|
PermissionType["B_CHANNEL_CREATE_PERMANENT"] = "b_channel_create_permanent";
|
|
PermissionType["B_CHANNEL_CREATE_SEMI_PERMANENT"] = "b_channel_create_semi_permanent";
|
|
PermissionType["B_CHANNEL_CREATE_TEMPORARY"] = "b_channel_create_temporary";
|
|
PermissionType["B_CHANNEL_CREATE_PRIVATE"] = "b_channel_create_private";
|
|
PermissionType["B_CHANNEL_CREATE_WITH_TOPIC"] = "b_channel_create_with_topic";
|
|
PermissionType["B_CHANNEL_CREATE_WITH_DESCRIPTION"] = "b_channel_create_with_description";
|
|
PermissionType["B_CHANNEL_CREATE_WITH_PASSWORD"] = "b_channel_create_with_password";
|
|
PermissionType["B_CHANNEL_CREATE_MODIFY_WITH_CODEC_SPEEX8"] = "b_channel_create_modify_with_codec_speex8";
|
|
PermissionType["B_CHANNEL_CREATE_MODIFY_WITH_CODEC_SPEEX16"] = "b_channel_create_modify_with_codec_speex16";
|
|
PermissionType["B_CHANNEL_CREATE_MODIFY_WITH_CODEC_SPEEX32"] = "b_channel_create_modify_with_codec_speex32";
|
|
PermissionType["B_CHANNEL_CREATE_MODIFY_WITH_CODEC_CELTMONO48"] = "b_channel_create_modify_with_codec_celtmono48";
|
|
PermissionType["B_CHANNEL_CREATE_MODIFY_WITH_CODEC_OPUSVOICE"] = "b_channel_create_modify_with_codec_opusvoice";
|
|
PermissionType["B_CHANNEL_CREATE_MODIFY_WITH_CODEC_OPUSMUSIC"] = "b_channel_create_modify_with_codec_opusmusic";
|
|
PermissionType["I_CHANNEL_CREATE_MODIFY_WITH_CODEC_MAXQUALITY"] = "i_channel_create_modify_with_codec_maxquality";
|
|
PermissionType["I_CHANNEL_CREATE_MODIFY_WITH_CODEC_LATENCY_FACTOR_MIN"] = "i_channel_create_modify_with_codec_latency_factor_min";
|
|
PermissionType["B_CHANNEL_CREATE_WITH_MAXCLIENTS"] = "b_channel_create_with_maxclients";
|
|
PermissionType["B_CHANNEL_CREATE_WITH_MAXFAMILYCLIENTS"] = "b_channel_create_with_maxfamilyclients";
|
|
PermissionType["B_CHANNEL_CREATE_WITH_SORTORDER"] = "b_channel_create_with_sortorder";
|
|
PermissionType["B_CHANNEL_CREATE_WITH_DEFAULT"] = "b_channel_create_with_default";
|
|
PermissionType["B_CHANNEL_CREATE_WITH_NEEDED_TALK_POWER"] = "b_channel_create_with_needed_talk_power";
|
|
PermissionType["B_CHANNEL_CREATE_MODIFY_WITH_FORCE_PASSWORD"] = "b_channel_create_modify_with_force_password";
|
|
PermissionType["I_CHANNEL_CREATE_MODIFY_WITH_TEMP_DELETE_DELAY"] = "i_channel_create_modify_with_temp_delete_delay";
|
|
PermissionType["B_CHANNEL_MODIFY_PARENT"] = "b_channel_modify_parent";
|
|
PermissionType["B_CHANNEL_MODIFY_MAKE_DEFAULT"] = "b_channel_modify_make_default";
|
|
PermissionType["B_CHANNEL_MODIFY_MAKE_PERMANENT"] = "b_channel_modify_make_permanent";
|
|
PermissionType["B_CHANNEL_MODIFY_MAKE_SEMI_PERMANENT"] = "b_channel_modify_make_semi_permanent";
|
|
PermissionType["B_CHANNEL_MODIFY_MAKE_TEMPORARY"] = "b_channel_modify_make_temporary";
|
|
PermissionType["B_CHANNEL_MODIFY_NAME"] = "b_channel_modify_name";
|
|
PermissionType["B_CHANNEL_MODIFY_TOPIC"] = "b_channel_modify_topic";
|
|
PermissionType["B_CHANNEL_MODIFY_DESCRIPTION"] = "b_channel_modify_description";
|
|
PermissionType["B_CHANNEL_MODIFY_PASSWORD"] = "b_channel_modify_password";
|
|
PermissionType["B_CHANNEL_MODIFY_CODEC"] = "b_channel_modify_codec";
|
|
PermissionType["B_CHANNEL_MODIFY_CODEC_QUALITY"] = "b_channel_modify_codec_quality";
|
|
PermissionType["B_CHANNEL_MODIFY_CODEC_LATENCY_FACTOR"] = "b_channel_modify_codec_latency_factor";
|
|
PermissionType["B_CHANNEL_MODIFY_MAXCLIENTS"] = "b_channel_modify_maxclients";
|
|
PermissionType["B_CHANNEL_MODIFY_MAXFAMILYCLIENTS"] = "b_channel_modify_maxfamilyclients";
|
|
PermissionType["B_CHANNEL_MODIFY_SORTORDER"] = "b_channel_modify_sortorder";
|
|
PermissionType["B_CHANNEL_MODIFY_NEEDED_TALK_POWER"] = "b_channel_modify_needed_talk_power";
|
|
PermissionType["I_CHANNEL_MODIFY_POWER"] = "i_channel_modify_power";
|
|
PermissionType["I_CHANNEL_NEEDED_MODIFY_POWER"] = "i_channel_needed_modify_power";
|
|
PermissionType["B_CHANNEL_MODIFY_MAKE_CODEC_ENCRYPTED"] = "b_channel_modify_make_codec_encrypted";
|
|
PermissionType["B_CHANNEL_MODIFY_TEMP_DELETE_DELAY"] = "b_channel_modify_temp_delete_delay";
|
|
PermissionType["B_CHANNEL_DELETE_PERMANENT"] = "b_channel_delete_permanent";
|
|
PermissionType["B_CHANNEL_DELETE_SEMI_PERMANENT"] = "b_channel_delete_semi_permanent";
|
|
PermissionType["B_CHANNEL_DELETE_TEMPORARY"] = "b_channel_delete_temporary";
|
|
PermissionType["B_CHANNEL_DELETE_FLAG_FORCE"] = "b_channel_delete_flag_force";
|
|
PermissionType["I_CHANNEL_DELETE_POWER"] = "i_channel_delete_power";
|
|
PermissionType["I_CHANNEL_NEEDED_DELETE_POWER"] = "i_channel_needed_delete_power";
|
|
PermissionType["B_CHANNEL_JOIN_PERMANENT"] = "b_channel_join_permanent";
|
|
PermissionType["B_CHANNEL_JOIN_SEMI_PERMANENT"] = "b_channel_join_semi_permanent";
|
|
PermissionType["B_CHANNEL_JOIN_TEMPORARY"] = "b_channel_join_temporary";
|
|
PermissionType["B_CHANNEL_JOIN_IGNORE_PASSWORD"] = "b_channel_join_ignore_password";
|
|
PermissionType["B_CHANNEL_JOIN_IGNORE_MAXCLIENTS"] = "b_channel_join_ignore_maxclients";
|
|
PermissionType["B_CHANNEL_IGNORE_VIEW_POWER"] = "b_channel_ignore_view_power";
|
|
PermissionType["I_CHANNEL_JOIN_POWER"] = "i_channel_join_power";
|
|
PermissionType["I_CHANNEL_NEEDED_JOIN_POWER"] = "i_channel_needed_join_power";
|
|
PermissionType["B_CHANNEL_IGNORE_JOIN_POWER"] = "b_channel_ignore_join_power";
|
|
PermissionType["I_CHANNEL_VIEW_POWER"] = "i_channel_view_power";
|
|
PermissionType["I_CHANNEL_NEEDED_VIEW_POWER"] = "i_channel_needed_view_power";
|
|
PermissionType["I_CHANNEL_SUBSCRIBE_POWER"] = "i_channel_subscribe_power";
|
|
PermissionType["I_CHANNEL_NEEDED_SUBSCRIBE_POWER"] = "i_channel_needed_subscribe_power";
|
|
PermissionType["I_CHANNEL_DESCRIPTION_VIEW_POWER"] = "i_channel_description_view_power";
|
|
PermissionType["I_CHANNEL_NEEDED_DESCRIPTION_VIEW_POWER"] = "i_channel_needed_description_view_power";
|
|
PermissionType["I_ICON_ID"] = "i_icon_id";
|
|
PermissionType["I_MAX_ICON_FILESIZE"] = "i_max_icon_filesize";
|
|
PermissionType["B_ICON_MANAGE"] = "b_icon_manage";
|
|
PermissionType["B_GROUP_IS_PERMANENT"] = "b_group_is_permanent";
|
|
PermissionType["I_GROUP_AUTO_UPDATE_TYPE"] = "i_group_auto_update_type";
|
|
PermissionType["I_GROUP_AUTO_UPDATE_MAX_VALUE"] = "i_group_auto_update_max_value";
|
|
PermissionType["I_GROUP_SORT_ID"] = "i_group_sort_id";
|
|
PermissionType["I_GROUP_SHOW_NAME_IN_TREE"] = "i_group_show_name_in_tree";
|
|
PermissionType["B_VIRTUALSERVER_SERVERGROUP_CREATE"] = "b_virtualserver_servergroup_create";
|
|
PermissionType["B_VIRTUALSERVER_SERVERGROUP_LIST"] = "b_virtualserver_servergroup_list";
|
|
PermissionType["B_VIRTUALSERVER_SERVERGROUP_PERMISSION_LIST"] = "b_virtualserver_servergroup_permission_list";
|
|
PermissionType["B_VIRTUALSERVER_SERVERGROUP_CLIENT_LIST"] = "b_virtualserver_servergroup_client_list";
|
|
PermissionType["B_VIRTUALSERVER_CHANNELGROUP_CREATE"] = "b_virtualserver_channelgroup_create";
|
|
PermissionType["B_VIRTUALSERVER_CHANNELGROUP_LIST"] = "b_virtualserver_channelgroup_list";
|
|
PermissionType["B_VIRTUALSERVER_CHANNELGROUP_PERMISSION_LIST"] = "b_virtualserver_channelgroup_permission_list";
|
|
PermissionType["B_VIRTUALSERVER_CHANNELGROUP_CLIENT_LIST"] = "b_virtualserver_channelgroup_client_list";
|
|
PermissionType["B_VIRTUALSERVER_CLIENT_PERMISSION_LIST"] = "b_virtualserver_client_permission_list";
|
|
PermissionType["B_VIRTUALSERVER_CHANNEL_PERMISSION_LIST"] = "b_virtualserver_channel_permission_list";
|
|
PermissionType["B_VIRTUALSERVER_CHANNELCLIENT_PERMISSION_LIST"] = "b_virtualserver_channelclient_permission_list";
|
|
PermissionType["B_VIRTUALSERVER_PLAYLIST_PERMISSION_LIST"] = "b_virtualserver_playlist_permission_list";
|
|
PermissionType["I_SERVER_GROUP_MODIFY_POWER"] = "i_server_group_modify_power";
|
|
PermissionType["I_SERVER_GROUP_NEEDED_MODIFY_POWER"] = "i_server_group_needed_modify_power";
|
|
PermissionType["I_SERVER_GROUP_MEMBER_ADD_POWER"] = "i_server_group_member_add_power";
|
|
PermissionType["I_SERVER_GROUP_SELF_ADD_POWER"] = "i_server_group_self_add_power";
|
|
PermissionType["I_SERVER_GROUP_NEEDED_MEMBER_ADD_POWER"] = "i_server_group_needed_member_add_power";
|
|
PermissionType["I_SERVER_GROUP_MEMBER_REMOVE_POWER"] = "i_server_group_member_remove_power";
|
|
PermissionType["I_SERVER_GROUP_SELF_REMOVE_POWER"] = "i_server_group_self_remove_power";
|
|
PermissionType["I_SERVER_GROUP_NEEDED_MEMBER_REMOVE_POWER"] = "i_server_group_needed_member_remove_power";
|
|
PermissionType["I_CHANNEL_GROUP_MODIFY_POWER"] = "i_channel_group_modify_power";
|
|
PermissionType["I_CHANNEL_GROUP_NEEDED_MODIFY_POWER"] = "i_channel_group_needed_modify_power";
|
|
PermissionType["I_CHANNEL_GROUP_MEMBER_ADD_POWER"] = "i_channel_group_member_add_power";
|
|
PermissionType["I_CHANNEL_GROUP_SELF_ADD_POWER"] = "i_channel_group_self_add_power";
|
|
PermissionType["I_CHANNEL_GROUP_NEEDED_MEMBER_ADD_POWER"] = "i_channel_group_needed_member_add_power";
|
|
PermissionType["I_CHANNEL_GROUP_MEMBER_REMOVE_POWER"] = "i_channel_group_member_remove_power";
|
|
PermissionType["I_CHANNEL_GROUP_SELF_REMOVE_POWER"] = "i_channel_group_self_remove_power";
|
|
PermissionType["I_CHANNEL_GROUP_NEEDED_MEMBER_REMOVE_POWER"] = "i_channel_group_needed_member_remove_power";
|
|
PermissionType["I_GROUP_MEMBER_ADD_POWER"] = "i_group_member_add_power";
|
|
PermissionType["I_GROUP_NEEDED_MEMBER_ADD_POWER"] = "i_group_needed_member_add_power";
|
|
PermissionType["I_GROUP_MEMBER_REMOVE_POWER"] = "i_group_member_remove_power";
|
|
PermissionType["I_GROUP_NEEDED_MEMBER_REMOVE_POWER"] = "i_group_needed_member_remove_power";
|
|
PermissionType["I_GROUP_MODIFY_POWER"] = "i_group_modify_power";
|
|
PermissionType["I_GROUP_NEEDED_MODIFY_POWER"] = "i_group_needed_modify_power";
|
|
PermissionType["I_PERMISSION_MODIFY_POWER"] = "i_permission_modify_power";
|
|
PermissionType["B_PERMISSION_MODIFY_POWER_IGNORE"] = "b_permission_modify_power_ignore";
|
|
PermissionType["B_VIRTUALSERVER_SERVERGROUP_DELETE"] = "b_virtualserver_servergroup_delete";
|
|
PermissionType["B_VIRTUALSERVER_CHANNELGROUP_DELETE"] = "b_virtualserver_channelgroup_delete";
|
|
PermissionType["I_CLIENT_PERMISSION_MODIFY_POWER"] = "i_client_permission_modify_power";
|
|
PermissionType["I_CLIENT_NEEDED_PERMISSION_MODIFY_POWER"] = "i_client_needed_permission_modify_power";
|
|
PermissionType["I_CLIENT_MAX_CLONES_UID"] = "i_client_max_clones_uid";
|
|
PermissionType["I_CLIENT_MAX_CLONES_IP"] = "i_client_max_clones_ip";
|
|
PermissionType["I_CLIENT_MAX_CLONES_HWID"] = "i_client_max_clones_hwid";
|
|
PermissionType["I_CLIENT_MAX_IDLETIME"] = "i_client_max_idletime";
|
|
PermissionType["I_CLIENT_MAX_AVATAR_FILESIZE"] = "i_client_max_avatar_filesize";
|
|
PermissionType["I_CLIENT_MAX_CHANNEL_SUBSCRIPTIONS"] = "i_client_max_channel_subscriptions";
|
|
PermissionType["I_CLIENT_MAX_CHANNELS"] = "i_client_max_channels";
|
|
PermissionType["I_CLIENT_MAX_TEMPORARY_CHANNELS"] = "i_client_max_temporary_channels";
|
|
PermissionType["I_CLIENT_MAX_SEMI_CHANNELS"] = "i_client_max_semi_channels";
|
|
PermissionType["I_CLIENT_MAX_PERMANENT_CHANNELS"] = "i_client_max_permanent_channels";
|
|
PermissionType["B_CLIENT_USE_PRIORITY_SPEAKER"] = "b_client_use_priority_speaker";
|
|
PermissionType["B_CLIENT_SKIP_CHANNELGROUP_PERMISSIONS"] = "b_client_skip_channelgroup_permissions";
|
|
PermissionType["B_CLIENT_FORCE_PUSH_TO_TALK"] = "b_client_force_push_to_talk";
|
|
PermissionType["B_CLIENT_IGNORE_BANS"] = "b_client_ignore_bans";
|
|
PermissionType["B_CLIENT_IGNORE_VPN"] = "b_client_ignore_vpn";
|
|
PermissionType["B_CLIENT_IGNORE_ANTIFLOOD"] = "b_client_ignore_antiflood";
|
|
PermissionType["B_CLIENT_ENFORCE_VALID_HWID"] = "b_client_enforce_valid_hwid";
|
|
PermissionType["B_CLIENT_ALLOW_INVALID_PACKET"] = "b_client_allow_invalid_packet";
|
|
PermissionType["B_CLIENT_ALLOW_INVALID_BADGES"] = "b_client_allow_invalid_badges";
|
|
PermissionType["B_CLIENT_ISSUE_CLIENT_QUERY_COMMAND"] = "b_client_issue_client_query_command";
|
|
PermissionType["B_CLIENT_USE_RESERVED_SLOT"] = "b_client_use_reserved_slot";
|
|
PermissionType["B_CLIENT_USE_CHANNEL_COMMANDER"] = "b_client_use_channel_commander";
|
|
PermissionType["B_CLIENT_REQUEST_TALKER"] = "b_client_request_talker";
|
|
PermissionType["B_CLIENT_AVATAR_DELETE_OTHER"] = "b_client_avatar_delete_other";
|
|
PermissionType["B_CLIENT_IS_STICKY"] = "b_client_is_sticky";
|
|
PermissionType["B_CLIENT_IGNORE_STICKY"] = "b_client_ignore_sticky";
|
|
PermissionType["B_CLIENT_MUSIC_CREATE_PERMANENT"] = "b_client_music_create_permanent";
|
|
PermissionType["B_CLIENT_MUSIC_CREATE_SEMI_PERMANENT"] = "b_client_music_create_semi_permanent";
|
|
PermissionType["B_CLIENT_MUSIC_CREATE_TEMPORARY"] = "b_client_music_create_temporary";
|
|
PermissionType["B_CLIENT_MUSIC_MODIFY_PERMANENT"] = "b_client_music_modify_permanent";
|
|
PermissionType["B_CLIENT_MUSIC_MODIFY_SEMI_PERMANENT"] = "b_client_music_modify_semi_permanent";
|
|
PermissionType["B_CLIENT_MUSIC_MODIFY_TEMPORARY"] = "b_client_music_modify_temporary";
|
|
PermissionType["I_CLIENT_MUSIC_CREATE_MODIFY_MAX_VOLUME"] = "i_client_music_create_modify_max_volume";
|
|
PermissionType["I_CLIENT_MUSIC_LIMIT"] = "i_client_music_limit";
|
|
PermissionType["I_CLIENT_MUSIC_NEEDED_DELETE_POWER"] = "i_client_music_needed_delete_power";
|
|
PermissionType["I_CLIENT_MUSIC_DELETE_POWER"] = "i_client_music_delete_power";
|
|
PermissionType["I_CLIENT_MUSIC_PLAY_POWER"] = "i_client_music_play_power";
|
|
PermissionType["I_CLIENT_MUSIC_NEEDED_PLAY_POWER"] = "i_client_music_needed_play_power";
|
|
PermissionType["I_CLIENT_MUSIC_MODIFY_POWER"] = "i_client_music_modify_power";
|
|
PermissionType["I_CLIENT_MUSIC_NEEDED_MODIFY_POWER"] = "i_client_music_needed_modify_power";
|
|
PermissionType["I_CLIENT_MUSIC_RENAME_POWER"] = "i_client_music_rename_power";
|
|
PermissionType["I_CLIENT_MUSIC_NEEDED_RENAME_POWER"] = "i_client_music_needed_rename_power";
|
|
PermissionType["B_PLAYLIST_CREATE"] = "b_playlist_create";
|
|
PermissionType["I_PLAYLIST_VIEW_POWER"] = "i_playlist_view_power";
|
|
PermissionType["I_PLAYLIST_NEEDED_VIEW_POWER"] = "i_playlist_needed_view_power";
|
|
PermissionType["I_PLAYLIST_MODIFY_POWER"] = "i_playlist_modify_power";
|
|
PermissionType["I_PLAYLIST_NEEDED_MODIFY_POWER"] = "i_playlist_needed_modify_power";
|
|
PermissionType["I_PLAYLIST_PERMISSION_MODIFY_POWER"] = "i_playlist_permission_modify_power";
|
|
PermissionType["I_PLAYLIST_NEEDED_PERMISSION_MODIFY_POWER"] = "i_playlist_needed_permission_modify_power";
|
|
PermissionType["I_PLAYLIST_DELETE_POWER"] = "i_playlist_delete_power";
|
|
PermissionType["I_PLAYLIST_NEEDED_DELETE_POWER"] = "i_playlist_needed_delete_power";
|
|
PermissionType["I_PLAYLIST_SONG_ADD_POWER"] = "i_playlist_song_add_power";
|
|
PermissionType["I_PLAYLIST_SONG_NEEDED_ADD_POWER"] = "i_playlist_song_needed_add_power";
|
|
PermissionType["I_PLAYLIST_SONG_REMOVE_POWER"] = "i_playlist_song_remove_power";
|
|
PermissionType["I_PLAYLIST_SONG_NEEDED_REMOVE_POWER"] = "i_playlist_song_needed_remove_power";
|
|
PermissionType["B_CLIENT_INFO_VIEW"] = "b_client_info_view";
|
|
PermissionType["B_CLIENT_PERMISSIONOVERVIEW_VIEW"] = "b_client_permissionoverview_view";
|
|
PermissionType["B_CLIENT_PERMISSIONOVERVIEW_OWN"] = "b_client_permissionoverview_own";
|
|
PermissionType["B_CLIENT_REMOTEADDRESS_VIEW"] = "b_client_remoteaddress_view";
|
|
PermissionType["I_CLIENT_SERVERQUERY_VIEW_POWER"] = "i_client_serverquery_view_power";
|
|
PermissionType["I_CLIENT_NEEDED_SERVERQUERY_VIEW_POWER"] = "i_client_needed_serverquery_view_power";
|
|
PermissionType["B_CLIENT_CUSTOM_INFO_VIEW"] = "b_client_custom_info_view";
|
|
PermissionType["B_CLIENT_MUSIC_CHANNEL_LIST"] = "b_client_music_channel_list";
|
|
PermissionType["B_CLIENT_MUSIC_SERVER_LIST"] = "b_client_music_server_list";
|
|
PermissionType["I_CLIENT_MUSIC_INFO"] = "i_client_music_info";
|
|
PermissionType["I_CLIENT_MUSIC_NEEDED_INFO"] = "i_client_music_needed_info";
|
|
PermissionType["I_CLIENT_KICK_FROM_SERVER_POWER"] = "i_client_kick_from_server_power";
|
|
PermissionType["I_CLIENT_NEEDED_KICK_FROM_SERVER_POWER"] = "i_client_needed_kick_from_server_power";
|
|
PermissionType["I_CLIENT_KICK_FROM_CHANNEL_POWER"] = "i_client_kick_from_channel_power";
|
|
PermissionType["I_CLIENT_NEEDED_KICK_FROM_CHANNEL_POWER"] = "i_client_needed_kick_from_channel_power";
|
|
PermissionType["I_CLIENT_BAN_POWER"] = "i_client_ban_power";
|
|
PermissionType["I_CLIENT_NEEDED_BAN_POWER"] = "i_client_needed_ban_power";
|
|
PermissionType["I_CLIENT_MOVE_POWER"] = "i_client_move_power";
|
|
PermissionType["I_CLIENT_NEEDED_MOVE_POWER"] = "i_client_needed_move_power";
|
|
PermissionType["I_CLIENT_COMPLAIN_POWER"] = "i_client_complain_power";
|
|
PermissionType["I_CLIENT_NEEDED_COMPLAIN_POWER"] = "i_client_needed_complain_power";
|
|
PermissionType["B_CLIENT_COMPLAIN_LIST"] = "b_client_complain_list";
|
|
PermissionType["B_CLIENT_COMPLAIN_DELETE_OWN"] = "b_client_complain_delete_own";
|
|
PermissionType["B_CLIENT_COMPLAIN_DELETE"] = "b_client_complain_delete";
|
|
PermissionType["B_CLIENT_BAN_LIST"] = "b_client_ban_list";
|
|
PermissionType["B_CLIENT_BAN_LIST_GLOBAL"] = "b_client_ban_list_global";
|
|
PermissionType["B_CLIENT_BAN_TRIGGER_LIST"] = "b_client_ban_trigger_list";
|
|
PermissionType["B_CLIENT_BAN_CREATE"] = "b_client_ban_create";
|
|
PermissionType["B_CLIENT_BAN_CREATE_GLOBAL"] = "b_client_ban_create_global";
|
|
PermissionType["B_CLIENT_BAN_NAME"] = "b_client_ban_name";
|
|
PermissionType["B_CLIENT_BAN_IP"] = "b_client_ban_ip";
|
|
PermissionType["B_CLIENT_BAN_HWID"] = "b_client_ban_hwid";
|
|
PermissionType["B_CLIENT_BAN_EDIT"] = "b_client_ban_edit";
|
|
PermissionType["B_CLIENT_BAN_EDIT_GLOBAL"] = "b_client_ban_edit_global";
|
|
PermissionType["B_CLIENT_BAN_DELETE_OWN"] = "b_client_ban_delete_own";
|
|
PermissionType["B_CLIENT_BAN_DELETE"] = "b_client_ban_delete";
|
|
PermissionType["B_CLIENT_BAN_DELETE_OWN_GLOBAL"] = "b_client_ban_delete_own_global";
|
|
PermissionType["B_CLIENT_BAN_DELETE_GLOBAL"] = "b_client_ban_delete_global";
|
|
PermissionType["I_CLIENT_BAN_MAX_BANTIME"] = "i_client_ban_max_bantime";
|
|
PermissionType["I_CLIENT_PRIVATE_TEXTMESSAGE_POWER"] = "i_client_private_textmessage_power";
|
|
PermissionType["I_CLIENT_NEEDED_PRIVATE_TEXTMESSAGE_POWER"] = "i_client_needed_private_textmessage_power";
|
|
PermissionType["B_CLIENT_EVEN_TEXTMESSAGE_SEND"] = "b_client_even_textmessage_send";
|
|
PermissionType["B_CLIENT_SERVER_TEXTMESSAGE_SEND"] = "b_client_server_textmessage_send";
|
|
PermissionType["B_CLIENT_CHANNEL_TEXTMESSAGE_SEND"] = "b_client_channel_textmessage_send";
|
|
PermissionType["B_CLIENT_OFFLINE_TEXTMESSAGE_SEND"] = "b_client_offline_textmessage_send";
|
|
PermissionType["I_CLIENT_TALK_POWER"] = "i_client_talk_power";
|
|
PermissionType["I_CLIENT_NEEDED_TALK_POWER"] = "i_client_needed_talk_power";
|
|
PermissionType["I_CLIENT_POKE_POWER"] = "i_client_poke_power";
|
|
PermissionType["I_CLIENT_NEEDED_POKE_POWER"] = "i_client_needed_poke_power";
|
|
PermissionType["B_CLIENT_SET_FLAG_TALKER"] = "b_client_set_flag_talker";
|
|
PermissionType["I_CLIENT_WHISPER_POWER"] = "i_client_whisper_power";
|
|
PermissionType["I_CLIENT_NEEDED_WHISPER_POWER"] = "i_client_needed_whisper_power";
|
|
PermissionType["B_CLIENT_MODIFY_DESCRIPTION"] = "b_client_modify_description";
|
|
PermissionType["B_CLIENT_MODIFY_OWN_DESCRIPTION"] = "b_client_modify_own_description";
|
|
PermissionType["B_CLIENT_USE_BBCODE_ANY"] = "b_client_use_bbcode_any";
|
|
PermissionType["B_CLIENT_USE_BBCODE_URL"] = "b_client_use_bbcode_url";
|
|
PermissionType["B_CLIENT_USE_BBCODE_IMAGE"] = "b_client_use_bbcode_image";
|
|
PermissionType["B_CLIENT_MODIFY_DBPROPERTIES"] = "b_client_modify_dbproperties";
|
|
PermissionType["B_CLIENT_DELETE_DBPROPERTIES"] = "b_client_delete_dbproperties";
|
|
PermissionType["B_CLIENT_CREATE_MODIFY_SERVERQUERY_LOGIN"] = "b_client_create_modify_serverquery_login";
|
|
PermissionType["B_CLIENT_QUERY_CREATE"] = "b_client_query_create";
|
|
PermissionType["B_CLIENT_QUERY_LIST"] = "b_client_query_list";
|
|
PermissionType["B_CLIENT_QUERY_LIST_OWN"] = "b_client_query_list_own";
|
|
PermissionType["B_CLIENT_QUERY_RENAME"] = "b_client_query_rename";
|
|
PermissionType["B_CLIENT_QUERY_RENAME_OWN"] = "b_client_query_rename_own";
|
|
PermissionType["B_CLIENT_QUERY_CHANGE_PASSWORD"] = "b_client_query_change_password";
|
|
PermissionType["B_CLIENT_QUERY_CHANGE_OWN_PASSWORD"] = "b_client_query_change_own_password";
|
|
PermissionType["B_CLIENT_QUERY_CHANGE_PASSWORD_GLOBAL"] = "b_client_query_change_password_global";
|
|
PermissionType["B_CLIENT_QUERY_DELETE"] = "b_client_query_delete";
|
|
PermissionType["B_CLIENT_QUERY_DELETE_OWN"] = "b_client_query_delete_own";
|
|
PermissionType["B_FT_IGNORE_PASSWORD"] = "b_ft_ignore_password";
|
|
PermissionType["B_FT_TRANSFER_LIST"] = "b_ft_transfer_list";
|
|
PermissionType["I_FT_FILE_UPLOAD_POWER"] = "i_ft_file_upload_power";
|
|
PermissionType["I_FT_NEEDED_FILE_UPLOAD_POWER"] = "i_ft_needed_file_upload_power";
|
|
PermissionType["I_FT_FILE_DOWNLOAD_POWER"] = "i_ft_file_download_power";
|
|
PermissionType["I_FT_NEEDED_FILE_DOWNLOAD_POWER"] = "i_ft_needed_file_download_power";
|
|
PermissionType["I_FT_FILE_DELETE_POWER"] = "i_ft_file_delete_power";
|
|
PermissionType["I_FT_NEEDED_FILE_DELETE_POWER"] = "i_ft_needed_file_delete_power";
|
|
PermissionType["I_FT_FILE_RENAME_POWER"] = "i_ft_file_rename_power";
|
|
PermissionType["I_FT_NEEDED_FILE_RENAME_POWER"] = "i_ft_needed_file_rename_power";
|
|
PermissionType["I_FT_FILE_BROWSE_POWER"] = "i_ft_file_browse_power";
|
|
PermissionType["I_FT_NEEDED_FILE_BROWSE_POWER"] = "i_ft_needed_file_browse_power";
|
|
PermissionType["I_FT_DIRECTORY_CREATE_POWER"] = "i_ft_directory_create_power";
|
|
PermissionType["I_FT_NEEDED_DIRECTORY_CREATE_POWER"] = "i_ft_needed_directory_create_power";
|
|
PermissionType["I_FT_QUOTA_MB_DOWNLOAD_PER_CLIENT"] = "i_ft_quota_mb_download_per_client";
|
|
PermissionType["I_FT_QUOTA_MB_UPLOAD_PER_CLIENT"] = "i_ft_quota_mb_upload_per_client";
|
|
})(PermissionType || (PermissionType = {}));
|
|
class PermissionInfo {
|
|
is_boolean() { return this.name.startsWith("b_"); }
|
|
id_grant() {
|
|
return this.id | (1 << 15);
|
|
}
|
|
}
|
|
class PermissionGroup {
|
|
}
|
|
class GroupedPermissions {
|
|
}
|
|
class PermissionValue {
|
|
constructor(type, value) {
|
|
this.type = type;
|
|
this.value = value;
|
|
}
|
|
granted(requiredValue, required = true) {
|
|
let result;
|
|
result = this.value == -1 || this.value >= requiredValue || (this.value == -2 && requiredValue == -2 && !required);
|
|
log.trace(LogCategory.PERMISSIONS, _translations.l6YeuZJB || (_translations.l6YeuZJB = tr("Test needed required: %o | %i | %o => %o")), this, requiredValue, required, result);
|
|
return result;
|
|
}
|
|
hasValue() {
|
|
return typeof (this.value) !== "undefined" && this.value != -2;
|
|
}
|
|
hasGrant() {
|
|
return typeof (this.granted_value) !== "undefined" && this.granted_value != -2;
|
|
}
|
|
}
|
|
class NeededPermissionValue extends PermissionValue {
|
|
constructor(type, value) {
|
|
super(type, value);
|
|
this.changeListener = [];
|
|
}
|
|
}
|
|
class ChannelPermissionRequest {
|
|
constructor() {
|
|
this.callback_success = [];
|
|
this.callback_error = [];
|
|
}
|
|
}
|
|
class TeaPermissionRequest {
|
|
}
|
|
class PermissionManager extends connection.AbstractCommandHandler {
|
|
constructor(client) {
|
|
super(client.serverConnection);
|
|
this.permissionList = [];
|
|
this.permissionGroups = [];
|
|
this.neededPermissions = [];
|
|
this.requests_channel_permissions = [];
|
|
this.requests_client_permissions = [];
|
|
this.requests_client_channel_permissions = [];
|
|
this.requests_playlist_permissions = [];
|
|
this.initializedListener = [];
|
|
//FIXME? Dont register the handler like this?
|
|
this.volatile_handler_boss = true;
|
|
client.serverConnection.command_handler_boss().register_handler(this);
|
|
this.handle = client;
|
|
}
|
|
static parse_permission_bulk(json, manager) {
|
|
let permissions = [];
|
|
for (let perm of json) {
|
|
if (perm["permid"] === undefined)
|
|
continue;
|
|
let perm_id = parseInt(perm["permid"]);
|
|
let perm_grant = (perm_id & (1 << 15)) > 0;
|
|
if (perm_grant)
|
|
perm_id &= ~(1 << 15);
|
|
let perm_info = manager.resolveInfo(perm_id);
|
|
if (!perm_info) {
|
|
log.warn(LogCategory.PERMISSIONS, _translations.hiRWWQk0 || (_translations.hiRWWQk0 = tr("Got unknown permission id (%o/%o (%o))!")), perm["permid"], perm_id, perm["permsid"]);
|
|
return;
|
|
}
|
|
let permission;
|
|
for (let ref_perm of permissions) {
|
|
if (ref_perm.type == perm_info) {
|
|
permission = ref_perm;
|
|
break;
|
|
}
|
|
}
|
|
if (!permission) {
|
|
permission = new PermissionValue(perm_info, 0);
|
|
permission.granted_value = undefined;
|
|
permission.value = undefined;
|
|
permissions.push(permission);
|
|
}
|
|
if (perm_grant) {
|
|
permission.granted_value = parseInt(perm["permvalue"]);
|
|
}
|
|
else {
|
|
permission.value = parseInt(perm["permvalue"]);
|
|
permission.flag_negate = perm["permnegated"] == "1";
|
|
permission.flag_skip = perm["permskip"] == "1";
|
|
}
|
|
}
|
|
return permissions;
|
|
}
|
|
handle_command(command) {
|
|
switch (command.command) {
|
|
case "notifyclientneededpermissions":
|
|
this.onNeededPermissions(command.arguments);
|
|
return true;
|
|
case "notifypermissionlist":
|
|
this.onPermissionList(command.arguments);
|
|
return true;
|
|
case "notifychannelpermlist":
|
|
this.onChannelPermList(command.arguments);
|
|
return true;
|
|
case "notifyclientpermlist":
|
|
this.onClientPermList(command.arguments);
|
|
return true;
|
|
case "notifyplaylistpermlist":
|
|
this.onPlaylistPermList(command.arguments);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
initialized() {
|
|
return this.permissionList.length > 0;
|
|
}
|
|
requestPermissionList() {
|
|
this.handle.serverConnection.send_command("permissionlist");
|
|
}
|
|
onPermissionList(json) {
|
|
this.permissionList = [];
|
|
this.permissionGroups = [];
|
|
this._group_mapping = PermissionManager.group_mapping.slice();
|
|
let group = log.group(log.LogType.TRACE, LogCategory.PERMISSIONS, _translations.KvTloMLv || (_translations.KvTloMLv = tr("Permission mapping")));
|
|
for (let e of json) {
|
|
if (e["group_id_end"]) {
|
|
let group = new PermissionGroup();
|
|
group.begin = this.permissionGroups.length ? this.permissionGroups.last().end : 0;
|
|
group.end = parseInt(e["group_id_end"]);
|
|
group.deep = 0;
|
|
group.name = (_translations.MSzE2M5g || (_translations.MSzE2M5g = tr("Group "))) + e["group_id_end"];
|
|
let info = this._group_mapping.pop_front();
|
|
if (info) {
|
|
group.name = info.name;
|
|
group.deep = info.deep;
|
|
}
|
|
this.permissionGroups.push(group);
|
|
}
|
|
let perm = new PermissionInfo();
|
|
perm.name = e["permname"];
|
|
perm.id = parseInt(e["permid"]);
|
|
perm.description = e["permdesc"];
|
|
group.log(_translations.Icp51Xyn || (_translations.Icp51Xyn = tr("%i <> %s -> %s")), perm.id, perm.name, perm.description);
|
|
this.permissionList.push(perm);
|
|
}
|
|
group.end();
|
|
log.info(LogCategory.PERMISSIONS, _translations.JCXF8tNn || (_translations.JCXF8tNn = tr("Got %i permissions")), this.permissionList.length);
|
|
if (this._cacheNeededPermissions)
|
|
this.onNeededPermissions(this._cacheNeededPermissions);
|
|
for (let listener of this.initializedListener)
|
|
listener(true);
|
|
}
|
|
onNeededPermissions(json) {
|
|
if (this.permissionList.length == 0) {
|
|
log.warn(LogCategory.PERMISSIONS, _translations.xW3OtQsi || (_translations.xW3OtQsi = tr("Got needed permissions but don't have a permission list!")));
|
|
this._cacheNeededPermissions = json;
|
|
return;
|
|
}
|
|
this._cacheNeededPermissions = undefined;
|
|
let copy = this.neededPermissions.slice();
|
|
let addcount = 0;
|
|
let group = log.group(log.LogType.TRACE, LogCategory.PERMISSIONS, _translations.gqaXY6XV || (_translations.gqaXY6XV = tr("Got %d needed permissions.")), json.length);
|
|
for (let e of json) {
|
|
let entry = undefined;
|
|
for (let p of copy) {
|
|
if (p.type.id == e["permid"]) {
|
|
entry = p;
|
|
copy.remove(p);
|
|
break;
|
|
}
|
|
}
|
|
if (!entry) {
|
|
let info = this.resolveInfo(e["permid"]);
|
|
if (info) {
|
|
entry = new NeededPermissionValue(info, -2);
|
|
this.neededPermissions.push(entry);
|
|
}
|
|
else {
|
|
log.warn(LogCategory.PERMISSIONS, _translations.GQx2LqqU || (_translations.GQx2LqqU = tr("Could not resolve perm for id %s (%o|%o)")), e["permid"], e, info);
|
|
continue;
|
|
}
|
|
addcount++;
|
|
}
|
|
if (entry.value == parseInt(e["permvalue"]))
|
|
continue;
|
|
entry.value = parseInt(e["permvalue"]);
|
|
//TODO tr
|
|
group.log("Update needed permission " + entry.type.name + " to " + entry.value);
|
|
for (let listener of entry.changeListener)
|
|
listener(entry.value);
|
|
}
|
|
group.end();
|
|
//TODO tr
|
|
log.debug(LogCategory.PERMISSIONS, "Dropping " + copy.length + " needed permissions and added " + addcount + " permissions.");
|
|
for (let e of copy) {
|
|
e.value = -2;
|
|
for (let listener of e.changeListener)
|
|
listener(e.value);
|
|
}
|
|
}
|
|
onChannelPermList(json) {
|
|
let channelId = parseInt(json[0]["cid"]);
|
|
let permissions = PermissionManager.parse_permission_bulk(json, this.handle.permissions);
|
|
log.debug(LogCategory.PERMISSIONS, _translations.TU9ekKrB || (_translations.TU9ekKrB = tr("Got channel permissions for channel %o")), channelId);
|
|
for (let element of this.requests_channel_permissions) {
|
|
if (element.channel_id == channelId) {
|
|
for (let l of element.callback_success)
|
|
l(permissions);
|
|
this.requests_channel_permissions.remove(element);
|
|
return;
|
|
}
|
|
}
|
|
log.debug(LogCategory.PERMISSIONS, _translations.ODK68n4X || (_translations.ODK68n4X = tr("Missing channel permission handle for requested channel id %o")), channelId);
|
|
}
|
|
resolveInfo(key) {
|
|
for (let perm of this.permissionList)
|
|
if (perm.id == key || perm.name == key)
|
|
return perm;
|
|
return undefined;
|
|
}
|
|
requestChannelPermissions(channelId) {
|
|
return new Promise((resolve, reject) => {
|
|
let request;
|
|
for (let element of this.requests_channel_permissions)
|
|
if (element.requested + 1000 < Date.now() && element.channel_id == channelId) {
|
|
request = element;
|
|
break;
|
|
}
|
|
if (!request) {
|
|
request = new ChannelPermissionRequest();
|
|
request.requested = Date.now();
|
|
request.channel_id = channelId;
|
|
this.handle.serverConnection.send_command("channelpermlist", { "cid": channelId });
|
|
this.requests_channel_permissions.push(request);
|
|
}
|
|
request.callback_error.push(reject);
|
|
request.callback_success.push(resolve);
|
|
});
|
|
}
|
|
onClientPermList(json) {
|
|
let client = parseInt(json[0]["cldbid"]);
|
|
let permissions = PermissionManager.parse_permission_bulk(json, this);
|
|
for (let req of this.requests_client_permissions.slice(0)) {
|
|
if (req.client_avatar_id == client) {
|
|
this.requests_client_permissions.remove(req);
|
|
req.promise.resolved(permissions);
|
|
}
|
|
}
|
|
}
|
|
requestClientPermissions(client_id) {
|
|
for (let request of this.requests_client_permissions)
|
|
if (request.client_avatar_id == client_id && request.promise.time() + 1000 > Date.now())
|
|
return request.promise;
|
|
let request = {};
|
|
request.client_id = client_id;
|
|
request.promise = new LaterPromise();
|
|
this.handle.serverConnection.send_command("clientpermlist", { cldbid: client_id }).catch(error => {
|
|
if (error instanceof CommandResult && error.id == ErrorID.EMPTY_RESULT)
|
|
request.promise.resolved([]);
|
|
else
|
|
request.promise.rejected(error);
|
|
});
|
|
this.requests_client_permissions.push(request);
|
|
return request.promise;
|
|
}
|
|
requestClientChannelPermissions(client_id, channel_id) {
|
|
for (let request of this.requests_client_channel_permissions)
|
|
if (request.client_avatar_id == client_id && request.channel_id == channel_id && request.promise.time() + 1000 > Date.now())
|
|
return request.promise;
|
|
let request = {};
|
|
request.client_id = client_id;
|
|
request.channel_id = channel_id;
|
|
request.promise = new LaterPromise();
|
|
this.handle.serverConnection.send_command("channelclientpermlist", { cldbid: client_id, cid: channel_id }).catch(error => {
|
|
if (error instanceof CommandResult && error.id == ErrorID.EMPTY_RESULT)
|
|
request.promise.resolved([]);
|
|
else
|
|
request.promise.rejected(error);
|
|
});
|
|
this.requests_client_channel_permissions.push(request);
|
|
return request.promise;
|
|
}
|
|
onPlaylistPermList(json) {
|
|
let playlist_id = parseInt(json[0]["playlist_id"]);
|
|
let permissions = PermissionManager.parse_permission_bulk(json, this);
|
|
for (let req of this.requests_playlist_permissions.slice(0)) {
|
|
if (req.playlist_id == playlist_id) {
|
|
this.requests_playlist_permissions.remove(req);
|
|
req.promise.resolved(permissions);
|
|
}
|
|
}
|
|
}
|
|
requestPlaylistPermissions(playlist_id) {
|
|
for (let request of this.requests_playlist_permissions)
|
|
if (request.playlist_id == playlist_id && request.promise.time() + 1000 > Date.now())
|
|
return request.promise;
|
|
let request = {};
|
|
request.playlist_id = playlist_id;
|
|
request.promise = new LaterPromise();
|
|
this.handle.serverConnection.send_command("playlistpermlist", { playlist_id: playlist_id }).catch(error => {
|
|
if (error instanceof CommandResult && error.id == ErrorID.EMPTY_RESULT)
|
|
request.promise.resolved([]);
|
|
else
|
|
request.promise.rejected(error);
|
|
});
|
|
this.requests_playlist_permissions.push(request);
|
|
return request.promise;
|
|
}
|
|
neededPermission(key) {
|
|
for (let perm of this.neededPermissions)
|
|
if (perm.type.id == key || perm.type.name == key || perm.type == key)
|
|
return perm;
|
|
log.debug(LogCategory.PERMISSIONS, _translations.REzpKcHE || (_translations.REzpKcHE = tr("Could not resolve grant permission %o. Creating a new one.")), key);
|
|
let info = key instanceof PermissionInfo ? key : this.resolveInfo(key);
|
|
if (!info) {
|
|
log.warn(LogCategory.PERMISSIONS, _translations.cFseHpLq || (_translations.cFseHpLq = tr("Requested needed permission with invalid key! (%o)")), key);
|
|
return new NeededPermissionValue(undefined, -2);
|
|
}
|
|
let result = new NeededPermissionValue(info, -2);
|
|
this.neededPermissions.push(result);
|
|
return result;
|
|
}
|
|
groupedPermissions() {
|
|
let result = [];
|
|
let current;
|
|
for (let group of this.permissionGroups) {
|
|
if (group.deep == 0) {
|
|
current = new GroupedPermissions();
|
|
current.group = group;
|
|
current.parent = undefined;
|
|
current.children = [];
|
|
current.permissions = [];
|
|
result.push(current);
|
|
}
|
|
else {
|
|
if (!current) {
|
|
throw _translations.q7zQFaQp || (_translations.q7zQFaQp = tr("invalid order!"));
|
|
}
|
|
else {
|
|
while (group.deep <= current.group.deep)
|
|
current = current.parent;
|
|
let parent = current;
|
|
current = new GroupedPermissions();
|
|
current.group = group;
|
|
current.parent = parent;
|
|
current.children = [];
|
|
current.permissions = [];
|
|
parent.children.push(current);
|
|
}
|
|
}
|
|
for (let permission of this.permissionList)
|
|
if (permission.id > current.group.begin && permission.id <= current.group.end)
|
|
current.permissions.push(permission);
|
|
}
|
|
return result;
|
|
}
|
|
/**
|
|
* Generates an enum with all know permission types, used for the enum above
|
|
*/
|
|
export_permission_types() {
|
|
let result = "";
|
|
result = result + "enum PermissionType {\n";
|
|
for (const permission of this.permissionList) {
|
|
if (!permission.name)
|
|
continue;
|
|
result = result + "\t" + permission.name.toUpperCase() + " = \"" + permission.name.toLowerCase() + "\", /* Permission ID: " + permission.id + " */\n";
|
|
}
|
|
result = result + "}";
|
|
return result;
|
|
}
|
|
}
|
|
/* Static info mapping until TeaSpeak implements a detailed info */
|
|
//TODO tr
|
|
PermissionManager.group_mapping = [
|
|
{ name: "Global", deep: 0 },
|
|
{ name: "Information", deep: 1 },
|
|
{ name: "Virtual server management", deep: 1 },
|
|
{ name: "Administration", deep: 1 },
|
|
{ name: "Settings", deep: 1 },
|
|
{ name: "Virtual Server", deep: 0 },
|
|
{ name: "Information", deep: 1 },
|
|
{ name: "Administration", deep: 1 },
|
|
{ name: "Settings", deep: 1 },
|
|
{ name: "Channel", deep: 0 },
|
|
{ name: "Information", deep: 1 },
|
|
{ name: "Create", deep: 1 },
|
|
{ name: "Modify", deep: 1 },
|
|
{ name: "Delete", deep: 1 },
|
|
{ name: "Access", deep: 1 },
|
|
{ name: "Group", deep: 0 },
|
|
{ name: "Information", deep: 1 },
|
|
{ name: "Create", deep: 1 },
|
|
{ name: "Modify", deep: 1 },
|
|
{ name: "Delete", deep: 1 },
|
|
{ name: "Client", deep: 0 },
|
|
{ name: "Information", deep: 1 },
|
|
{ name: "Admin", deep: 1 },
|
|
{ name: "Basics", deep: 1 },
|
|
{ name: "Modify", deep: 1 },
|
|
//TODO Music bot
|
|
{ name: "File Transfer", deep: 0 },
|
|
];
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["a81ae99c9fe3d1a6dabcacaa70a4f4effcbf39ca57367d993b18036432881f23"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["a81ae99c9fe3d1a6dabcacaa70a4f4effcbf39ca57367d993b18036432881f23"] = "a81ae99c9fe3d1a6dabcacaa70a4f4effcbf39ca57367d993b18036432881f23";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "NNGAmR6u", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/GroupManager.ts (127,27)" }, { name: "tVu_YwTx", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/GroupManager.ts (197,48)" }, { name: "zZLMJZGq", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/permission/GroupManager.ts (206,47)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../connection/ConnectionBase.ts" />
|
|
var GroupType;
|
|
(function (GroupType) {
|
|
GroupType[GroupType["QUERY"] = 0] = "QUERY";
|
|
GroupType[GroupType["TEMPLATE"] = 1] = "TEMPLATE";
|
|
GroupType[GroupType["NORMAL"] = 2] = "NORMAL";
|
|
})(GroupType || (GroupType = {}));
|
|
var GroupTarget;
|
|
(function (GroupTarget) {
|
|
GroupTarget[GroupTarget["SERVER"] = 0] = "SERVER";
|
|
GroupTarget[GroupTarget["CHANNEL"] = 1] = "CHANNEL";
|
|
})(GroupTarget || (GroupTarget = {}));
|
|
class GroupProperties {
|
|
constructor() {
|
|
this.iconid = 0;
|
|
this.sortid = 0;
|
|
this.savedb = false;
|
|
this.namemode = 0;
|
|
}
|
|
}
|
|
class GroupPermissionRequest {
|
|
}
|
|
class Group {
|
|
constructor(handle, id, target, type, name) {
|
|
this.properties = new GroupProperties();
|
|
this.requiredModifyPower = 0;
|
|
this.requiredMemberAddPower = 0;
|
|
this.requiredMemberRemovePower = 0;
|
|
this.handle = handle;
|
|
this.id = id;
|
|
this.target = target;
|
|
this.type = type;
|
|
this.name = name;
|
|
}
|
|
updateProperty(key, value) {
|
|
JSON.map_field_to(this.properties, value, key);
|
|
if (key == "iconid") {
|
|
this.properties.iconid = (new Uint32Array([this.properties.iconid]))[0];
|
|
console.log("Icon id " + this.properties.iconid);
|
|
this.handle.handle.channelTree.clientsByGroup(this).forEach(client => {
|
|
client.updateGroupIcon(this);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
class GroupManager extends connection.AbstractCommandHandler {
|
|
constructor(client) {
|
|
super(client.serverConnection);
|
|
this.serverGroups = [];
|
|
this.channelGroups = [];
|
|
this.requests_group_permissions = [];
|
|
client.serverConnection.command_handler_boss().register_handler(this);
|
|
this.handle = client;
|
|
}
|
|
handle_command(command) {
|
|
switch (command.command) {
|
|
case "notifyservergrouplist":
|
|
case "notifychannelgrouplist":
|
|
this.handle_grouplist(command.arguments);
|
|
return true;
|
|
case "notifyservergrouppermlist":
|
|
case "notifychannelgrouppermlist":
|
|
this.handle_group_permission_list(command.arguments);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
requestGroups() {
|
|
this.handle.serverConnection.send_command("servergrouplist");
|
|
this.handle.serverConnection.send_command("channelgrouplist");
|
|
}
|
|
static sorter() {
|
|
return (a, b) => {
|
|
if (a.properties.sortid > b.properties.sortid)
|
|
return 1;
|
|
if (a.properties.sortid < b.properties.sortid)
|
|
return -1;
|
|
if (a.id < b.id)
|
|
return -1;
|
|
if (a.id > b.id)
|
|
return 1;
|
|
return 0;
|
|
};
|
|
}
|
|
serverGroup(id) {
|
|
for (let group of this.serverGroups)
|
|
if (group.id == id)
|
|
return group;
|
|
return undefined;
|
|
}
|
|
channelGroup(id) {
|
|
for (let group of this.channelGroups)
|
|
if (group.id == id)
|
|
return group;
|
|
return undefined;
|
|
}
|
|
handle_grouplist(json) {
|
|
let target;
|
|
if (json[0]["sgid"])
|
|
target = GroupTarget.SERVER;
|
|
else if (json[0]["cgid"])
|
|
target = GroupTarget.CHANNEL;
|
|
else {
|
|
console.error(_translations.NNGAmR6u || (_translations.NNGAmR6u = tr("Could not resolve group target! => %o")), json[0]);
|
|
return;
|
|
}
|
|
if (target == GroupTarget.SERVER)
|
|
this.serverGroups = [];
|
|
else
|
|
this.channelGroups = [];
|
|
for (let groupData of json) {
|
|
let type;
|
|
switch (Number.parseInt(groupData["type"])) {
|
|
case 0:
|
|
type = GroupType.TEMPLATE;
|
|
break;
|
|
case 1:
|
|
type = GroupType.NORMAL;
|
|
break;
|
|
case 2:
|
|
type = GroupType.QUERY;
|
|
break;
|
|
default:
|
|
//TODO tr
|
|
console.error("Invalid group type: " + groupData["type"] + " for group " + groupData["name"]);
|
|
continue;
|
|
}
|
|
let group = new Group(this, parseInt(target == GroupTarget.SERVER ? groupData["sgid"] : groupData["cgid"]), target, type, groupData["name"]);
|
|
for (let key in groupData) {
|
|
if (key == "sgid")
|
|
continue;
|
|
if (key == "cgid")
|
|
continue;
|
|
if (key == "type")
|
|
continue;
|
|
if (key == "name")
|
|
continue;
|
|
group.updateProperty(key, groupData[key]);
|
|
}
|
|
group.requiredMemberRemovePower = parseInt(groupData["n_member_removep"]);
|
|
group.requiredMemberAddPower = parseInt(groupData["n_member_addp"]);
|
|
group.requiredModifyPower = parseInt(groupData["n_modifyp"]);
|
|
if (target == GroupTarget.SERVER)
|
|
this.serverGroups.push(group);
|
|
else
|
|
this.channelGroups.push(group);
|
|
}
|
|
console.log("Got " + json.length + " new " + target + " groups:");
|
|
for (const client of this.handle.channelTree.clients)
|
|
client.update_displayed_client_groups();
|
|
}
|
|
request_permissions(group) {
|
|
for (let request of this.requests_group_permissions)
|
|
if (request.group_id == group.id && request.promise.time() + 1000 > Date.now())
|
|
return request.promise;
|
|
let req = new GroupPermissionRequest();
|
|
req.group_id = group.id;
|
|
req.promise = new LaterPromise();
|
|
this.requests_group_permissions.push(req);
|
|
this.handle.serverConnection.send_command(group.target == GroupTarget.SERVER ? "servergrouppermlist" : "channelgrouppermlist", {
|
|
cgid: group.id,
|
|
sgid: group.id
|
|
}).catch(error => {
|
|
if (error instanceof CommandResult && error.id == 0x0501)
|
|
req.promise.resolved([]);
|
|
else
|
|
req.promise.rejected(error);
|
|
});
|
|
return req.promise;
|
|
}
|
|
handle_group_permission_list(json) {
|
|
let group = json[0]["sgid"] ? this.serverGroup(parseInt(json[0]["sgid"])) : this.channelGroup(parseInt(json[0]["cgid"]));
|
|
if (!group) {
|
|
log.error(LogCategory.PERMISSIONS, _translations.tVu_YwTx || (_translations.tVu_YwTx = tr("Got group permissions for group %o/%o, but its not a registered group!")), json[0]["sgid"], json[0]["cgid"]);
|
|
return;
|
|
}
|
|
let requests = [];
|
|
for (let req of this.requests_group_permissions)
|
|
if (req.group_id == group.id)
|
|
requests.push(req);
|
|
if (requests.length == 0) {
|
|
log.warn(LogCategory.PERMISSIONS, _translations.zZLMJZGq || (_translations.zZLMJZGq = tr("Got group permissions for group %o/%o, but it was never requested!")), json[0]["sgid"], json[0]["cgid"]);
|
|
return;
|
|
}
|
|
let permissions = PermissionManager.parse_permission_bulk(json, this.handle.permissions);
|
|
for (let req of requests) {
|
|
this.requests_group_permissions.remove(req);
|
|
req.promise.resolved(permissions);
|
|
}
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["ec835d42b3d6ae771f5f0eae50c26c1e8b071995d5df1245175c0bc10ac5fb84"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["ec835d42b3d6ae771f5f0eae50c26c1e8b071995d5df1245175c0bc10ac5fb84"] = "ec835d42b3d6ae771f5f0eae50c26c1e8b071995d5df1245175c0bc10ac5fb84";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "Aj8PajLX", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/i18n/localize.ts (105,52)" }, { name: "uLm8UOda", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/i18n/localize.ts (106,32)" }, { name: "WxSsQs_w", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/i18n/localize.ts (110,28)" }, { name: "p6yJmpGX", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/i18n/localize.ts (118,40)" }, { name: "HlyUXdnU", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/i18n/localize.ts (122,40)" }, { name: "kcmdR8r1", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/i18n/localize.ts (144,32)" }, { name: "lQdjng16", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/i18n/localize.ts (196,48)" }, { name: "yEYagZjd", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/i18n/localize.ts (199,48)" }, { name: "U6ARXz_h", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/i18n/localize.ts (278,52)" }, { name: "F2K3ghGt", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/i18n/localize.ts (288,44)" }, { name: "lQqId0FO", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/i18n/localize.ts (323,34)" }, { name: "j5y8yWZu", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/i18n/localize.ts (323,60)" }, { name: "ytLhnjvg", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/i18n/localize.ts (323,196)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/*
|
|
"key": {
|
|
"message": "Show permission description",
|
|
"line": 374,
|
|
"character": 30,
|
|
"filename": "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts"
|
|
},
|
|
"translated": "Berechtigungsbeschreibung anzeigen",
|
|
"flags": [
|
|
"google-translate",
|
|
"verified"
|
|
]
|
|
*/
|
|
function guid() {
|
|
function s4() {
|
|
return Math.floor((1 + Math.random()) * 0x10000)
|
|
.toString(16)
|
|
.substring(1);
|
|
}
|
|
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
|
|
}
|
|
var i18n;
|
|
(function (i18n) {
|
|
let translations = [];
|
|
let fast_translate = {};
|
|
function tr(message, key) {
|
|
const sloppy = fast_translate[message];
|
|
if (sloppy)
|
|
return sloppy;
|
|
log.info(LogCategory.I18N, "Translating \"%s\". Default: \"%s\"", key, message);
|
|
let translated = message;
|
|
for (const translation of translations) {
|
|
if (translation.key.message == message) {
|
|
translated = translation.translated;
|
|
break;
|
|
}
|
|
}
|
|
fast_translate[message] = translated;
|
|
return translated;
|
|
}
|
|
i18n.tr = tr;
|
|
function load_translation_file(url) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
return new Promise((resolve, reject) => {
|
|
$.ajax({
|
|
url: url,
|
|
async: true,
|
|
success: result => {
|
|
try {
|
|
const file = (typeof (result) === "string" ? JSON.parse(result) : result);
|
|
if (!file) {
|
|
reject("Invalid json");
|
|
return;
|
|
}
|
|
file.url = url;
|
|
//TODO validate file
|
|
resolve(file);
|
|
}
|
|
catch (error) {
|
|
log.warn(LogCategory.I18N, _translations.Aj8PajLX || (_translations.Aj8PajLX = tr("Failed to load translation file %s. Failed to parse or process json: %o")), url, error);
|
|
reject(_translations.uLm8UOda || (_translations.uLm8UOda = tr("Failed to process or parse json!")));
|
|
}
|
|
},
|
|
error: (xhr, error) => {
|
|
reject((_translations.WxSsQs_w || (_translations.WxSsQs_w = tr("Failed to load file: "))) + error);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
function load_file(url) {
|
|
return load_translation_file(url).then(result => {
|
|
log.info(LogCategory.I18N, _translations.p6yJmpGX || (_translations.p6yJmpGX = tr("Successfully initialized up translation file from %s")), url);
|
|
translations = result.translations;
|
|
return Promise.resolve();
|
|
}).catch(error => {
|
|
log.warn(LogCategory.I18N, _translations.HlyUXdnU || (_translations.HlyUXdnU = tr("Failed to load translation file from \"%s\". Error: %o")), url, error);
|
|
return Promise.reject(error);
|
|
});
|
|
}
|
|
i18n.load_file = load_file;
|
|
function load_repository0(repo, reload) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
if (!repo.load_timestamp || repo.load_timestamp < 1000 || reload) {
|
|
const info_json = yield new Promise((resolve, reject) => {
|
|
$.ajax({
|
|
url: repo.url + "/info.json",
|
|
async: true,
|
|
cache: !reload,
|
|
success: result => {
|
|
const file = (typeof (result) === "string" ? JSON.parse(result) : result);
|
|
if (!file) {
|
|
reject("Invalid json");
|
|
return;
|
|
}
|
|
resolve(file);
|
|
},
|
|
error: (xhr, error) => {
|
|
reject((_translations.kcmdR8r1 || (_translations.kcmdR8r1 = tr("Failed to load file: "))) + error);
|
|
}
|
|
});
|
|
});
|
|
Object.assign(repo, info_json);
|
|
}
|
|
if (!repo.unique_id)
|
|
repo.unique_id = guid();
|
|
repo.translations = repo.translations || [];
|
|
repo.load_timestamp = Date.now();
|
|
});
|
|
}
|
|
function load_repository(url) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const result = {};
|
|
result.url = url;
|
|
yield load_repository0(result, false);
|
|
return result;
|
|
});
|
|
}
|
|
i18n.load_repository = load_repository;
|
|
let config;
|
|
(function (config_1) {
|
|
const repository_config_key = "i18n.repository";
|
|
let _cached_repository_config;
|
|
function repository_config() {
|
|
if (_cached_repository_config)
|
|
return _cached_repository_config;
|
|
const config_string = localStorage.getItem(repository_config_key);
|
|
const config = config_string ? JSON.parse(config_string) : {};
|
|
config.repositories = config.repositories || [];
|
|
for (const repo of config.repositories)
|
|
(repo.repository || { load_timestamp: 0 }).load_timestamp = 0;
|
|
if (config.repositories.length == 0) {
|
|
//Add the default TeaSpeak repository
|
|
load_repository(StaticSettings.instance.static("i18n.default_repository", "i18n/")).then(repo => {
|
|
log.info(LogCategory.I18N, _translations.lQdjng16 || (_translations.lQdjng16 = tr("Successfully added default repository from \"%s\".")), repo.url);
|
|
register_repository(repo);
|
|
}).catch(error => {
|
|
log.warn(LogCategory.I18N, _translations.yEYagZjd || (_translations.yEYagZjd = tr("Failed to add default repository. Error: %o")), error);
|
|
});
|
|
}
|
|
return _cached_repository_config = config;
|
|
}
|
|
config_1.repository_config = repository_config;
|
|
function save_repository_config() {
|
|
localStorage.setItem(repository_config_key, JSON.stringify(_cached_repository_config));
|
|
}
|
|
config_1.save_repository_config = save_repository_config;
|
|
const translation_config_key = "i18n.translation";
|
|
let _cached_translation_config;
|
|
function translation_config() {
|
|
if (_cached_translation_config)
|
|
return _cached_translation_config;
|
|
const config_string = localStorage.getItem(translation_config_key);
|
|
_cached_translation_config = config_string ? JSON.parse(config_string) : {};
|
|
return _cached_translation_config;
|
|
}
|
|
config_1.translation_config = translation_config;
|
|
function save_translation_config() {
|
|
localStorage.setItem(translation_config_key, JSON.stringify(_cached_translation_config));
|
|
}
|
|
config_1.save_translation_config = save_translation_config;
|
|
})(config = i18n.config || (i18n.config = {}));
|
|
function register_repository(repository) {
|
|
if (!repository)
|
|
return;
|
|
for (const repo of config.repository_config().repositories)
|
|
if (repo.url == repository.url)
|
|
return;
|
|
config.repository_config().repositories.push(repository);
|
|
config.save_repository_config();
|
|
}
|
|
i18n.register_repository = register_repository;
|
|
function registered_repositories() {
|
|
return config.repository_config().repositories.map(e => e.repository || { url: e.url, load_timestamp: 0 });
|
|
}
|
|
i18n.registered_repositories = registered_repositories;
|
|
function delete_repository(repository) {
|
|
if (!repository)
|
|
return;
|
|
for (const repo of [...config.repository_config().repositories])
|
|
if (repo.url == repository.url) {
|
|
config.repository_config().repositories.remove(repo);
|
|
}
|
|
config.save_repository_config();
|
|
}
|
|
i18n.delete_repository = delete_repository;
|
|
function iterate_translations(callback_entry, callback_finish) {
|
|
let count = 0;
|
|
const update_finish = () => {
|
|
if (count == 0 && callback_finish)
|
|
callback_finish();
|
|
};
|
|
for (const repo of registered_repositories()) {
|
|
count++;
|
|
load_repository0(repo, false).then(() => {
|
|
for (const translation of repo.translations || []) {
|
|
const translation_path = repo.url + "/" + translation.path;
|
|
count++;
|
|
load_translation_file(translation_path).then(file => {
|
|
if (callback_entry) {
|
|
try {
|
|
callback_entry(repo, file);
|
|
}
|
|
catch (error) {
|
|
console.error(error);
|
|
//TODO more error handling?
|
|
}
|
|
}
|
|
count--;
|
|
update_finish();
|
|
}).catch(error => {
|
|
log.warn(LogCategory.I18N, _translations.U6ARXz_h || (_translations.U6ARXz_h = tr("Failed to load translation file for repository %s. Translation: %s (%s) Error: %o")), repo.name, translation.key, translation_path, error);
|
|
count--;
|
|
update_finish();
|
|
});
|
|
}
|
|
count--;
|
|
update_finish();
|
|
}).catch(error => {
|
|
log.warn(LogCategory.I18N, _translations.F2K3ghGt || (_translations.F2K3ghGt = tr("Failed to load repository while iteration: %s (%s). Error: %o")), (repo || { name: "unknown" }).name, (repo || { url: "unknown" }).url, error);
|
|
count--;
|
|
update_finish();
|
|
});
|
|
}
|
|
update_finish();
|
|
}
|
|
i18n.iterate_translations = iterate_translations;
|
|
function select_translation(repository, entry) {
|
|
const cfg = config.translation_config();
|
|
if (entry && repository) {
|
|
cfg.current_language = entry.info.name;
|
|
cfg.current_repository_url = repository.url;
|
|
cfg.current_translation_url = entry.url;
|
|
}
|
|
else {
|
|
cfg.current_language = undefined;
|
|
cfg.current_repository_url = undefined;
|
|
cfg.current_translation_url = undefined;
|
|
}
|
|
config.save_translation_config();
|
|
}
|
|
i18n.select_translation = select_translation;
|
|
function initialize() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const rcfg = config.repository_config(); /* initialize */
|
|
const cfg = config.translation_config();
|
|
if (cfg.current_translation_url) {
|
|
try {
|
|
yield load_file(cfg.current_translation_url);
|
|
}
|
|
catch (error) {
|
|
createErrorModal(_translations.lQqId0FO || (_translations.lQqId0FO = tr("Translation System")), (_translations.j5y8yWZu || (_translations.j5y8yWZu = tr("Failed to load current selected translation file."))) + "<br>File: " + cfg.current_translation_url + "<br>Error: " + error + "<br>" + (_translations.ytLhnjvg || (_translations.ytLhnjvg = tr("Using default fallback translations.")))).open();
|
|
}
|
|
}
|
|
// await load_file("http://localhost/home/TeaSpeak/TeaSpeak/Web-Client/web/environment/development/i18n/de_DE.translation");
|
|
// await load_file("http://localhost/home/TeaSpeak/TeaSpeak/Web-Client/web/environment/development/i18n/test.json");
|
|
});
|
|
}
|
|
i18n.initialize = initialize;
|
|
})(i18n || (i18n = {}));
|
|
const tr = i18n.tr;
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["0608e67a6e07bc39237edb01d392a99930ecb6de98d5577d8ba63f5d84388743"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["0608e67a6e07bc39237edb01d392a99930ecb6de98d5577d8ba63f5d84388743"] = "0608e67a6e07bc39237edb01d392a99930ecb6de98d5577d8ba63f5d84388743";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "Z3yXpqqL", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/utils/tab.ts (26,18)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../i18n/localize.ts" />
|
|
if (typeof (customElements) !== "undefined") {
|
|
try {
|
|
class X_Tab extends HTMLElement {
|
|
}
|
|
class X_Entry extends HTMLElement {
|
|
}
|
|
class X_Tag extends HTMLElement {
|
|
}
|
|
class X_Content extends HTMLElement {
|
|
}
|
|
customElements.define('x-tab', X_Tab, { extends: 'div' });
|
|
customElements.define('x-entry', X_Entry, { extends: 'div' });
|
|
customElements.define('x-tag', X_Tag, { extends: 'div' });
|
|
customElements.define('x-content', X_Content, { extends: 'div' });
|
|
}
|
|
catch (error) {
|
|
console.warn("failed to define costum elements");
|
|
}
|
|
}
|
|
else {
|
|
console.warn(_translations.Z3yXpqqL || (_translations.Z3yXpqqL = tr("Could not defied tab customElements!")));
|
|
}
|
|
var TabFunctions = {
|
|
tabify(template, copy = true) {
|
|
console.log("Tabify: copy=" + copy);
|
|
console.log(template);
|
|
let tag = $.spawn("div");
|
|
tag.addClass("tab");
|
|
let header = $.spawn("div");
|
|
header.addClass("tab-header");
|
|
let content = $.spawn("div");
|
|
content.addClass("tab-content");
|
|
let silentContent = $.spawn("div");
|
|
silentContent.addClass("tab-content-invisible");
|
|
/* add some kind of min height */
|
|
const update_height = () => {
|
|
const entries = tag.find("> .tab-content-invisible x-content, > .tab-content x-content");
|
|
console.error(entries);
|
|
let max_height = 0;
|
|
entries.each((_, _e) => {
|
|
const entry = $(_e);
|
|
const height = entry.visible_height();
|
|
if (height > max_height)
|
|
max_height = height;
|
|
});
|
|
console.error("HIGHT: " + max_height);
|
|
entries.each((_, _e) => {
|
|
const entry = $(_e);
|
|
entry.animate({
|
|
'min-height': max_height + "px"
|
|
}, 250);
|
|
});
|
|
};
|
|
template.find("x-entry").each((_, _entry) => {
|
|
const entry = $(_entry);
|
|
let tag_header = $.spawn("div").addClass("entry");
|
|
if (copy)
|
|
tag_header.append(entry.find("x-tag").clone(true, true));
|
|
else
|
|
tag_header.append(entry.find("x-tag"));
|
|
const tag_content = copy ? entry.find("x-content").clone(true, true) : entry.find("x-content");
|
|
content.append(tag_content.hide());
|
|
tag_header.on("click", () => {
|
|
if (tag_header.hasClass("selected"))
|
|
return;
|
|
tag.find(".tab-header .selected").removeClass("selected");
|
|
tag_header.addClass("selected");
|
|
content.find("> x-content").hide();
|
|
/* don't show many nodes at once */
|
|
let entries = tag_content.find(".tab-show-partitional");
|
|
entries.hide();
|
|
const show_next = index => {
|
|
console.log("Show " + index);
|
|
if (index >= entries.length)
|
|
return;
|
|
entries.eq(index).show();
|
|
setTimeout(show_next.bind(undefined, index + 1), 0);
|
|
};
|
|
show_next(0);
|
|
tag_content.trigger('show');
|
|
tag_content.show();
|
|
});
|
|
console.log(this);
|
|
header.append(tag_header);
|
|
});
|
|
setTimeout(() => header.find(".entry").first().trigger("click"), 0);
|
|
tag.append(header);
|
|
tag.append(content);
|
|
tag.append(silentContent);
|
|
tag.on('tab.resize', update_height);
|
|
return tag;
|
|
}
|
|
};
|
|
if (!$.fn.asTabWidget) {
|
|
$.fn.asTabWidget = function (copy) {
|
|
if ($(this).prop("tagName") == "X-TAB")
|
|
return TabFunctions.tabify($(this), typeof (copy) === "boolean" ? copy : true);
|
|
else {
|
|
throw "Invalid tag! " + $(this).prop("tagName");
|
|
}
|
|
};
|
|
}
|
|
if (!$.fn.tabify) {
|
|
$.fn.tabify = function (copy) {
|
|
const wrapped_tag = $.spawn("div").append(this);
|
|
wrapped_tag.find("x-tab").each((_, _element) => {
|
|
const element = $(_element);
|
|
element.replaceWith(element.asTabWidget(copy));
|
|
});
|
|
return wrapped_tag.children();
|
|
};
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["26497305b2d8068b208cb264a896e75dcbd2fc426a0102a57b52777707d986d2"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["26497305b2d8068b208cb264a896e75dcbd2fc426a0102a57b52777707d986d2"] = "26497305b2d8068b208cb264a896e75dcbd2fc426a0102a57b52777707d986d2";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "WVMGeKir", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/profiles/Identity.ts (79,30)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var profiles;
|
|
(function (profiles) {
|
|
var identities;
|
|
(function (identities) {
|
|
let IdentitifyType;
|
|
(function (IdentitifyType) {
|
|
IdentitifyType[IdentitifyType["TEAFORO"] = 0] = "TEAFORO";
|
|
IdentitifyType[IdentitifyType["TEAMSPEAK"] = 1] = "TEAMSPEAK";
|
|
IdentitifyType[IdentitifyType["NICKNAME"] = 2] = "NICKNAME";
|
|
})(IdentitifyType = identities.IdentitifyType || (identities.IdentitifyType = {}));
|
|
function decode_identity(type, data) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
let identity;
|
|
switch (type) {
|
|
case IdentitifyType.NICKNAME:
|
|
identity = new identities.NameIdentity();
|
|
break;
|
|
case IdentitifyType.TEAFORO:
|
|
identity = new identities.TeaForumIdentity(undefined, undefined);
|
|
break;
|
|
case IdentitifyType.TEAMSPEAK:
|
|
identity = new identities.TeaSpeakIdentity(undefined, undefined);
|
|
break;
|
|
}
|
|
if (!identity)
|
|
return undefined;
|
|
try {
|
|
yield identity.decode(data);
|
|
}
|
|
catch (error) {
|
|
/* todo better error handling! */
|
|
console.error(error);
|
|
return undefined;
|
|
}
|
|
return identity;
|
|
});
|
|
}
|
|
identities.decode_identity = decode_identity;
|
|
function create_identity(type) {
|
|
let identity;
|
|
switch (type) {
|
|
case IdentitifyType.NICKNAME:
|
|
identity = new identities.NameIdentity();
|
|
break;
|
|
case IdentitifyType.TEAFORO:
|
|
identity = new identities.TeaForumIdentity(undefined, undefined);
|
|
break;
|
|
case IdentitifyType.TEAMSPEAK:
|
|
identity = new identities.TeaSpeakIdentity(undefined, undefined);
|
|
break;
|
|
}
|
|
return identity;
|
|
}
|
|
identities.create_identity = create_identity;
|
|
class HandshakeCommandHandler extends connection.AbstractCommandHandler {
|
|
constructor(connection, handle) {
|
|
super(connection);
|
|
this.handle = handle;
|
|
}
|
|
handle_command(command) {
|
|
if ($.isFunction(this[command.command]))
|
|
this[command.command](command.arguments);
|
|
else if (command.command == "error") {
|
|
return false;
|
|
}
|
|
else {
|
|
console.warn(_translations.WVMGeKir || (_translations.WVMGeKir = tr("Received unknown command while handshaking (%o)")), command);
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
identities.HandshakeCommandHandler = HandshakeCommandHandler;
|
|
class AbstractHandshakeIdentityHandler {
|
|
constructor(connection) {
|
|
this.callbacks = [];
|
|
this.connection = connection;
|
|
}
|
|
register_callback(callback) {
|
|
this.callbacks.push(callback);
|
|
}
|
|
trigger_success() {
|
|
for (const callback of this.callbacks)
|
|
callback(true);
|
|
}
|
|
trigger_fail(message) {
|
|
for (const callback of this.callbacks)
|
|
callback(false, message);
|
|
}
|
|
}
|
|
identities.AbstractHandshakeIdentityHandler = AbstractHandshakeIdentityHandler;
|
|
})(identities = profiles.identities || (profiles.identities = {}));
|
|
})(profiles || (profiles = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["6e73161c487fad41b7c4c5baf6cc368bdb42dbfc8a59540a353876c15215dff1"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["6e73161c487fad41b7c4c5baf6cc368bdb42dbfc8a59540a353876c15215dff1"] = "6e73161c487fad41b7c4c5baf6cc368bdb42dbfc8a59540a353876c15215dff1";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "KdRLXfeo", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (13,21)" }, { name: "yx_xHhJB", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (39,40)" }, { name: "AbIB7kuK", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (39,54)" }, { name: "pLrbmacb", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (61,46)" }, { name: "H8XKcwqE", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (61,80)" }, { name: "PXQnHjzx", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (74,53)" }, { name: "TNwFGGdq", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (74,119)" }, { name: "LglJTEhF", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (83,46)" }, { name: "n6YP6bgq", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (83,80)" }, { name: "gPFWcPhf", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (127,21)" }, { name: "sGfe77wj", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (165,43)" }, { name: "RTn7ep8V", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (166,39)" }, { name: "qxT8i0h0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (203,21)" }, { name: "iea9bskW", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (235,80)" }, { name: "LAba6sXO", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (237,84)" }, { name: "d9JSFaA1", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (296,39)" }, { name: "mjG6j0ML", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (306,41)" }, { name: "jyqAJeYM", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (382,27)" }, { name: "kb9gRNI1", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (389,39)" }, { name: "bDG4yJ1S", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (400,35)" }, { name: "tL0bCP54", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (402,35)" }, { name: "cUQD3Itt", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (415,33)" }, { name: "fLXoZ44p", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (442,35)" }, { name: "giEinlmS", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (444,35)" }, { name: "_bYpHOYM", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (456,33)" }, { name: "wNBrz45p", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (459,39)" }, { name: "Mj83gjpx", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (513,37)" }, { name: "R_rvWgki", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (620,33)" }, { name: "dVaJRUpW", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (638,43)" }, { name: "GQ7uZCIp", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (661,46)" }, { name: "pvEhAEg0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (661,67)" }, { name: "xTmVYl7B", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (687,36)" }, { name: "t8KEieTl", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (709,46)" }, { name: "oGJHPfbq", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (736,46)" }, { name: "fdSBxddp", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (745,70)" }, { name: "j97itdQy", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (881,41)" }, { name: "uq3SlGtZ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (881,66)" }, { name: "IuhqR8em", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (885,36)" }, { name: "F3qLDw6y", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (885,56)" }, { name: "XNKN8L18", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (896,38)" }, { name: "u6rghx8Y", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (896,55)" }, { name: "aZI_J5tO", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (909,50)" }, { name: "DLdFWwPd", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (909,83)" }, { name: "x8afoFoc", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (921,45)" }, { name: "ynFYOHQs", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (921,70)" }, { name: "mfN6hbkM", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (923,43)" }, { name: "YH0Js1Ll", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (924,46)" }, { name: "ZCXXZ5WL", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (924,81)" }, { name: "tnuGGElr", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (929,36)" }, { name: "GWA7WrRm", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (929,56)" }, { name: "IaVpSbUr", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (1047,34)" }, { name: "DXtYBVnN", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (1047,61)" }, { name: "En9YP_2L", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (1067,32)" }, { name: "tQHWsdmy", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalSettings.ts (1067,53)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../utils/modal.ts" />
|
|
/// <reference path="../../utils/tab.ts" />
|
|
/// <reference path="../../proto.ts" />
|
|
/// <reference path="../../voice/AudioController.ts" />
|
|
/// <reference path="../../profiles/Identity.ts" />
|
|
var Modals;
|
|
(function (Modals) {
|
|
function spawnTeamSpeakIdentityImprove(identity) {
|
|
let modal;
|
|
let elapsed_timer;
|
|
modal = createModal({
|
|
header: _translations.KdRLXfeo || (_translations.KdRLXfeo = tr("Improve identity")),
|
|
body: () => {
|
|
let template = $("#tmpl_settings-teamspeak_improve").renderTag();
|
|
template = $.spawn("div").append(template);
|
|
let active;
|
|
const button_start_stop = template.find(".button-start-stop");
|
|
const button_close = template.find(".button-close");
|
|
const input_current_level = template.find(".identity-level input");
|
|
const input_target_level = template.find(".identity-target-level input");
|
|
const input_threads = template.find(".threads input");
|
|
const input_hash_rate = template.find(".hash-rate input");
|
|
const input_elapsed = template.find(".time-elapsed input");
|
|
button_close.on('click', event => {
|
|
if (active)
|
|
button_start_stop.trigger('click');
|
|
if (modal.shown)
|
|
modal.close();
|
|
});
|
|
button_start_stop.on('click', event => {
|
|
button_start_stop
|
|
.toggleClass('btn-success', active)
|
|
.toggleClass('btn-danger', !active)
|
|
.text(active ? _translations.yx_xHhJB || (_translations.yx_xHhJB = tr("Start")) : _translations.AbIB7kuK || (_translations.AbIB7kuK = tr("Stop")));
|
|
input_threads.prop("disabled", !active);
|
|
input_target_level.prop("disabled", !active);
|
|
if (active) {
|
|
input_hash_rate.val(0);
|
|
clearInterval(elapsed_timer);
|
|
active = false;
|
|
return;
|
|
}
|
|
active = true;
|
|
input_hash_rate.val("nan");
|
|
const threads = parseInt(input_threads.val());
|
|
const target_level = parseInt(input_target_level.val());
|
|
if (target_level == 0) {
|
|
identity.improve_level(-1, threads, () => active, current_level => {
|
|
input_current_level.val(current_level);
|
|
}, hash_rate => {
|
|
input_hash_rate.val(hash_rate);
|
|
}).catch(error => {
|
|
console.error(error);
|
|
createErrorModal(_translations.pLrbmacb || (_translations.pLrbmacb = tr("Failed to improve identity")), (_translations.H8XKcwqE || (_translations.H8XKcwqE = tr("Failed to improve identity.<br>Error:"))) + error).open();
|
|
if (active)
|
|
button_start_stop.trigger('click');
|
|
});
|
|
}
|
|
else {
|
|
identity.improve_level(target_level, threads, () => active, current_level => {
|
|
input_current_level.val(current_level);
|
|
}, hash_rate => {
|
|
input_hash_rate.val(hash_rate);
|
|
}).then(success => {
|
|
if (success) {
|
|
identity.level().then(level => {
|
|
input_current_level.val(level);
|
|
createInfoModal(_translations.PXQnHjzx || (_translations.PXQnHjzx = tr("Identity successfully improved")), MessageHelper.formatMessage(_translations.TNwFGGdq || (_translations.TNwFGGdq = tr("Identity successfully improved to level {}")), level)).open();
|
|
}).catch(error => {
|
|
input_current_level.val("error: " + error);
|
|
});
|
|
}
|
|
if (active)
|
|
button_start_stop.trigger('click');
|
|
}).catch(error => {
|
|
console.error(error);
|
|
createErrorModal(_translations.LglJTEhF || (_translations.LglJTEhF = tr("Failed to improve identity")), (_translations.n6YP6bgq || (_translations.n6YP6bgq = tr("Failed to improve identity.<br>Error:"))) + error).open();
|
|
if (active)
|
|
button_start_stop.trigger('click');
|
|
});
|
|
}
|
|
const begin = Date.now();
|
|
elapsed_timer = setInterval(() => {
|
|
const time = (Date.now() - begin) / 1000;
|
|
let seconds = Math.floor(time % 60).toString();
|
|
let minutes = Math.floor(time / 60).toString();
|
|
if (seconds.length < 2)
|
|
seconds = "0" + seconds;
|
|
if (minutes.length < 2)
|
|
minutes = "0" + minutes;
|
|
input_elapsed.val(minutes + ":" + seconds);
|
|
}, 1000);
|
|
});
|
|
template.find(".identity-unique-id input").val(identity.uid());
|
|
identity.level().then(level => {
|
|
input_current_level.val(level);
|
|
}).catch(error => {
|
|
input_current_level.val("error: " + error);
|
|
});
|
|
return template;
|
|
},
|
|
footer: undefined,
|
|
width: 750
|
|
});
|
|
modal.close_listener.push(() => modal.htmlTag.find(".button-close").trigger('click'));
|
|
modal.open();
|
|
return modal;
|
|
}
|
|
function spawnTeamSpeakIdentityImport(callback) {
|
|
let modal;
|
|
let loaded_identity;
|
|
modal = createModal({
|
|
header: _translations.gPFWcPhf || (_translations.gPFWcPhf = tr("Import identity")),
|
|
body: () => {
|
|
let template = $("#tmpl_settings-teamspeak_import").renderTag();
|
|
template = $.spawn("div").append(template);
|
|
template.find(".button-load-file").on('click', event => template.find(".input-file").trigger('click'));
|
|
const button_import = template.find(".button-import");
|
|
const set_error = message => {
|
|
template.find(".success").hide();
|
|
if (message) {
|
|
template.find(".error").text(message).show();
|
|
button_import.prop("disabled", true);
|
|
}
|
|
else
|
|
template.find(".error").hide();
|
|
};
|
|
const import_identity = (data, ini) => {
|
|
profiles.identities.TeaSpeakIdentity.import_ts(data, ini).then(identity => {
|
|
loaded_identity = identity;
|
|
set_error("");
|
|
button_import.prop("disabled", false);
|
|
template.find(".success").show();
|
|
}).catch(error => {
|
|
set_error("Failed to load identity: " + error);
|
|
});
|
|
};
|
|
{ /* file select button */
|
|
template.find(".input-file").on('change', event => {
|
|
const element = event.target;
|
|
const file_reader = new FileReader();
|
|
file_reader.onload = function () {
|
|
import_identity(file_reader.result, true);
|
|
};
|
|
file_reader.onerror = ev => {
|
|
console.error(_translations.sGfe77wj || (_translations.sGfe77wj = tr("Failed to read give identity file: %o")), ev);
|
|
set_error(_translations.RTn7ep8V || (_translations.RTn7ep8V = tr("Failed to read file!")));
|
|
return;
|
|
};
|
|
if (element.files && element.files.length > 0)
|
|
file_reader.readAsText(element.files[0]);
|
|
});
|
|
}
|
|
{ /* text input */
|
|
template.find(".button-load-text").on('click', event => {
|
|
createInputModal("Import identity from text", "Please paste your idenity bellow<br>", text => text.length > 0 && text.indexOf('V') != -1, result => {
|
|
if (result)
|
|
import_identity(result, false);
|
|
}).open();
|
|
});
|
|
}
|
|
button_import.on('click', event => {
|
|
modal.close();
|
|
callback(loaded_identity);
|
|
});
|
|
set_error("");
|
|
button_import.prop("disabled", true);
|
|
return template;
|
|
},
|
|
footer: undefined,
|
|
width: 750
|
|
});
|
|
modal.open();
|
|
return modal;
|
|
}
|
|
function spawnSettingsModal() {
|
|
let modal;
|
|
modal = createModal({
|
|
header: _translations.qxT8i0h0 || (_translations.qxT8i0h0 = tr("Settings")),
|
|
body: () => {
|
|
let template = $("#tmpl_settings").renderTag({
|
|
client: native_client,
|
|
valid_forum_identity: profiles.identities.valid_static_forum_identity(),
|
|
forum_path: settings.static("forum_path"),
|
|
});
|
|
initialiseVoiceListeners(modal, (template = template.tabify()).find(".settings_audio"));
|
|
initialise_translations(template.find(".settings-translations"));
|
|
initialise_profiles(modal, template.find(".settings-profiles"));
|
|
initialise_global(modal, template.find(".settings-general"));
|
|
return template;
|
|
},
|
|
footer: undefined,
|
|
width: 750
|
|
});
|
|
modal.open();
|
|
return modal;
|
|
}
|
|
Modals.spawnSettingsModal = spawnSettingsModal;
|
|
function initialise_global(modal, tag) {
|
|
console.log(tag);
|
|
{ /* setup the forum */
|
|
const identity = profiles.identities.static_forum_identity();
|
|
if (identity && identity.valid()) {
|
|
tag.find(".not-connected").hide();
|
|
tag.find(".property.username .value").text(identity.name());
|
|
const premium_tag = tag.find(".property.premium .value").text("");
|
|
if (identity.is_stuff() || identity.is_premium())
|
|
premium_tag.append($.spawn("div").addClass("premium").text(_translations.iea9bskW || (_translations.iea9bskW = tr("yes"))));
|
|
else
|
|
premium_tag.append($.spawn("div").addClass("non-premium").text(_translations.LAba6sXO || (_translations.LAba6sXO = tr("no"))));
|
|
}
|
|
else {
|
|
tag.find(".connected").hide();
|
|
}
|
|
tag.find(".button-logout").on('click', event => {
|
|
window.location.href = settings.static("forum_path") + "auth.php?type=logout";
|
|
});
|
|
tag.find(".button-login").on('click', event => {
|
|
window.location.href = settings.static("forum_path") + "login.php";
|
|
});
|
|
}
|
|
}
|
|
function initialiseVoiceListeners(modal, tag) {
|
|
let currentVAD = settings.global("vad_type", "vad");
|
|
{ //Initialized voice activation detection
|
|
const vad_tag = tag.find(".settings-vad-container");
|
|
vad_tag.find('input[type=radio]').on('change', event => {
|
|
const select = event.currentTarget;
|
|
{
|
|
vad_tag.find(".settings-vad-impl-entry").hide();
|
|
vad_tag.find(".setting-vad-" + select.value).show();
|
|
}
|
|
{
|
|
settings.changeGlobal("vad_type", select.value);
|
|
globalClient.voiceConnection.voiceRecorder.reinitialiseVAD();
|
|
}
|
|
switch (select.value) {
|
|
case "ppt":
|
|
let ppt_settings = settings.global('vad_ppt_settings', undefined);
|
|
ppt_settings = ppt_settings ? JSON.parse(ppt_settings) : {};
|
|
vad_tag.find(".vat_ppt_key").text(ppt.key_description(ppt_settings));
|
|
vad_tag.find(".ppt-delay input").val(ppt_settings.delay === undefined ? 300 : ppt_settings.delay);
|
|
break;
|
|
case "vad":
|
|
let slider = vad_tag.find(".vad_vad_slider");
|
|
let vad = globalClient.voiceConnection.voiceRecorder.getVADHandler();
|
|
slider.val(vad.percentageThreshold);
|
|
slider.trigger("change");
|
|
globalClient.voiceConnection.voiceRecorder.update(true);
|
|
vad.percentage_listener = per => {
|
|
vad_tag.find(".vad_vad_bar_filler")
|
|
.css("width", (100 - per) + "%");
|
|
};
|
|
break;
|
|
}
|
|
});
|
|
{ //Initialized push to talk
|
|
vad_tag.find(".vat_ppt_key").click(function () {
|
|
let modal = createModal({
|
|
body: "",
|
|
header: () => {
|
|
let head = $.spawn("div");
|
|
head.text(_translations.d9JSFaA1 || (_translations.d9JSFaA1 = tr("Type the key you wish")));
|
|
head.css("background-color", "blue");
|
|
return head;
|
|
},
|
|
footer: ""
|
|
});
|
|
let listener = (event) => {
|
|
if (event.type == ppt.EventType.KEY_TYPED) {
|
|
settings.changeGlobal('vad_ppt_key', undefined); //TODO remove that because its legacy shit
|
|
console.log(_translations.mjG6j0ML || (_translations.mjG6j0ML = tr("Got key %o")), event);
|
|
let ppt_settings = settings.global('vad_ppt_settings', undefined);
|
|
ppt_settings = ppt_settings ? JSON.parse(ppt_settings) : {};
|
|
Object.assign(ppt_settings, event);
|
|
settings.changeGlobal('vad_ppt_settings', ppt_settings);
|
|
globalClient.voiceConnection.voiceRecorder.reinitialiseVAD();
|
|
ppt.unregister_key_listener(listener);
|
|
modal.close();
|
|
vad_tag.find(".vat_ppt_key").text(ppt.key_description(event));
|
|
}
|
|
};
|
|
ppt.register_key_listener(listener);
|
|
modal.open();
|
|
});
|
|
vad_tag.find(".ppt-delay input").on('change', event => {
|
|
let ppt_settings = settings.global('vad_ppt_settings', undefined);
|
|
ppt_settings = ppt_settings ? JSON.parse(ppt_settings) : {};
|
|
ppt_settings.delay = event.target.valueAsNumber;
|
|
settings.changeGlobal('vad_ppt_settings', ppt_settings);
|
|
globalClient.voiceConnection.voiceRecorder.reinitialiseVAD();
|
|
});
|
|
}
|
|
{ //Initialized voice activation detection
|
|
let slider = vad_tag.find(".vad_vad_slider");
|
|
slider.on("input change", () => {
|
|
settings.changeGlobal("vad_threshold", slider.val().toString());
|
|
let vad = globalClient.voiceConnection.voiceRecorder.getVADHandler();
|
|
if (vad instanceof VoiceActivityDetectorVAD)
|
|
vad.percentageThreshold = slider.val();
|
|
vad_tag.find(".vad_vad_slider_value").text(slider.val().toString());
|
|
});
|
|
modal.properties.registerCloseListener(() => {
|
|
let vad = globalClient.voiceConnection.voiceRecorder.getVADHandler();
|
|
if (vad instanceof VoiceActivityDetectorVAD)
|
|
vad.percentage_listener = undefined;
|
|
});
|
|
}
|
|
let target_tag = vad_tag.find('input[type=radio][name="vad_type"][value="' + currentVAD + '"]');
|
|
if (target_tag.length == 0) {
|
|
//TODO tr
|
|
console.warn("Failed to find tag for " + currentVAD + ". Using latest tag!");
|
|
target_tag = vad_tag.find('input[type=radio][name="vad_type"]').last();
|
|
}
|
|
target_tag.prop("checked", true);
|
|
setTimeout(() => target_tag.trigger('change'), 0);
|
|
}
|
|
const display_error = (message) => {
|
|
const alert = tag.find(".settings-device-error").first();
|
|
alert.clone()
|
|
.alert()
|
|
.css("display", "block")
|
|
.insertAfter(alert)
|
|
.find(".message")
|
|
.text(message);
|
|
};
|
|
{ //Initialize microphone
|
|
const setting_tag = tag.find(".settings-microphone");
|
|
const tag_select = setting_tag.find(".audio-select-microphone");
|
|
const update_devices = () => {
|
|
tag_select.empty();
|
|
$.spawn("option")
|
|
.attr("device-id", "")
|
|
.attr("device-group", "")
|
|
.text(_translations.jyqAJeYM || (_translations.jyqAJeYM = tr("No device")))
|
|
.appendTo(tag_select);
|
|
navigator.mediaDevices.enumerateDevices().then(devices => {
|
|
const active_device = globalClient.voiceConnection.voiceRecorder.device_id();
|
|
for (const device of devices) {
|
|
console.debug(_translations.kb9gRNI1 || (_translations.kb9gRNI1 = tr("Got device %s (%s): %s (%o)")), device.deviceId, device.kind, device.label);
|
|
if (device.kind !== 'audioinput')
|
|
continue;
|
|
$.spawn("option")
|
|
.attr("device-id", device.deviceId)
|
|
.attr("device-group", device.groupId)
|
|
.text(device.label)
|
|
.prop("selected", device.deviceId == active_device)
|
|
.appendTo(tag_select);
|
|
}
|
|
}).catch(error => {
|
|
console.error(_translations.bDG4yJ1S || (_translations.bDG4yJ1S = tr("Could not enumerate over devices!")));
|
|
console.error(error);
|
|
display_error(_translations.tL0bCP54 || (_translations.tL0bCP54 = tr("Could not get microphone device list!")));
|
|
});
|
|
if (tag_select.find("option:selected").length == 0)
|
|
tag_select.find("option").prop("selected", true);
|
|
};
|
|
{
|
|
tag_select.on('change', event => {
|
|
let selected_tag = tag_select.find("option:selected");
|
|
let deviceId = selected_tag.attr("device-id");
|
|
let groupId = selected_tag.attr("device-group");
|
|
console.log(_translations.cUQD3Itt || (_translations.cUQD3Itt = tr("Selected microphone device: id: %o group: %o")), deviceId, groupId);
|
|
globalClient.voiceConnection.voiceRecorder.change_device(deviceId, groupId);
|
|
});
|
|
}
|
|
update_devices();
|
|
setting_tag.find(".button-device-update").on('click', event => update_devices());
|
|
}
|
|
{ //Initialize speaker
|
|
const setting_tag = tag.find(".settings-speaker");
|
|
const tag_select = setting_tag.find(".audio-select-speaker");
|
|
const update_devices = () => {
|
|
tag_select.empty();
|
|
const active_device = audio.player.current_device();
|
|
audio.player.available_devices().then(devices => {
|
|
for (const device of devices) {
|
|
$.spawn("option")
|
|
.attr("device-id", device.device_id)
|
|
.text(device.name)
|
|
.prop("selected", device.device_id == active_device.device_id)
|
|
.appendTo(tag_select);
|
|
}
|
|
}).catch(error => {
|
|
console.error(_translations.fLXoZ44p || (_translations.fLXoZ44p = tr("Could not enumerate over devices!")));
|
|
console.error(error);
|
|
display_error(_translations.giEinlmS || (_translations.giEinlmS = tr("Could not get speaker device list!")));
|
|
});
|
|
if (tag_select.find("option:selected").length == 0)
|
|
tag_select.find("option").prop("selected", true);
|
|
};
|
|
{
|
|
tag_select.on('change', event => {
|
|
let selected_tag = tag_select.find("option:selected");
|
|
let deviceId = selected_tag.attr("device-id");
|
|
console.log(_translations._bYpHOYM || (_translations._bYpHOYM = tr("Selected speaker device: id: %o")), deviceId);
|
|
audio.player.set_device(deviceId).catch(error => {
|
|
console.error(error);
|
|
display_error(_translations.wNBrz45p || (_translations.wNBrz45p = tr("Failed to change device!")));
|
|
});
|
|
});
|
|
}
|
|
update_devices();
|
|
setting_tag.find(".button-device-update").on('click', event => update_devices());
|
|
}
|
|
{ /* initialize sounds */
|
|
const sound_tag = tag.find(".sound-settings");
|
|
{ /* master volume */
|
|
const master_tag = sound_tag.find(".master-volume");
|
|
master_tag.find("input").on('change input', event => {
|
|
const value = parseInt(event.target.value);
|
|
master_tag.find('a').text("(" + value + "%)");
|
|
sound.set_master_volume(value / 100);
|
|
}).val((sound.get_master_volume() * 100).toString()).trigger('change');
|
|
}
|
|
{
|
|
const overlap_tag = sound_tag.find(".overlap-sounds input");
|
|
overlap_tag.on('change', event => {
|
|
const activated = event.target.checked;
|
|
sound.set_overlap_activated(activated);
|
|
}).prop("checked", sound.overlap_activated());
|
|
}
|
|
{
|
|
const muted_tag = sound_tag.find(".muted-sounds input");
|
|
muted_tag.on('change', event => {
|
|
const activated = event.target.checked;
|
|
sound.set_ignore_output_muted(!activated);
|
|
}).prop("checked", !sound.ignore_output_muted());
|
|
}
|
|
{ /* sound elements */
|
|
const template_tag = $("#tmpl_settings-sound_entry");
|
|
const entry_tag = sound_tag.find(".sound-list-entries");
|
|
for (const _sound in Sound) {
|
|
const sound_name = Sound[_sound];
|
|
console.log(sound.get_sound_volume(sound_name));
|
|
const data = {
|
|
name: sound_name,
|
|
activated: sound.get_sound_volume(sound_name) > 0
|
|
};
|
|
const entry = template_tag.renderTag(data);
|
|
entry.find("input").on('change', event => {
|
|
const activated = event.target.checked;
|
|
console.log(_translations.Mj83gjpx || (_translations.Mj83gjpx = tr("Sound %s had changed to %o")), sound_name, activated);
|
|
sound.set_sound_volume(sound_name, activated ? 1 : 0);
|
|
});
|
|
entry.find(".button-playback").on('click', event => {
|
|
sound.play(sound_name);
|
|
});
|
|
entry_tag.append(entry);
|
|
}
|
|
setTimeout(() => {
|
|
const entry_container = sound_tag.find(".sound-list-entries-container");
|
|
if (entry_container.hasScrollBar())
|
|
entry_container.addClass("scrollbar");
|
|
}, 100);
|
|
/* filter */
|
|
const filter_tag = sound_tag.find(".sound-list-filter input");
|
|
filter_tag.on('change keyup', event => {
|
|
const filter = (event.target.value || "").toLowerCase();
|
|
if (!filter)
|
|
entry_tag.find(".entry").show();
|
|
else {
|
|
entry_tag.find(".entry").each((_, _entry) => {
|
|
const entry = $(_entry);
|
|
if (entry.text().toLowerCase().indexOf(filter) == -1)
|
|
entry.hide();
|
|
else
|
|
entry.show();
|
|
});
|
|
}
|
|
});
|
|
}
|
|
modal.close_listener.push(sound.save);
|
|
}
|
|
//Initialise microphones
|
|
/*
|
|
let select_microphone = tag.find(".voice_microphone_select");
|
|
let select_error = tag.find(".voice_microphone_select_error");
|
|
|
|
navigator.mediaDevices.enumerateDevices().then(devices => {
|
|
let recoder = globalClient.voiceConnection.voiceRecorder;
|
|
|
|
console.log("Got " + devices.length + " devices:");
|
|
for(let device of devices) {
|
|
console.log(" - Type: %s Name %s ID: %s Group: %s", device.kind, device.label, device.deviceId, device.groupId);
|
|
if(device.kind == "audioinput") {
|
|
let dtag = $.spawn("option");
|
|
dtag.attr("device-id", device.deviceId);
|
|
dtag.attr("device-group", device.groupId);
|
|
dtag.text(device.label);
|
|
select_microphone.append(dtag);
|
|
|
|
if(recoder) dtag.prop("selected", device.deviceId == recoder.device_id());
|
|
}
|
|
}
|
|
}).catch(error => {
|
|
console.error("Could not enumerate over devices!");
|
|
console.error(error);
|
|
select_error.text("Could not get device list!").show();
|
|
});
|
|
|
|
select_microphone.change(event => {
|
|
let deviceSelected = select_microphone.find("option:selected");
|
|
let deviceId = deviceSelected.attr("device-id");
|
|
let groupId = deviceSelected.attr("device-group");
|
|
console.log("Selected microphone device: id: %o group: %o", deviceId, groupId);
|
|
globalClient.voiceConnection.voiceRecorder.change_device(deviceId, groupId);
|
|
});
|
|
*/
|
|
//Initialise speakers
|
|
}
|
|
function initialise_translations(tag) {
|
|
{ //Initialize the list
|
|
const tag_list = tag.find(".setting-list .list");
|
|
const tag_loading = tag.find(".setting-list .loading");
|
|
const template = $("#settings-translations-list-entry");
|
|
const restart_hint = tag.find(".setting-list .restart-note");
|
|
restart_hint.hide();
|
|
const update_list = () => {
|
|
tag_list.empty();
|
|
const currently_selected = i18n.config.translation_config().current_translation_url;
|
|
{ //Default translation
|
|
const tag = template.renderTag({
|
|
type: "default",
|
|
selected: !currently_selected || currently_selected == "default"
|
|
});
|
|
tag.on('click', () => {
|
|
i18n.select_translation(undefined, undefined);
|
|
tag_list.find(".selected").removeClass("selected");
|
|
tag.addClass("selected");
|
|
restart_hint.show();
|
|
});
|
|
tag.appendTo(tag_list);
|
|
}
|
|
{
|
|
const display_repository_info = (repository) => {
|
|
const info_modal = createModal({
|
|
header: _translations.R_rvWgki || (_translations.R_rvWgki = tr("Repository info")),
|
|
body: () => {
|
|
return $("#settings-translations-list-entry-info").renderTag({
|
|
type: "repository",
|
|
name: repository.name,
|
|
url: repository.url,
|
|
contact: repository.contact,
|
|
translations: repository.translations || []
|
|
});
|
|
},
|
|
footer: () => {
|
|
let footer = $.spawn("div");
|
|
footer.addClass("modal-button-group");
|
|
footer.css("margin-top", "5px");
|
|
footer.css("margin-bottom", "5px");
|
|
footer.css("text-align", "right");
|
|
let buttonOk = $.spawn("button");
|
|
buttonOk.text(_translations.dVaJRUpW || (_translations.dVaJRUpW = tr("Close")));
|
|
buttonOk.click(() => info_modal.close());
|
|
footer.append(buttonOk);
|
|
return footer;
|
|
}
|
|
});
|
|
info_modal.open();
|
|
};
|
|
tag_loading.show();
|
|
i18n.iterate_translations((repo, entry) => {
|
|
let repo_tag = tag_list.find("[repository=\"" + repo.unique_id + "\"]");
|
|
if (repo_tag.length == 0) {
|
|
repo_tag = template.renderTag({
|
|
type: "repository",
|
|
name: repo.name || repo.url,
|
|
id: repo.unique_id
|
|
});
|
|
repo_tag.find(".button-delete").on('click', e => {
|
|
e.preventDefault();
|
|
Modals.spawnYesNo(_translations.GQ7uZCIp || (_translations.GQ7uZCIp = tr("Are you sure?")), _translations.pvEhAEg0 || (_translations.pvEhAEg0 = tr("Do you really want to delete this repository?")), answer => {
|
|
if (answer) {
|
|
i18n.delete_repository(repo);
|
|
update_list();
|
|
}
|
|
});
|
|
});
|
|
repo_tag.find(".button-info").on('click', e => {
|
|
e.preventDefault();
|
|
display_repository_info(repo);
|
|
});
|
|
tag_list.append(repo_tag);
|
|
}
|
|
const tag = template.renderTag({
|
|
type: "translation",
|
|
name: entry.info.name || entry.url,
|
|
id: repo.unique_id,
|
|
selected: i18n.config.translation_config().current_translation_url == entry.url
|
|
});
|
|
tag.find(".button-info").on('click', e => {
|
|
e.preventDefault();
|
|
const info_modal = createModal({
|
|
header: _translations.xTmVYl7B || (_translations.xTmVYl7B = tr("Translation info")),
|
|
body: () => {
|
|
const tag = $("#settings-translations-list-entry-info").renderTag({
|
|
type: "translation",
|
|
name: entry.info.name,
|
|
url: entry.url,
|
|
repository_name: repo.name,
|
|
contributors: entry.info.contributors || []
|
|
});
|
|
tag.find(".button-info").on('click', () => display_repository_info(repo));
|
|
return tag;
|
|
},
|
|
footer: () => {
|
|
let footer = $.spawn("div");
|
|
footer.addClass("modal-button-group");
|
|
footer.css("margin-top", "5px");
|
|
footer.css("margin-bottom", "5px");
|
|
footer.css("text-align", "right");
|
|
let buttonOk = $.spawn("button");
|
|
buttonOk.text(_translations.t8KEieTl || (_translations.t8KEieTl = tr("Close")));
|
|
buttonOk.click(() => info_modal.close());
|
|
footer.append(buttonOk);
|
|
return footer;
|
|
}
|
|
});
|
|
info_modal.open();
|
|
});
|
|
tag.on('click', e => {
|
|
if (e.isDefaultPrevented())
|
|
return;
|
|
i18n.select_translation(repo, entry);
|
|
tag_list.find(".selected").removeClass("selected");
|
|
tag.addClass("selected");
|
|
restart_hint.show();
|
|
});
|
|
tag.insertAfter(repo_tag);
|
|
}, () => {
|
|
tag_loading.hide();
|
|
});
|
|
}
|
|
};
|
|
{
|
|
tag.find(".button-add-repository").on('click', () => {
|
|
createInputModal("Enter URL", _translations.oGJHPfbq || (_translations.oGJHPfbq = tr("Enter repository URL:<br>")), text => true, url => {
|
|
if (!url)
|
|
return;
|
|
tag_loading.show();
|
|
i18n.load_repository(url).then(repository => {
|
|
i18n.register_repository(repository);
|
|
update_list();
|
|
}).catch(error => {
|
|
tag_loading.hide();
|
|
createErrorModal("Failed to load repository", (_translations.fdSBxddp || (_translations.fdSBxddp = tr("Failed to query repository.<br>Ensure that this repository is valid and reachable.<br>Error: "))) + error).open();
|
|
});
|
|
}).open();
|
|
});
|
|
}
|
|
restart_hint.find(".button-reload").on('click', () => {
|
|
location.reload();
|
|
});
|
|
update_list();
|
|
}
|
|
}
|
|
function initialise_profiles(modal, tag) {
|
|
const settings_tag = tag.find(".profile-settings");
|
|
let selected_profile;
|
|
let nickname_listener;
|
|
let status_listener;
|
|
const display_settings = (profile) => {
|
|
selected_profile = profile;
|
|
settings_tag.find(".setting-name").val(profile.profile_name);
|
|
settings_tag.find(".setting-default-nickname").val(profile.default_username);
|
|
settings_tag.find(".setting-default-password").val(profile.default_password);
|
|
{
|
|
//change listener
|
|
const select_tag = settings_tag.find(".select-container select")[0];
|
|
const type = profile.selected_identity_type.toLowerCase();
|
|
select_tag.onchange = () => {
|
|
console.log("Selected: " + select_tag.value);
|
|
settings_tag.find(".identity-settings.active").removeClass("active");
|
|
settings_tag.find(".identity-settings-" + select_tag.value).addClass("active");
|
|
profile.selected_identity_type = select_tag.value.toLowerCase();
|
|
const selected_type = profile.selected_type();
|
|
const identity = profile.selected_identity();
|
|
profiles.mark_need_save();
|
|
let tag;
|
|
if (selected_type == profiles.identities.IdentitifyType.TEAFORO) {
|
|
const forum_tag = tag = settings_tag.find(".identity-settings-teaforo");
|
|
forum_tag.find(".connected, .disconnected").hide();
|
|
if (identity && identity.valid()) {
|
|
forum_tag.find(".connected").show();
|
|
}
|
|
else {
|
|
forum_tag.find(".disconnected").show();
|
|
}
|
|
}
|
|
else if (selected_type == profiles.identities.IdentitifyType.TEAMSPEAK) {
|
|
console.log("Set: " + identity);
|
|
const teamspeak_tag = tag = settings_tag.find(".identity-settings-teamspeak");
|
|
teamspeak_tag.find(".identity_string").val("");
|
|
if (identity)
|
|
identity.export_ts().then(e => teamspeak_tag.find(".identity_string").val(e));
|
|
}
|
|
else if (selected_type == profiles.identities.IdentitifyType.NICKNAME) {
|
|
const name_tag = tag = settings_tag.find(".identity-settings-nickname");
|
|
if (identity)
|
|
name_tag.find("input").val(identity.name());
|
|
else
|
|
name_tag.find("input").val("");
|
|
}
|
|
if (tag)
|
|
tag.trigger('show');
|
|
};
|
|
select_tag.value = type;
|
|
select_tag.onchange(undefined);
|
|
}
|
|
};
|
|
const update_profile_list = () => {
|
|
const profile_list = tag.find(".profile-list .list").empty();
|
|
const profile_template = $("#settings-profile-list-entry");
|
|
for (const profile of profiles.profiles()) {
|
|
const list_tag = profile_template.renderTag({
|
|
profile_name: profile.profile_name,
|
|
id: profile.id
|
|
});
|
|
const profile_status_update = () => {
|
|
list_tag.find(".status").hide();
|
|
if (profile.valid())
|
|
list_tag.find(".status-valid").show();
|
|
else
|
|
list_tag.find(".status-invalid").show();
|
|
};
|
|
list_tag.on('click', event => {
|
|
/* update ui */
|
|
profile_list.find(".selected").removeClass("selected");
|
|
list_tag.addClass("selected");
|
|
if (profile == selected_profile)
|
|
return;
|
|
nickname_listener = () => list_tag.find(".name").text(profile.profile_name);
|
|
status_listener = profile_status_update;
|
|
display_settings(profile);
|
|
});
|
|
profile_list.append(list_tag);
|
|
if ((!selected_profile && profile.id == "default") || selected_profile == profile)
|
|
setTimeout(() => list_tag.trigger('click'), 1);
|
|
profile_status_update();
|
|
}
|
|
};
|
|
const display_error = (error) => {
|
|
if (error) {
|
|
settings_tag.find(".settings-profile-error").show().find(".message").html(error);
|
|
}
|
|
else
|
|
settings_tag.find(".settings-profile-error").hide();
|
|
status_listener();
|
|
};
|
|
/* identity settings */
|
|
{
|
|
{ //TeamSpeak change listener
|
|
const teamspeak_tag = settings_tag.find(".identity-settings-teamspeak");
|
|
const identity_info_tag = teamspeak_tag.find(".identity-info");
|
|
const button_export = teamspeak_tag.find(".button-export");
|
|
const button_import = teamspeak_tag.find(".button-import");
|
|
const button_generate = teamspeak_tag.find(".button-generate");
|
|
const button_improve = teamspeak_tag.find(".button-improve");
|
|
button_import.on('click', event => {
|
|
const profile = selected_profile.selected_identity(profiles.identities.IdentitifyType.TEAMSPEAK);
|
|
const set_identity = (identity) => {
|
|
selected_profile.set_identity(profiles.identities.IdentitifyType.TEAMSPEAK, identity);
|
|
teamspeak_tag.trigger('show');
|
|
createInfoModal(_translations.j97itdQy || (_translations.j97itdQy = tr("Identity imported")), _translations.uq3SlGtZ || (_translations.uq3SlGtZ = tr("Your identity has been successfully imported!"))).open();
|
|
};
|
|
if (profile && profile.valid()) {
|
|
Modals.spawnYesNo(_translations.IuhqR8em || (_translations.IuhqR8em = tr("Are you sure")), _translations.F3qLDw6y || (_translations.F3qLDw6y = tr("Do you really want to import a new identity and override the old identity?")), result => {
|
|
if (result)
|
|
spawnTeamSpeakIdentityImport(set_identity);
|
|
});
|
|
}
|
|
else
|
|
spawnTeamSpeakIdentityImport(set_identity);
|
|
});
|
|
button_export.on('click', event => {
|
|
const profile = selected_profile.selected_identity(profiles.identities.IdentitifyType.TEAMSPEAK);
|
|
if (!profile)
|
|
return;
|
|
createInputModal(_translations.XNKN8L18 || (_translations.XNKN8L18 = tr("File name")), _translations.u6rghx8Y || (_translations.u6rghx8Y = tr("Please enter the file name")), text => !!text, name => {
|
|
if (name) {
|
|
profile.export_ts(true).then(data => {
|
|
const element = $.spawn("a")
|
|
.text("donwload")
|
|
.attr("href", "data:test/plain;charset=utf-8," + encodeURIComponent(data))
|
|
.attr("download", name + ".ini")
|
|
.css("display", "none")
|
|
.appendTo($("body"));
|
|
element[0].click();
|
|
element.detach();
|
|
}).catch(error => {
|
|
console.error(error);
|
|
createErrorModal(_translations.aZI_J5tO || (_translations.aZI_J5tO = tr("Failed to export identity")), (_translations.DLdFWwPd || (_translations.DLdFWwPd = tr("Failed to export and save identity.<br>Error: "))) + error).open();
|
|
});
|
|
}
|
|
}).open();
|
|
});
|
|
button_generate.on('click', event => {
|
|
const profile = selected_profile.selected_identity(profiles.identities.IdentitifyType.TEAMSPEAK);
|
|
const generate_identity = () => {
|
|
profiles.identities.TeaSpeakIdentity.generate_new().then(identity => {
|
|
selected_profile.set_identity(profiles.identities.IdentitifyType.TEAMSPEAK, identity);
|
|
teamspeak_tag.trigger('show');
|
|
createInfoModal(_translations.x8afoFoc || (_translations.x8afoFoc = tr("Identity generate")), _translations.ynFYOHQs || (_translations.ynFYOHQs = tr("A new identity had been successfully generated"))).open();
|
|
}).catch(error => {
|
|
console.error(_translations.mfN6hbkM || (_translations.mfN6hbkM = tr("Failed to generate a new identity. Error object: %o")), error);
|
|
createErrorModal(_translations.YH0Js1Ll || (_translations.YH0Js1Ll = tr("Failed to generate identity")), (_translations.ZCXXZ5WL || (_translations.ZCXXZ5WL = tr("Failed to generate a new identity.<br>Error:"))) + error).open();
|
|
});
|
|
};
|
|
if (profile && profile.valid()) {
|
|
Modals.spawnYesNo(_translations.tnuGGElr || (_translations.tnuGGElr = tr("Are you sure")), _translations.GWA7WrRm || (_translations.GWA7WrRm = tr("Do you really want to generate a new identity and override the old identity?")), result => {
|
|
if (result)
|
|
generate_identity();
|
|
});
|
|
}
|
|
else
|
|
generate_identity();
|
|
});
|
|
button_improve.on('click', event => {
|
|
const profile = selected_profile.selected_identity(profiles.identities.IdentitifyType.TEAMSPEAK);
|
|
if (!profile)
|
|
return;
|
|
spawnTeamSpeakIdentityImprove(profile).close_listener.push(() => teamspeak_tag.trigger('show'));
|
|
});
|
|
/* updates the data */
|
|
teamspeak_tag.on('show', event => {
|
|
const profile = selected_profile.selected_identity(profiles.identities.IdentitifyType.TEAMSPEAK);
|
|
if (!profile || !profile.valid()) {
|
|
identity_info_tag.hide();
|
|
teamspeak_tag.find(".identity-undefined").show();
|
|
button_export.prop("disabled", true);
|
|
}
|
|
else {
|
|
identity_info_tag.show();
|
|
teamspeak_tag.find(".identity-undefined").hide();
|
|
button_export.prop("disabled", false);
|
|
identity_info_tag.find(".unique-id input").val(profile.uid());
|
|
const input_level = identity_info_tag.find(".level input").val("loading...");
|
|
profile.level().then(level => input_level.val(level.toString())).catch(error => input_level.val("error: " + error));
|
|
}
|
|
display_error();
|
|
});
|
|
}
|
|
{ //The forum
|
|
const teaforo_tag = settings_tag.find(".identity-settings-teaforo");
|
|
if (native_client) {
|
|
teaforo_tag.find(".native-teaforo-login").on('click', event => {
|
|
setTimeout(() => {
|
|
const forum = require("teaforo.js");
|
|
const call = () => {
|
|
if (modal.shown) {
|
|
display_settings(selected_profile);
|
|
status_listener();
|
|
}
|
|
};
|
|
forum.register_callback(call);
|
|
forum.open();
|
|
}, 0);
|
|
});
|
|
}
|
|
teaforo_tag.on('show', event => {
|
|
display_error(); /* clear error */
|
|
});
|
|
}
|
|
{ //The name
|
|
const name_tag = settings_tag.find(".identity-settings-nickname");
|
|
name_tag.find(".setting-name").on('change keyup', event => {
|
|
const name = name_tag.find(".setting-name").val();
|
|
selected_profile.set_identity(profiles.identities.IdentitifyType.NICKNAME, new profiles.identities.NameIdentity(name));
|
|
profiles.mark_need_save();
|
|
if (name.length < 3) {
|
|
display_error("Name must be at least 3 characters long!");
|
|
return;
|
|
}
|
|
display_error();
|
|
});
|
|
name_tag.on('show', event => {
|
|
const profile = selected_profile.selected_identity(profiles.identities.IdentitifyType.NICKNAME);
|
|
if (!profile)
|
|
display_error("invalid profile");
|
|
else if (!profile.valid())
|
|
display_error("Name must be at least 3 characters long!");
|
|
else
|
|
display_error();
|
|
});
|
|
}
|
|
}
|
|
/* general settings */
|
|
{
|
|
settings_tag.find(".setting-name").on('change', event => {
|
|
const value = settings_tag.find(".setting-name").val();
|
|
if (value && selected_profile) {
|
|
selected_profile.profile_name = value;
|
|
if (nickname_listener)
|
|
nickname_listener();
|
|
profiles.mark_need_save();
|
|
status_listener();
|
|
}
|
|
});
|
|
settings_tag.find(".setting-default-nickname").on('change', event => {
|
|
const value = settings_tag.find(".setting-default-nickname").val();
|
|
if (value && selected_profile) {
|
|
selected_profile.default_username = value;
|
|
profiles.mark_need_save();
|
|
status_listener();
|
|
}
|
|
});
|
|
settings_tag.find(".setting-default-password").on('change', event => {
|
|
const value = settings_tag.find(".setting-default-password").val();
|
|
if (value && selected_profile) {
|
|
selected_profile.default_username = value;
|
|
profiles.mark_need_save();
|
|
status_listener();
|
|
}
|
|
});
|
|
}
|
|
/* general buttons */
|
|
{
|
|
tag.find(".button-add-profile").on('click', event => {
|
|
createInputModal(_translations.IaVpSbUr || (_translations.IaVpSbUr = tr("Please enter a name")), _translations.DXtYBVnN || (_translations.DXtYBVnN = tr("Please enter a name for the new profile:<br>")), text => text.length > 0 && !profiles.find_profile_by_name(text), value => {
|
|
if (value) {
|
|
display_settings(profiles.create_new_profile(value));
|
|
update_profile_list();
|
|
profiles.mark_need_save();
|
|
}
|
|
}).open();
|
|
});
|
|
tag.find(".button-set-default").on('click', event => {
|
|
if (selected_profile && selected_profile.id != 'default') {
|
|
profiles.set_default_profile(selected_profile);
|
|
update_profile_list();
|
|
profiles.mark_need_save();
|
|
}
|
|
});
|
|
tag.find(".button-delete").on('click', event => {
|
|
if (selected_profile && selected_profile.id != 'default') {
|
|
event.preventDefault();
|
|
Modals.spawnYesNo(_translations.En9YP_2L || (_translations.En9YP_2L = tr("Are you sure?")), _translations.tQHWsdmy || (_translations.tQHWsdmy = tr("Do you really want to delete this profile?")), result => {
|
|
if (result) {
|
|
profiles.delete_profile(selected_profile);
|
|
update_profile_list();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
modal.close_listener.push(() => {
|
|
if (profiles.requires_save())
|
|
profiles.save();
|
|
});
|
|
update_profile_list();
|
|
}
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["8066716c36e5b50be5b873a38c0887fa3845473643d72e3e801f31873194ce41"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["8066716c36e5b50be5b873a38c0887fa3845473643d72e3e801f31873194ce41"] = "8066716c36e5b50be5b873a38c0887fa3845473643d72e3e801f31873194ce41";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "xEzPwX5F", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBanList.ts (36,29)" }, { name: "_zgMdWvL", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBanList.ts (50,38)" }, { name: "cBb82yEw", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBanList.ts (54,25)" }, { name: "LknfHAUI", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBanList.ts (56,29)" }, { name: "crqIN56n", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBanList.ts (72,38)" }, { name: "IfovotkL", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBanList.ts (76,25)" }, { name: "N0nYzXYj", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBanList.ts (84,34)" }, { name: "xmKQAikZ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBanList.ts (92,29)" }, { name: "nmdJ5Rwk", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBanList.ts (176,26)" }, { name: "Ba0xrSlB", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBanList.ts (185,26)" }, { name: "BqwjkvXy", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBanList.ts (191,21)" }, { name: "fKqJzgya", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBanList.ts (233,25)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var Modals;
|
|
(function (Modals) {
|
|
function openBanList(client) {
|
|
let update;
|
|
const modal = spawnBanListModal(() => update(), () => {
|
|
Modals.spawnBanCreate(undefined, result => {
|
|
if (result.server_id < 0)
|
|
result.server_id = undefined;
|
|
console.log(_translations.xEzPwX5F || (_translations.xEzPwX5F = tr("Adding ban %o")), result);
|
|
client.serverConnection.send_command("banadd", {
|
|
ip: result.ip,
|
|
name: result.name,
|
|
uid: result.unique_id,
|
|
hwid: result.hardware_id,
|
|
banreason: result.reason,
|
|
time: result.timestamp_expire.getTime() > 0 ? (result.timestamp_expire.getTime() - result.timestamp_created.getTime()) / 1000 : 0,
|
|
sid: result.server_id
|
|
}).then(() => {
|
|
update();
|
|
}).catch(error => {
|
|
//TODO tr
|
|
createErrorModal(_translations._zgMdWvL || (_translations._zgMdWvL = tr("Failed to add ban")), "Failed to add ban.<br>Reason: " + (error instanceof CommandResult ? error.extra_message || error.message : error)).open();
|
|
});
|
|
});
|
|
}, ban => {
|
|
console.log(_translations.cBb82yEw || (_translations.cBb82yEw = tr("Editing ban %o")), ban);
|
|
Modals.spawnBanCreate(ban, result => {
|
|
console.log(_translations.LknfHAUI || (_translations.LknfHAUI = tr("Apply edit changes %o")), result);
|
|
if (result.server_id < 0)
|
|
result.server_id = undefined;
|
|
client.serverConnection.send_command("banedit", {
|
|
banid: result.banid,
|
|
ip: result.ip,
|
|
name: result.name,
|
|
uid: result.unique_id,
|
|
hwid: result.hardware_id,
|
|
banreason: result.reason,
|
|
time: result.timestamp_expire.getTime() > 0 ? (result.timestamp_expire.getTime() - result.timestamp_created.getTime()) / 1000 : 0,
|
|
sid: result.server_id
|
|
}).then(() => {
|
|
update();
|
|
}).catch(error => {
|
|
//TODO tr
|
|
createErrorModal(_translations.crqIN56n || (_translations.crqIN56n = tr("Failed to edit ban")), "Failed to edit ban.<br>Reason: " + (error instanceof CommandResult ? error.extra_message || error.message : error)).open();
|
|
});
|
|
});
|
|
}, ban => {
|
|
console.log(_translations.IfovotkL || (_translations.IfovotkL = tr("Deleting ban %o")), ban);
|
|
client.serverConnection.send_command("bandel", {
|
|
banid: ban.banid,
|
|
sid: ban.server_id
|
|
}).then(() => {
|
|
update();
|
|
}).catch(error => {
|
|
//TODO tr
|
|
createErrorModal(_translations.N0nYzXYj || (_translations.N0nYzXYj = tr("Failed to delete ban")), "Failed to delete ban.<br>Reason: " + (error instanceof CommandResult ? error.extra_message || error.message : error)).open();
|
|
});
|
|
});
|
|
const single_handler = {
|
|
command: "notifybanlist",
|
|
function: command => {
|
|
const json = command.arguments;
|
|
console.log(_translations.xmKQAikZ || (_translations.xmKQAikZ = tr("Got banlist: %o")), json);
|
|
let bans = [];
|
|
for (const entry of json) {
|
|
/*
|
|
notify[index]["sid"] = elm->serverId;
|
|
notify[index]["banid"] = elm->banId;
|
|
if(allow_ip)
|
|
notify[index]["ip"] = elm->ip;
|
|
else
|
|
notify[index]["ip"] = "hidden";
|
|
notify[index]["name"] = elm->name;
|
|
notify[index]["uid"] = elm->uid;
|
|
notify[index]["lastnickname"] = elm->name; //Maybe update?
|
|
|
|
notify[index]["created"] = chrono::duration_cast<chrono::seconds>(elm->created.time_since_epoch()).count();
|
|
if (elm->until.time_since_epoch().count() != 0)
|
|
notify[index]["duration"] = chrono::duration_cast<chrono::seconds>(elm->until - elm->created).count();
|
|
else
|
|
notify[index]["duration"] = 0;
|
|
|
|
notify[index]["reason"] = elm->reason;
|
|
notify[index]["enforcements"] = elm->triggered;
|
|
|
|
notify[index]["invokername"] = elm->invokerName;
|
|
notify[index]["invokercldbid"] = elm->invokerDbId;
|
|
notify[index]["invokeruid"] = elm->invokerUid;
|
|
*/
|
|
bans.push({
|
|
server_id: parseInt(entry["sid"]),
|
|
banid: parseInt(entry["banid"]),
|
|
ip: entry["ip"],
|
|
name: entry["name"],
|
|
unique_id: entry["uid"],
|
|
hardware_id: entry["hwid"],
|
|
timestamp_created: new Date(parseInt(entry["created"]) * 1000),
|
|
timestamp_expire: new Date(parseInt(entry["duration"]) > 0 ? parseInt(entry["created"]) * 1000 + parseInt(entry["duration"]) * 1000 : 0),
|
|
invoker_name: entry["invokername"],
|
|
invoker_database_id: parseInt(entry["invokercldbid"]),
|
|
invoker_unique_id: entry["invokeruid"],
|
|
reason: entry["reason"],
|
|
enforcements: parseInt(entry["enforcements"]),
|
|
flag_own: entry["invokeruid"] == client.getClient().properties.client_unique_identifier
|
|
});
|
|
}
|
|
modal.addbans(bans);
|
|
return false;
|
|
}
|
|
};
|
|
client.serverConnection.command_handler_boss().register_single_handler(single_handler);
|
|
modal.modal.close_listener.push(() => {
|
|
client.serverConnection.command_handler_boss().remove_single_handler(single_handler);
|
|
});
|
|
update = () => {
|
|
//TODO test permission
|
|
modal.clear();
|
|
client.serverConnection.send_command("banlist", { sid: 0 }); //Global ban list
|
|
client.serverConnection.send_command("banlist").catch(error => {
|
|
if (error instanceof CommandResult) {
|
|
}
|
|
else {
|
|
console.error(error);
|
|
}
|
|
});
|
|
};
|
|
update();
|
|
}
|
|
Modals.openBanList = openBanList;
|
|
function spawnBanListModal(callback_update, callback_add, callback_edit, callback_delete) {
|
|
let result = {};
|
|
let entries = [];
|
|
const _callback_edit = ban_id => {
|
|
for (const entry of entries)
|
|
if (entry.banid == ban_id) {
|
|
callback_edit(entry);
|
|
return;
|
|
}
|
|
console.warn(_translations.nmdJ5Rwk || (_translations.nmdJ5Rwk = tr("Missing ban entry with id %d")), ban_id);
|
|
};
|
|
const _callback_delete = ban_id => {
|
|
for (const entry of entries)
|
|
if (entry.banid == ban_id) {
|
|
callback_delete(entry);
|
|
return;
|
|
}
|
|
console.warn(_translations.Ba0xrSlB || (_translations.Ba0xrSlB = tr("Missing ban entry with id %d")), ban_id);
|
|
};
|
|
let update_function;
|
|
let modal;
|
|
modal = createModal({
|
|
header: _translations.BqwjkvXy || (_translations.BqwjkvXy = tr("Banlist")),
|
|
body: () => {
|
|
let template = $("#tmpl_ban_list").renderTag();
|
|
apply_filter(template.find(".entry-filter"), template.find(".filter-flag-force-own"), template.find(".filter-flag-highlight-own"), template.find(".ban-entry-list"));
|
|
update_function = apply_buttons(template.find(".manage-buttons"), template.find(".entry-container .entries"), callback_add, _callback_edit, _callback_delete);
|
|
template.find(".button-close").on('click', _ => modal.close());
|
|
template.find(".button-refresh").on('click', () => callback_update());
|
|
return template;
|
|
},
|
|
footer: undefined,
|
|
width: "80%",
|
|
height: "80%"
|
|
});
|
|
modal.open();
|
|
modal.close_listener.push(() => entries = []);
|
|
const template_entry = $("#tmpl_ban_entry");
|
|
result.addbans = (bans) => {
|
|
for (const entry of bans) {
|
|
entries.push(entry);
|
|
template_entry.renderTag(entry).appendTo(modal.htmlTag.find(".entry-container .entries"));
|
|
}
|
|
modal.htmlTag.find(".entry-filter").trigger("change");
|
|
update_function();
|
|
};
|
|
result.clear = () => {
|
|
entries = [];
|
|
modal.htmlTag.find(".entry-container .entries").children().detach();
|
|
update_function();
|
|
};
|
|
result.modal = modal;
|
|
return result;
|
|
}
|
|
Modals.spawnBanListModal = spawnBanListModal;
|
|
function apply_filter(input, show_own_bans, highlight_own_bans, elements) {
|
|
input.on('keyup change', event => {
|
|
const filter = input.val().trim();
|
|
const show_own_only = show_own_bans.prop("checked");
|
|
const highlight_own = highlight_own_bans.prop("checked");
|
|
console.log(_translations.fKqJzgya || (_translations.fKqJzgya = tr("Search for filter %s")), filter);
|
|
let shown = 0, hidden = 0;
|
|
elements.find(".ban-entry").each((_idx, _entry) => {
|
|
const entry = $(_entry);
|
|
if (entry.hasClass("ban-entry-own")) {
|
|
if (highlight_own)
|
|
entry.addClass("ban-entry-own-bold");
|
|
else
|
|
entry.removeClass("ban-entry-own-bold");
|
|
}
|
|
else if (show_own_only) {
|
|
if (entry.hide().hasClass("selected"))
|
|
entry.trigger("click");
|
|
hidden++;
|
|
return;
|
|
}
|
|
if (filter.length == 0 || entry.text().indexOf(filter) > 0) {
|
|
entry.show();
|
|
shown++;
|
|
}
|
|
else {
|
|
if (entry.hide().hasClass("selected"))
|
|
entry.trigger("click");
|
|
hidden++;
|
|
}
|
|
});
|
|
$(".entry-count-info").text((shown + hidden) + " entries. " + shown + " entries shown");
|
|
});
|
|
show_own_bans.on('click', () => input.trigger('change'));
|
|
highlight_own_bans.on('click', () => input.trigger('change'));
|
|
}
|
|
function apply_buttons(tag, elements, cb_add, cb_edit, cb_delete) {
|
|
const update = () => {
|
|
console.log(elements.find(".ban-entry.selected").length);
|
|
$(".button-edit, .button-remove").prop("disabled", elements.find(".ban-entry.selected").length == 0);
|
|
};
|
|
tag.find(".button-add").on('click', event => cb_add());
|
|
tag.find(".button-edit").on('click', event => {
|
|
const selected = elements.find(".ban-entry.selected");
|
|
if (!selected)
|
|
return;
|
|
cb_edit(parseInt(selected.attr("ban-id")));
|
|
});
|
|
tag.find(".button-remove").on('click', event => {
|
|
const selected = elements.find(".ban-entry.selected");
|
|
if (!selected)
|
|
return;
|
|
cb_delete(parseInt(selected.attr("ban-id")));
|
|
});
|
|
const element_selected = element => {
|
|
elements.find(".ban-entry").removeClass("selected");
|
|
if (element.is(":visible"))
|
|
element.addClass("selected");
|
|
update();
|
|
};
|
|
const click_handler = event => element_selected($(event.currentTarget));
|
|
const context_handler = event => {
|
|
const element = $(event.currentTarget);
|
|
element_selected(element);
|
|
event.preventDefault();
|
|
spawn_context_menu(event.pageX, event.pageY, {
|
|
name: "Edit",
|
|
type: MenuEntryType.ENTRY,
|
|
callback: () => cb_edit(parseInt(element.attr("ban-id")))
|
|
}, {
|
|
name: "Delete",
|
|
type: MenuEntryType.ENTRY,
|
|
callback: () => cb_delete(parseInt(element.attr("ban-id")))
|
|
});
|
|
};
|
|
return () => {
|
|
elements.find(".ban-entry").each((_idx, _entry) => {
|
|
_entry.addEventListener("click", click_handler);
|
|
_entry.addEventListener("contextmenu", context_handler);
|
|
});
|
|
update();
|
|
};
|
|
}
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["ea246f47b86a1f3980314e24ff4859690e9e4f0a7be06be3102c8e81d6541f83"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["ea246f47b86a1f3980314e24ff4859690e9e4f0a7be06be3102c8e81d6541f83"] = "ea246f47b86a1f3980314e24ff4859690e9e4f0a7be06be3102c8e81d6541f83";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "my8hxlKB", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (109,26)" }, { name: "AWWxOq6S", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (109,50)" }, { name: "UZAOab6m", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (230,30)" }, { name: "J6wF_VJg", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (230,63)" }, { name: "ZlcA0t6X", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (273,26)" }, { name: "wK8ikYh2", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (273,43)" }, { name: "Y59uaHGW", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (279,37)" }, { name: "lv404I8O", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (279,54)" }, { name: "s4M7Bo9c", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (282,38)" }, { name: "osnGlNqU", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (288,26)" }, { name: "qiooa_qH", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (288,49)" }, { name: "RW7ji6sK", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (306,30)" }, { name: "SHNh0XMm", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (306,66)" }, { name: "k6lZeW4L", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (313,30)" }, { name: "YRGt3SGU", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (313,58)" }, { name: "Ooqjp5G0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (327,30)" }, { name: "GNCPCtA5", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (327,62)" }, { name: "WLOZ7vRh", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (447,30)" }, { name: "mwo0IEKd", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (447,66)" }, { name: "CK1J9YhU", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (456,30)" }, { name: "ODydgt3V", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (456,62)" }, { name: "_VLMFimn", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (464,30)" }, { name: "nEfbnQ1a", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/frames/ControlBar.ts (464,62)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../client.ts" />
|
|
/// <reference path="../modal/ModalSettings.ts" />
|
|
/// <reference path="../modal/ModalBanList.ts" />
|
|
/*
|
|
client_output_hardware Value: '1'
|
|
client_output_muted Value: '0'
|
|
client_outputonly_muted Value: '0'
|
|
|
|
client_input_hardware Value: '1'
|
|
client_input_muted Value: '0'
|
|
|
|
client_away Value: '0'
|
|
client_away_message Value: ''
|
|
*/
|
|
class ControlBar {
|
|
constructor(handle, htmlTag) {
|
|
this.codec_supported = false;
|
|
this.support_playback = false;
|
|
this.support_record = false;
|
|
this.handle = handle;
|
|
this.htmlTag = htmlTag;
|
|
}
|
|
initialise() {
|
|
this.htmlTag.find(".btn_connect").on('click', this.onConnect.bind(this));
|
|
this.htmlTag.find(".btn_disconnect").on('click', this.onDisconnect.bind(this));
|
|
this.htmlTag.find(".btn_mute_input").on('click', this.onInputMute.bind(this));
|
|
this.htmlTag.find(".btn_mute_output").on('click', this.onOutputMute.bind(this));
|
|
this.htmlTag.find(".btn_open_settings").on('click', this.onOpenSettings.bind(this));
|
|
this.htmlTag.find(".btn_permissions").on('click', this.onPermission.bind(this));
|
|
this.htmlTag.find(".btn_banlist").on('click', this.onBanlist.bind(this));
|
|
this.htmlTag.find(".button-playlist-manage").on('click', this.on_playlist_manage.bind(this));
|
|
{
|
|
let tokens = this.htmlTag.find(".btn_token");
|
|
tokens.find(".button-dropdown").on('click', () => {
|
|
tokens.find(".dropdown").addClass("displayed");
|
|
});
|
|
tokens.on('mouseleave', () => {
|
|
tokens.find(".dropdown").removeClass("displayed");
|
|
});
|
|
tokens.find(".btn_token_use").on('click', this.on_token_use.bind(this));
|
|
tokens.find(".btn_token_list").on('click', this.on_token_list.bind(this));
|
|
}
|
|
{
|
|
let away = this.htmlTag.find(".btn_away");
|
|
away.find(".button-dropdown").on('click', () => {
|
|
away.find(".dropdown").addClass("displayed");
|
|
});
|
|
away.on('mouseleave', () => {
|
|
away.find(".dropdown").removeClass("displayed");
|
|
});
|
|
away.find(".btn_away_toggle").on('click', this.on_away_toggle.bind(this));
|
|
away.find(".btn_away_message").on('click', this.on_away_set_message.bind(this));
|
|
}
|
|
{
|
|
let bookmark = this.htmlTag.find(".btn_bookmark");
|
|
bookmark.find(".button-dropdown").on('click', () => {
|
|
bookmark.find("> .dropdown").addClass("displayed");
|
|
});
|
|
bookmark.on('mouseleave', () => {
|
|
bookmark.find("> .dropdown").removeClass("displayed");
|
|
});
|
|
bookmark.find(".btn_bookmark_list").on('click', this.on_bookmark_manage.bind(this));
|
|
bookmark.find(".btn_bookmark_add").on('click', this.on_bookmark_server_add.bind(this));
|
|
this.update_bookmarks();
|
|
this.update_bookmark_status();
|
|
}
|
|
{
|
|
let query = this.htmlTag.find(".btn_query");
|
|
query.find(".button-dropdown").on('click', () => {
|
|
query.find(".dropdown").addClass("displayed");
|
|
});
|
|
query.on('mouseleave', () => {
|
|
query.find(".dropdown").removeClass("displayed");
|
|
});
|
|
query.find(".btn_query_toggle").on('click', this.on_query_visibility_toggle.bind(this));
|
|
query.find(".btn_query_create").on('click', this.on_query_create.bind(this));
|
|
query.find(".btn_query_manage").on('click', this.on_query_manage.bind(this));
|
|
}
|
|
//Need an initialise
|
|
this.muteInput = settings.static_global("mute_input", false);
|
|
this.muteOutput = settings.static_global("mute_output", false);
|
|
this.query_visible = settings.static_global("show_server_queries", false);
|
|
}
|
|
on_away_toggle() {
|
|
this._awayMessage = "";
|
|
this.away = !this._away;
|
|
}
|
|
on_away_set_message() {
|
|
createInputModal(_translations.my8hxlKB || (_translations.my8hxlKB = tr("Set away message")), _translations.AWWxOq6S || (_translations.AWWxOq6S = tr("Please enter the away message")), message => true, message => {
|
|
if (message)
|
|
this.away = message;
|
|
}).open();
|
|
}
|
|
onInputMute() {
|
|
this.muteInput = !this._muteInput;
|
|
}
|
|
onOutputMute() {
|
|
this.muteOutput = !this._muteOutput;
|
|
}
|
|
set muteInput(flag) {
|
|
if (this._muteInput == flag)
|
|
return;
|
|
this._muteInput = flag;
|
|
let tag = this.htmlTag.find(".btn_mute_input");
|
|
if (flag) {
|
|
if (!tag.hasClass("activated"))
|
|
tag.addClass("activated");
|
|
tag.find(".icon_x32").attr("class", "icon_x32 client-input_muted");
|
|
}
|
|
else {
|
|
if (tag.hasClass("activated"))
|
|
tag.removeClass("activated");
|
|
tag.find(".icon_x32").attr("class", "icon_x32 client-capture");
|
|
}
|
|
if (this.handle.serverConnection.connected)
|
|
this.handle.serverConnection.send_command("clientupdate", {
|
|
client_input_muted: this._muteInput
|
|
});
|
|
settings.changeGlobal("mute_input", this._muteInput);
|
|
this.updateMicrophoneRecordState();
|
|
}
|
|
get muteOutput() { return this._muteOutput; }
|
|
set muteOutput(flag) {
|
|
if (this._muteOutput == flag)
|
|
return;
|
|
this._muteOutput = flag;
|
|
let tag = this.htmlTag.find(".btn_mute_output");
|
|
if (flag) {
|
|
if (!tag.hasClass("activated"))
|
|
tag.addClass("activated");
|
|
tag.find(".icon_x32").attr("class", "icon_x32 client-output_muted");
|
|
}
|
|
else {
|
|
if (tag.hasClass("activated"))
|
|
tag.removeClass("activated");
|
|
tag.find(".icon_x32").attr("class", "icon_x32 client-volume");
|
|
}
|
|
if (this.handle.serverConnection.connected)
|
|
this.handle.serverConnection.send_command("clientupdate", {
|
|
client_output_muted: this._muteOutput
|
|
});
|
|
settings.changeGlobal("mute_output", this._muteOutput);
|
|
this.updateMicrophoneRecordState();
|
|
}
|
|
set away(value) {
|
|
if (typeof (value) == "boolean") {
|
|
if (this._away == value)
|
|
return;
|
|
this._away = value;
|
|
this._awayMessage = "";
|
|
}
|
|
else {
|
|
this._awayMessage = value;
|
|
this._away = true;
|
|
}
|
|
let tag = this.htmlTag.find(".btn_away_toggle");
|
|
if (this._away) {
|
|
tag.addClass("activated");
|
|
}
|
|
else {
|
|
tag.removeClass("activated");
|
|
}
|
|
if (this.handle.serverConnection.connected)
|
|
this.handle.serverConnection.send_command("clientupdate", {
|
|
client_away: this._away,
|
|
client_away_message: this._awayMessage
|
|
});
|
|
this.updateMicrophoneRecordState();
|
|
}
|
|
updateMicrophoneRecordState() {
|
|
let enabled = !this._muteInput && !this._muteOutput && !this._away;
|
|
this.handle.voiceConnection.voiceRecorder.update(enabled);
|
|
}
|
|
updateProperties() {
|
|
if (this.handle.serverConnection.connected)
|
|
this.handle.serverConnection.send_command("clientupdate", {
|
|
client_input_muted: this._muteInput,
|
|
client_output_muted: this._muteOutput,
|
|
client_away: this._away,
|
|
client_away_message: this._awayMessage,
|
|
client_input_hardware: this.codec_supported && this.support_record,
|
|
client_output_hardware: this.codec_supported && this.support_playback
|
|
});
|
|
}
|
|
updateVoice(targetChannel) {
|
|
if (!targetChannel)
|
|
targetChannel = this.handle.getClient().currentChannel();
|
|
let client = this.handle.getClient();
|
|
this.codec_supported = targetChannel ? this.handle.voiceConnection.codecSupported(targetChannel.properties.channel_codec) : true;
|
|
this.support_record = this.handle.voiceConnection.voice_send_support();
|
|
this.support_playback = this.handle.voiceConnection.voice_playback_support();
|
|
this.htmlTag.find(".btn_mute_input").prop("disabled", !this.codec_supported || !this.support_playback || !this.support_record);
|
|
this.htmlTag.find(".btn_mute_output").prop("disabled", !this.codec_supported || !this.support_playback);
|
|
this.handle.serverConnection.send_command("clientupdate", {
|
|
client_input_hardware: this.codec_supported && this.support_record,
|
|
client_output_hardware: this.codec_supported && this.support_playback
|
|
});
|
|
if (!this.codec_supported)
|
|
createErrorModal(_translations.UZAOab6m || (_translations.UZAOab6m = tr("Channel codec unsupported")), _translations.J6wF_VJg || (_translations.J6wF_VJg = tr("This channel has an unsupported codec.<br>You cant speak or listen to anybody within this channel!"))).open();
|
|
/* Update these properties anyways (for case the server fails to handle the command) */
|
|
client.updateVariables({ key: "client_input_hardware", value: (this.codec_supported && this.support_record) + "" }, { key: "client_output_hardware", value: (this.codec_supported && this.support_playback) + "" });
|
|
}
|
|
onOpenSettings() {
|
|
Modals.spawnSettingsModal();
|
|
}
|
|
onConnect() {
|
|
this.handle.cancel_reconnect();
|
|
Modals.spawnConnectModal({
|
|
url: "ts.TeaSpeak.de",
|
|
enforce: false
|
|
});
|
|
}
|
|
update_connection_state() {
|
|
switch (this.handle.serverConnection ? this.handle.serverConnection._connectionState : ConnectionState.UNCONNECTED) {
|
|
case ConnectionState.CONNECTED:
|
|
case ConnectionState.CONNECTING:
|
|
case ConnectionState.INITIALISING:
|
|
this.htmlTag.find(".btn_disconnect").show();
|
|
this.htmlTag.find(".btn_connect").hide();
|
|
break;
|
|
default:
|
|
this.htmlTag.find(".btn_disconnect").hide();
|
|
this.htmlTag.find(".btn_connect").show();
|
|
}
|
|
}
|
|
onDisconnect() {
|
|
this.handle.cancel_reconnect();
|
|
this.handle.handleDisconnect(DisconnectReason.REQUESTED); //TODO message?
|
|
this.update_connection_state();
|
|
sound.play(Sound.CONNECTION_DISCONNECTED);
|
|
}
|
|
on_token_use() {
|
|
createInputModal(_translations.ZlcA0t6X || (_translations.ZlcA0t6X = tr("Use token")), _translations.wK8ikYh2 || (_translations.wK8ikYh2 = tr("Please enter your token/priviledge key")), message => message.length > 0, result => {
|
|
if (!result)
|
|
return;
|
|
if (this.handle.serverConnection.connected)
|
|
this.handle.serverConnection.send_command("tokenuse", {
|
|
token: result
|
|
}).then(() => {
|
|
createInfoModal(_translations.Y59uaHGW || (_translations.Y59uaHGW = tr("Use token")), _translations.lv404I8O || (_translations.lv404I8O = tr("Toke successfully used!"))).open();
|
|
}).catch(error => {
|
|
//TODO tr
|
|
createErrorModal(_translations.s4M7Bo9c || (_translations.s4M7Bo9c = tr("Use token")), "Failed to use token: " + (error instanceof CommandResult ? error.message : error)).open();
|
|
});
|
|
}).open();
|
|
}
|
|
on_token_list() {
|
|
createErrorModal(_translations.osnGlNqU || (_translations.osnGlNqU = tr("Not implemented")), _translations.qiooa_qH || (_translations.qiooa_qH = tr("Token list is not implemented yet!"))).open();
|
|
}
|
|
onPermission() {
|
|
let button = this.htmlTag.find(".btn_permissions");
|
|
button.addClass("activated");
|
|
setTimeout(() => {
|
|
Modals.spawnPermissionEdit().open();
|
|
button.removeClass("activated");
|
|
}, 0);
|
|
}
|
|
onBanlist() {
|
|
if (!this.handle.serverConnection)
|
|
return;
|
|
if (this.handle.permissions.neededPermission(PermissionType.B_CLIENT_BAN_LIST).granted(1)) {
|
|
Modals.openBanList(this.handle);
|
|
}
|
|
else {
|
|
createErrorModal(_translations.RW7ji6sK || (_translations.RW7ji6sK = tr("You dont have the permission")), _translations.SHNh0XMm || (_translations.SHNh0XMm = tr("You dont have the permission to view the ban list"))).open();
|
|
sound.play(Sound.ERROR_INSUFFICIENT_PERMISSIONS);
|
|
}
|
|
}
|
|
on_bookmark_server_add() {
|
|
if (globalClient && globalClient.connected) {
|
|
createInputModal(_translations.k6lZeW4L || (_translations.k6lZeW4L = tr("Enter bookmarks name")), _translations.YRGt3SGU || (_translations.YRGt3SGU = tr("Please enter the bookmarks name:<br>")), text => true, result => {
|
|
if (result) {
|
|
const bookmark = bookmarks.create_bookmark(result, bookmarks.bookmarks(), {
|
|
server_port: globalClient.serverConnection._remote_address.port,
|
|
server_address: globalClient.serverConnection._remote_address.host,
|
|
server_password: "",
|
|
server_password_hash: ""
|
|
}, globalClient.getClient().clientNickName());
|
|
bookmarks.save_bookmark(bookmark);
|
|
this.update_bookmarks();
|
|
}
|
|
}).open();
|
|
}
|
|
else {
|
|
createErrorModal(_translations.Ooqjp5G0 || (_translations.Ooqjp5G0 = tr("You have to be connected")), _translations.GNCPCtA5 || (_translations.GNCPCtA5 = tr("You have to be connected!"))).open();
|
|
}
|
|
}
|
|
update_bookmark_status() {
|
|
this.htmlTag.find(".btn_bookmark_add").removeClass("hidden").addClass("disabled");
|
|
this.htmlTag.find(".btn_bookmark_remove").addClass("hidden");
|
|
}
|
|
update_bookmarks() {
|
|
//<div class="btn_bookmark_connect" target="localhost"><a>Localhost</a></div>
|
|
let tag_bookmark = this.htmlTag.find(".btn_bookmark .dropdown");
|
|
tag_bookmark.find(".bookmark, .directory").detach();
|
|
const build_entry = (bookmark) => {
|
|
if (bookmark.type == bookmarks.BookmarkType.ENTRY) {
|
|
const mark = bookmark;
|
|
return $.spawn("div")
|
|
.addClass("bookmark")
|
|
.append($.spawn("div").addClass("icon client-server"))
|
|
.append($.spawn("div")
|
|
.addClass("name")
|
|
.text(bookmark.display_name)
|
|
.on('click', event => {
|
|
this.htmlTag.find(".btn_bookmark").find(".dropdown").removeClass("displayed");
|
|
const profile = profiles.find_profile(mark.connect_profile) || profiles.default_profile();
|
|
if (profile.valid()) {
|
|
this.handle.startConnection(mark.server_properties.server_address + ":" + mark.server_properties.server_port, profile, mark.nickname, {
|
|
password: mark.server_properties.server_password_hash,
|
|
hashed: true
|
|
});
|
|
}
|
|
else {
|
|
Modals.spawnConnectModal({
|
|
url: mark.server_properties.server_address + ":" + mark.server_properties.server_port,
|
|
enforce: true
|
|
}, {
|
|
profile: profile,
|
|
enforce: true
|
|
});
|
|
}
|
|
}));
|
|
}
|
|
else {
|
|
const mark = bookmark;
|
|
const container = $.spawn("div").addClass("sub-menu dropdown");
|
|
for (const member of mark.content)
|
|
container.append(build_entry(member));
|
|
return $.spawn("div")
|
|
.addClass("directory")
|
|
.append($.spawn("div").addClass("icon client-folder"))
|
|
.append($.spawn("div")
|
|
.addClass("name")
|
|
.text(bookmark.display_name))
|
|
.append($.spawn("div").addClass("arrow right"))
|
|
.append($.spawn("div").addClass("sub-container")
|
|
.append(container));
|
|
}
|
|
};
|
|
for (const bookmark of bookmarks.bookmarks().content) {
|
|
const entry = build_entry(bookmark);
|
|
tag_bookmark.append(entry);
|
|
}
|
|
}
|
|
on_bookmark_manage() {
|
|
Modals.spawnBookmarkModal();
|
|
}
|
|
get query_visible() {
|
|
return this._query_visible;
|
|
}
|
|
set query_visible(flag) {
|
|
console.error(flag);
|
|
if (this._query_visible == flag)
|
|
return;
|
|
this._query_visible = flag;
|
|
settings.changeGlobal("show_server_queries", flag);
|
|
this.update_query_visibility_button();
|
|
this.handle.channelTree.toggle_server_queries(flag);
|
|
}
|
|
on_query_visibility_toggle() {
|
|
this.query_visible = !this._query_visible;
|
|
this.update_query_visibility_button();
|
|
}
|
|
update_query_visibility_button() {
|
|
let tag = this.htmlTag.find(".btn_query_toggle");
|
|
if (this._query_visible) {
|
|
tag.addClass("activated");
|
|
}
|
|
else {
|
|
tag.removeClass("activated");
|
|
}
|
|
}
|
|
on_query_create() {
|
|
if (this.handle.permissions.neededPermission(PermissionType.B_CLIENT_CREATE_MODIFY_SERVERQUERY_LOGIN).granted(1)) {
|
|
Modals.spawnQueryCreate();
|
|
}
|
|
else {
|
|
createErrorModal(_translations.WLOZ7vRh || (_translations.WLOZ7vRh = tr("You dont have the permission")), _translations.mwo0IEKd || (_translations.mwo0IEKd = tr("You dont have the permission to create a server query login"))).open();
|
|
sound.play(Sound.ERROR_INSUFFICIENT_PERMISSIONS);
|
|
}
|
|
}
|
|
on_query_manage() {
|
|
if (globalClient && globalClient.connected) {
|
|
Modals.spawnQueryManage(globalClient);
|
|
}
|
|
else {
|
|
createErrorModal(_translations.CK1J9YhU || (_translations.CK1J9YhU = tr("You have to be connected")), _translations.ODydgt3V || (_translations.ODydgt3V = tr("You have to be connected!"))).open();
|
|
}
|
|
}
|
|
on_playlist_manage() {
|
|
if (this.handle && this.handle.connected) {
|
|
Modals.spawnPlaylistManage(this.handle);
|
|
}
|
|
else {
|
|
createErrorModal(_translations._VLMFimn || (_translations._VLMFimn = tr("You have to be connected")), _translations.nEfbnQ1a || (_translations.nEfbnQ1a = tr("You have to be connected to use this function!"))).open();
|
|
}
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["c2be6d3793b763169d17f03b4957ab4eb0699f1817032fe7c2b6e0c635416ce8"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["c2be6d3793b763169d17f03b4957ab4eb0699f1817032fe7c2b6e0c635416ce8"] = "c2be6d3793b763169d17f03b4957ab4eb0699f1817032fe7c2b6e0c635416ce8";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "JAEWtQTW", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (99,21)" }, { name: "bV4lkvkA", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (107,34)" }, { name: "u8qFbvGn", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (107,70)" }, { name: "p_L1zpOY", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (144,30)" }, { name: "mkYBZI51", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (183,51)" }, { name: "i13Qq5lP", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (186,31)" }, { name: "cVoTk97h", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (190,25)" }, { name: "KCk709tI", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (191,25)" }, { name: "mq0BoYHj", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (196,25)" }, { name: "wCe7uH8c", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (206,31)" }, { name: "Jx6FIucL", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (208,21)" }, { name: "ckq4sOQG", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (209,21)" }, { name: "CpO5hsYt", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (213,31)" }, { name: "gQT1woZd", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (215,21)" }, { name: "d4MTpRCT", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (216,21)" }, { name: "JT_pws6H", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (223,31)" }, { name: "rUpUHlzi", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (226,21)" }, { name: "_lZjyLc0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (227,21)" }, { name: "NeJK3Ye8", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (232,47)" }, { name: "PsDVUZ4O", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (234,21)" }, { name: "k9_p6t0P", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (243,47)" }, { name: "vgqAaBSb", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (244,34)" }, { name: "nYEz_XI9", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (244,57)" }, { name: "Lq3w511A", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (253,47)" }, { name: "tqIlSIVg", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (260,47)" }, { name: "rLg_S2Tb", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (266,31)" }, { name: "AwKnUotx", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (267,31)" }, { name: "bMtuaii5", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (281,29)" }, { name: "uS396luz", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (284,45)" }, { name: "dDHTCdwB", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (286,25)" }, { name: "BmUuHG2D", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (294,49)" }, { name: "Zt58aq4G", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (295,29)" }, { name: "AWIMAHNY", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/client.ts (304,45)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="log.ts" />
|
|
/// <reference path="voice/AudioController.ts" />
|
|
/// <reference path="proto.ts" />
|
|
/// <reference path="ui/view.ts" />
|
|
/// <reference path="settings.ts" />
|
|
/// <reference path="ui/frames/SelectedItemInfo.ts" />
|
|
/// <reference path="FileManager.ts" />
|
|
/// <reference path="permission/PermissionManager.ts" />
|
|
/// <reference path="permission/GroupManager.ts" />
|
|
/// <reference path="ui/frames/ControlBar.ts" />
|
|
/// <reference path="connection/ConnectionBase.ts" />
|
|
var DisconnectReason;
|
|
(function (DisconnectReason) {
|
|
DisconnectReason[DisconnectReason["REQUESTED"] = 0] = "REQUESTED";
|
|
DisconnectReason[DisconnectReason["CONNECT_FAILURE"] = 1] = "CONNECT_FAILURE";
|
|
DisconnectReason[DisconnectReason["CONNECTION_CLOSED"] = 2] = "CONNECTION_CLOSED";
|
|
DisconnectReason[DisconnectReason["CONNECTION_FATAL_ERROR"] = 3] = "CONNECTION_FATAL_ERROR";
|
|
DisconnectReason[DisconnectReason["CONNECTION_PING_TIMEOUT"] = 4] = "CONNECTION_PING_TIMEOUT";
|
|
DisconnectReason[DisconnectReason["CLIENT_KICKED"] = 5] = "CLIENT_KICKED";
|
|
DisconnectReason[DisconnectReason["CLIENT_BANNED"] = 6] = "CLIENT_BANNED";
|
|
DisconnectReason[DisconnectReason["HANDSHAKE_FAILED"] = 7] = "HANDSHAKE_FAILED";
|
|
DisconnectReason[DisconnectReason["SERVER_CLOSED"] = 8] = "SERVER_CLOSED";
|
|
DisconnectReason[DisconnectReason["SERVER_REQUIRES_PASSWORD"] = 9] = "SERVER_REQUIRES_PASSWORD";
|
|
DisconnectReason[DisconnectReason["UNKNOWN"] = 10] = "UNKNOWN";
|
|
})(DisconnectReason || (DisconnectReason = {}));
|
|
var ConnectionState;
|
|
(function (ConnectionState) {
|
|
ConnectionState[ConnectionState["UNCONNECTED"] = 0] = "UNCONNECTED";
|
|
ConnectionState[ConnectionState["CONNECTING"] = 1] = "CONNECTING";
|
|
ConnectionState[ConnectionState["INITIALISING"] = 2] = "INITIALISING";
|
|
ConnectionState[ConnectionState["CONNECTED"] = 3] = "CONNECTED";
|
|
ConnectionState[ConnectionState["DISCONNECTING"] = 4] = "DISCONNECTING";
|
|
})(ConnectionState || (ConnectionState = {}));
|
|
var ViewReasonId;
|
|
(function (ViewReasonId) {
|
|
ViewReasonId[ViewReasonId["VREASON_USER_ACTION"] = 0] = "VREASON_USER_ACTION";
|
|
ViewReasonId[ViewReasonId["VREASON_MOVED"] = 1] = "VREASON_MOVED";
|
|
ViewReasonId[ViewReasonId["VREASON_SYSTEM"] = 2] = "VREASON_SYSTEM";
|
|
ViewReasonId[ViewReasonId["VREASON_TIMEOUT"] = 3] = "VREASON_TIMEOUT";
|
|
ViewReasonId[ViewReasonId["VREASON_CHANNEL_KICK"] = 4] = "VREASON_CHANNEL_KICK";
|
|
ViewReasonId[ViewReasonId["VREASON_SERVER_KICK"] = 5] = "VREASON_SERVER_KICK";
|
|
ViewReasonId[ViewReasonId["VREASON_BAN"] = 6] = "VREASON_BAN";
|
|
ViewReasonId[ViewReasonId["VREASON_SERVER_STOPPED"] = 7] = "VREASON_SERVER_STOPPED";
|
|
ViewReasonId[ViewReasonId["VREASON_SERVER_LEFT"] = 8] = "VREASON_SERVER_LEFT";
|
|
ViewReasonId[ViewReasonId["VREASON_CHANNEL_UPDATED"] = 9] = "VREASON_CHANNEL_UPDATED";
|
|
ViewReasonId[ViewReasonId["VREASON_EDITED"] = 10] = "VREASON_EDITED";
|
|
ViewReasonId[ViewReasonId["VREASON_SERVER_SHUTDOWN"] = 11] = "VREASON_SERVER_SHUTDOWN";
|
|
})(ViewReasonId || (ViewReasonId = {}));
|
|
class TSClient {
|
|
constructor() {
|
|
this._clientId = 0;
|
|
this._reconnect_attempt = false;
|
|
this.selectInfo = new InfoBar(this, $("#select_info"));
|
|
this.channelTree = new ChannelTree(this, $("#channelTree"));
|
|
this.serverConnection = new connection.ServerConnection(this);
|
|
this.fileManager = new FileManager(this);
|
|
this.permissions = new PermissionManager(this);
|
|
this.groups = new GroupManager(this);
|
|
this.voiceConnection = new VoiceConnection(this);
|
|
this._ownEntry = new LocalClientEntry(this);
|
|
this.controlBar = new ControlBar(this, $("#control_bar"));
|
|
this.channelTree.registerClient(this._ownEntry);
|
|
}
|
|
setup() {
|
|
this.controlBar.initialise();
|
|
}
|
|
startConnection(addr, profile, name, password) {
|
|
this.cancel_reconnect();
|
|
this._reconnect_attempt = false;
|
|
if (this.serverConnection)
|
|
this.handleDisconnect(DisconnectReason.REQUESTED);
|
|
let idx = addr.lastIndexOf(':');
|
|
let port;
|
|
let host;
|
|
if (idx != -1) {
|
|
port = parseInt(addr.substr(idx + 1));
|
|
host = addr.substr(0, idx);
|
|
}
|
|
else {
|
|
host = addr;
|
|
port = 9987;
|
|
}
|
|
console.log(_translations.JAEWtQTW || (_translations.JAEWtQTW = tr("Start connection to %s:%d")), host, port);
|
|
this.channelTree.initialiseHead(addr, { host, port });
|
|
if (password && !password.hashed) {
|
|
helpers.hashPassword(password.password).then(password => {
|
|
/* errors will be already handled via the handle disconnect thing */
|
|
this.serverConnection.connect({ host, port }, new connection.HandshakeHandler(profile, name, password));
|
|
}).catch(error => {
|
|
createErrorModal(_translations.bV4lkvkA || (_translations.bV4lkvkA = tr("Error while hashing password")), (_translations.u8qFbvGn || (_translations.u8qFbvGn = tr("Failed to hash server password!<br>"))) + error).open();
|
|
});
|
|
}
|
|
else {
|
|
/* errors will be already handled via the handle disconnect thing */
|
|
this.serverConnection.connect({ host, port }, new connection.HandshakeHandler(profile, name, password ? password.password : undefined));
|
|
}
|
|
}
|
|
getClient() { return this._ownEntry; }
|
|
getClientId() { return this._clientId; } //TODO here
|
|
set clientId(id) {
|
|
this._clientId = id;
|
|
this._ownEntry["_clientId"] = id;
|
|
}
|
|
get clientId() {
|
|
return this._clientId;
|
|
}
|
|
getServerConnection() { return this.serverConnection; }
|
|
/**
|
|
* LISTENER
|
|
*/
|
|
onConnected() {
|
|
console.log("Client connected!");
|
|
this.channelTree.registerClient(this._ownEntry);
|
|
settings.setServer(this.channelTree.server);
|
|
this.permissions.requestPermissionList();
|
|
this.serverConnection.send_command("channelsubscribeall");
|
|
if (this.groups.serverGroups.length == 0)
|
|
this.groups.requestGroups();
|
|
this.controlBar.updateProperties();
|
|
if (!this.voiceConnection.current_encoding_supported())
|
|
createErrorModal(_translations.p_L1zpOY || (_translations.p_L1zpOY = tr("Codec encode type not supported!")), tr("Codec encode type " + VoiceConnectionType[this.voiceConnection.type] + " not supported by this browser!<br>Choose another one!")).open(); //TODO tr
|
|
}
|
|
get connected() {
|
|
return this.serverConnection && this.serverConnection.connected();
|
|
}
|
|
certAcceptUrl() {
|
|
const properties = {
|
|
connect_default: true,
|
|
connect_profile: this.serverConnection._handshakeHandler.profile.id,
|
|
connect_address: this.serverConnection._remote_address.host + ":" + this.serverConnection._remote_address.port
|
|
};
|
|
const parameters = [];
|
|
for (const key in properties)
|
|
parameters.push(key + "=" + encodeURIComponent(properties[key]));
|
|
// document.URL
|
|
let callback = document.URL;
|
|
if (document.location.search.length == 0)
|
|
callback += "?" + parameters.join("&");
|
|
else
|
|
callback += "&" + parameters.join("&");
|
|
return "https://" + this.serverConnection._remote_address.host + ":" + this.serverConnection._remote_address.port + "/?forward_url=" + encodeURIComponent(callback);
|
|
}
|
|
handleDisconnect(type, data = {}) {
|
|
let auto_reconnect = false;
|
|
switch (type) {
|
|
case DisconnectReason.REQUESTED:
|
|
break;
|
|
case DisconnectReason.CONNECT_FAILURE:
|
|
if (this._reconnect_attempt) {
|
|
auto_reconnect = true;
|
|
chat.serverChat().appendError(_translations.mkYBZI51 || (_translations.mkYBZI51 = tr("Connect failed")));
|
|
break;
|
|
}
|
|
console.error(_translations.i13Qq5lP || (_translations.i13Qq5lP = tr("Could not connect to remote host! Exception: %o")), data);
|
|
if (native_client) {
|
|
createErrorModal(_translations.cVoTk97h || (_translations.cVoTk97h = tr("Could not connect")), _translations.KCk709tI || (_translations.KCk709tI = tr("Could not connect to remote host (Connection refused)"))).open();
|
|
}
|
|
else {
|
|
//TODO tr
|
|
createErrorModal(_translations.mq0BoYHj || (_translations.mq0BoYHj = tr("Could not connect")), "Could not connect to remote host (Connection refused)<br>" +
|
|
"If you're sure that the remote host is up, than you may not allow unsigned certificates.<br>" +
|
|
"Click <a href='" + this.certAcceptUrl() + "'>here</a> to accept the remote certificate").open();
|
|
}
|
|
sound.play(Sound.CONNECTION_REFUSED);
|
|
break;
|
|
case DisconnectReason.HANDSHAKE_FAILED:
|
|
//TODO sound
|
|
console.error(_translations.wCe7uH8c || (_translations.wCe7uH8c = tr("Failed to process handshake: %o")), data);
|
|
createErrorModal(_translations.Jx6FIucL || (_translations.Jx6FIucL = tr("Could not connect")), (_translations.ckq4sOQG || (_translations.ckq4sOQG = tr("Failed to process handshake: "))) + data).open();
|
|
break;
|
|
case DisconnectReason.CONNECTION_CLOSED:
|
|
console.error(_translations.CpO5hsYt || (_translations.CpO5hsYt = tr("Lost connection to remote server!")));
|
|
createErrorModal(_translations.gQT1woZd || (_translations.gQT1woZd = tr("Connection closed")), _translations.d4MTpRCT || (_translations.d4MTpRCT = tr("The connection was closed by remote host"))).open();
|
|
sound.play(Sound.CONNECTION_DISCONNECTED);
|
|
auto_reconnect = true;
|
|
break;
|
|
case DisconnectReason.CONNECTION_PING_TIMEOUT:
|
|
console.error(_translations.JT_pws6H || (_translations.JT_pws6H = tr("Connection ping timeout")));
|
|
sound.play(Sound.CONNECTION_DISCONNECTED_TIMEOUT);
|
|
createErrorModal(_translations.rUpUHlzi || (_translations.rUpUHlzi = tr("Connection lost")), _translations._lZjyLc0 || (_translations._lZjyLc0 = tr("Lost connection to remote host (Ping timeout)<br>Even possible?"))).open();
|
|
break;
|
|
case DisconnectReason.SERVER_CLOSED:
|
|
chat.serverChat().appendError(_translations.NeJK3Ye8 || (_translations.NeJK3Ye8 = tr("Server closed ({0})")), data.reasonmsg);
|
|
createErrorModal(_translations.PsDVUZ4O || (_translations.PsDVUZ4O = tr("Server closed")), "The server is closed.<br>" + //TODO tr
|
|
"Reason: " + data.reasonmsg).open();
|
|
sound.play(Sound.CONNECTION_DISCONNECTED);
|
|
auto_reconnect = true;
|
|
break;
|
|
case DisconnectReason.SERVER_REQUIRES_PASSWORD:
|
|
chat.serverChat().appendError(_translations.k9_p6t0P || (_translations.k9_p6t0P = tr("Server requires password")));
|
|
createInputModal(_translations.vgqAaBSb || (_translations.vgqAaBSb = tr("Server password")), _translations.nYEz_XI9 || (_translations.nYEz_XI9 = tr("Enter server password:")), password => password.length != 0, password => {
|
|
if (!(typeof password === "string"))
|
|
return;
|
|
this.startConnection(this.serverConnection._remote_address.host + ":" + this.serverConnection._remote_address.port, this.serverConnection._handshakeHandler.profile, this.serverConnection._handshakeHandler.name, { password: password, hashed: false });
|
|
}).open();
|
|
break;
|
|
case DisconnectReason.CLIENT_KICKED:
|
|
chat.serverChat().appendError(_translations.Lq3w511A || (_translations.Lq3w511A = tr("You got kicked from the server by {0}{1}")), ClientEntry.chatTag(data["invokerid"], data["invokername"], data["invokeruid"]), data["reasonmsg"] ? " (" + data["reasonmsg"] + ")" : "");
|
|
sound.play(Sound.SERVER_KICKED);
|
|
auto_reconnect = true;
|
|
break;
|
|
case DisconnectReason.CLIENT_BANNED:
|
|
chat.serverChat().appendError(_translations.tqIlSIVg || (_translations.tqIlSIVg = tr("You got banned from the server by {0}{1}")), ClientEntry.chatTag(data["invokerid"], data["invokername"], data["invokeruid"]), data["reasonmsg"] ? " (" + data["reasonmsg"] + ")" : "");
|
|
sound.play(Sound.CONNECTION_BANNED); //TODO findout if it was a disconnect or a connect refuse
|
|
break;
|
|
default:
|
|
console.error(_translations.rLg_S2Tb || (_translations.rLg_S2Tb = tr("Got uncaught disconnect!")));
|
|
console.error(_translations.AwKnUotx || (_translations.AwKnUotx = tr("Type: %o Data:")), type);
|
|
console.error(data);
|
|
break;
|
|
}
|
|
this.channelTree.reset();
|
|
this.voiceConnection.dropSession();
|
|
if (this.serverConnection)
|
|
this.serverConnection.disconnect();
|
|
this.controlBar.update_connection_state();
|
|
this.selectInfo.setCurrentSelected(null);
|
|
this.selectInfo.update_banner();
|
|
if (auto_reconnect) {
|
|
if (!this.serverConnection) {
|
|
console.log(_translations.bMtuaii5 || (_translations.bMtuaii5 = tr("Allowed to auto reconnect but cant reconnect because we dont have any information left...")));
|
|
return;
|
|
}
|
|
chat.serverChat().appendMessage(_translations.uS396luz || (_translations.uS396luz = tr("Reconnecting in 5 seconds")));
|
|
console.log(_translations.dDHTCdwB || (_translations.dDHTCdwB = tr("Allowed to auto reconnect. Reconnecting in 5000ms")));
|
|
const server_address = this.serverConnection._remote_address;
|
|
const profile = this.serverConnection._handshakeHandler.profile;
|
|
const name = this.serverConnection._handshakeHandler.name;
|
|
const password = this.serverConnection._handshakeHandler.server_password;
|
|
this._reconnect_timer = setTimeout(() => {
|
|
this._reconnect_timer = undefined;
|
|
chat.serverChat().appendMessage(_translations.BmUuHG2D || (_translations.BmUuHG2D = tr("Reconnecting...")));
|
|
console.log(_translations.Zt58aq4G || (_translations.Zt58aq4G = tr("Reconnecting...")));
|
|
this.startConnection(server_address.host + ":" + server_address.port, profile, name, password ? { password: password, hashed: true } : undefined);
|
|
this._reconnect_attempt = true;
|
|
}, 5000);
|
|
}
|
|
}
|
|
cancel_reconnect() {
|
|
if (this._reconnect_timer) {
|
|
chat.serverChat().appendMessage(_translations.AWIMAHNY || (_translations.AWIMAHNY = tr("Reconnect canceled")));
|
|
clearTimeout(this._reconnect_timer);
|
|
this._reconnect_timer = undefined;
|
|
}
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["f2b04bedfeb84a7179b0b6218f04ced236c258941a594c1d99341a91a2ea7311"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["f2b04bedfeb84a7179b0b6218f04ced236c258941a594c1d99341a91a2ea7311"] = "f2b04bedfeb84a7179b0b6218f04ced236c258941a594c1d99341a91a2ea7311";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "y8J0eI9A", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (52,23)" }, { name: "hc7aVYby", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (70,27)" }, { name: "hqRdxWxT", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (96,22)" }, { name: "dRSVSPXL", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (103,45)" }, { name: "NT5S_zSi", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (183,27)" }, { name: "LO41aNOW", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (202,27)" }, { name: "c90b64RT", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (352,35)" }, { name: "XS1yfMFG", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (353,51)" }, { name: "DtVBEPYe", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (374,31)" }, { name: "z_jAHQFu", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (375,47)" }, { name: "tNuA8Hvx", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (401,27)" }, { name: "b0o29_VA", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (414,31)" }, { name: "AI0C0oqC", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (416,31)" }, { name: "f9lF4foN", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (425,31)" }, { name: "FXXPuv5A", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (452,21)" }, { name: "H1BS6cr_", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (499,35)" }, { name: "FA4tiZqm", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (500,51)" }, { name: "ynLLTaB0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (528,31)" }, { name: "kQSaQY_Z", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (529,47)" }, { name: "D7ibedPu", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (551,31)" }, { name: "e2jUF1F6", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (566,35)" }, { name: "yZ0tGu8j", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (578,31)" }, { name: "u5eqNg06", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/FileManager.ts (580,68)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="client.ts" />
|
|
/// <reference path="connection/ConnectionBase.ts" />
|
|
class FileEntry {
|
|
}
|
|
class FileListRequest {
|
|
}
|
|
class DownloadFileTransfer {
|
|
constructor(handle, id) {
|
|
this.currentSize = 0;
|
|
this.on_start = () => { };
|
|
this.on_complete = () => { };
|
|
this.on_fail = (_) => { };
|
|
this.on_data = (_) => { };
|
|
this.transferId = id;
|
|
this._handle = handle;
|
|
}
|
|
startTransfer() {
|
|
if (!this.remoteHost || !this.remotePort || !this.transferKey || !this.totalSize) {
|
|
this.on_fail("Missing data!");
|
|
return;
|
|
}
|
|
console.debug(_translations.y8J0eI9A || (_translations.y8J0eI9A = tr("Create new file download to %s:%s (Key: %s, Expect %d bytes)")), this.remoteHost, this.remotePort, this.transferId, this.totalSize);
|
|
this._active = true;
|
|
this._socket = new WebSocket("wss://" + this.remoteHost + ":" + this.remotePort);
|
|
this._socket.onopen = this.onOpen.bind(this);
|
|
this._socket.onclose = this.onClose.bind(this);
|
|
this._socket.onmessage = this.onMessage.bind(this);
|
|
this._socket.onerror = this.onError.bind(this);
|
|
}
|
|
onOpen() {
|
|
if (!this._active)
|
|
return;
|
|
this._socket.send(this.transferKey);
|
|
this.on_start();
|
|
}
|
|
onMessage(data) {
|
|
if (!this._active) {
|
|
console.error(_translations.hc7aVYby || (_translations.hc7aVYby = tr("Got data, but socket closed?")));
|
|
return;
|
|
}
|
|
this._parseActive = true;
|
|
let fileReader = new FileReader();
|
|
fileReader.onload = (event) => {
|
|
this.onBinaryData(new Uint8Array(event.target.result));
|
|
//if(this._socket.readyState != WebSocket.OPEN && !this._succeed) this.on_fail("unexpected close");
|
|
this._parseActive = false;
|
|
};
|
|
fileReader.readAsArrayBuffer(data.data);
|
|
}
|
|
onBinaryData(data) {
|
|
this.currentSize += data.length;
|
|
this.on_data(data);
|
|
if (this.currentSize == this.totalSize) {
|
|
this._succeed = true;
|
|
this.on_complete();
|
|
this.disconnect();
|
|
}
|
|
}
|
|
onError() {
|
|
if (!this._active)
|
|
return;
|
|
this.on_fail(_translations.hqRdxWxT || (_translations.hqRdxWxT = tr("an error occurent")));
|
|
this.disconnect();
|
|
}
|
|
onClose() {
|
|
if (!this._active)
|
|
return;
|
|
if (!this._parseActive)
|
|
this.on_fail(_translations.dRSVSPXL || (_translations.dRSVSPXL = tr("unexpected close (remote closed)")));
|
|
this.disconnect();
|
|
}
|
|
disconnect() {
|
|
this._active = false;
|
|
//this._socket.close();
|
|
}
|
|
}
|
|
class FileManager extends connection.AbstractCommandHandler {
|
|
constructor(client) {
|
|
super(client.serverConnection);
|
|
this.listRequests = [];
|
|
this.pendingDownloadTransfers = [];
|
|
this.downloadCounter = 0;
|
|
this.handle = client;
|
|
this.icons = new IconManager(this);
|
|
this.avatars = new AvatarManager(this);
|
|
this.connection.command_handler_boss().register_handler(this);
|
|
}
|
|
handle_command(command) {
|
|
switch (command.command) {
|
|
case "notifyfilelist":
|
|
this.notifyFileList(command.arguments);
|
|
return true;
|
|
case "notifyfilelistfinished":
|
|
this.notifyFileListFinished(command.arguments);
|
|
return true;
|
|
case "notifystartdownload":
|
|
this.notifyStartDownload(command.arguments);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
/******************************** File list ********************************/
|
|
//TODO multiple requests (same path)
|
|
requestFileList(path, channel, password) {
|
|
const _this = this;
|
|
return new Promise((accept, reject) => {
|
|
let req = new FileListRequest();
|
|
req.path = path;
|
|
req.entries = [];
|
|
req.callback = accept;
|
|
_this.listRequests.push(req);
|
|
_this.handle.serverConnection.send_command("ftgetfilelist", { "path": path, "cid": (channel ? channel.channelId : "0"), "cpw": (password ? password : "") }).then(() => { }).catch(reason => {
|
|
_this.listRequests.remove(req);
|
|
if (reason instanceof CommandResult) {
|
|
if (reason.id == 0x0501) {
|
|
accept([]); //Empty result
|
|
return;
|
|
}
|
|
}
|
|
reject(reason);
|
|
});
|
|
});
|
|
}
|
|
notifyFileList(json) {
|
|
let entry = undefined;
|
|
for (let e of this.listRequests) {
|
|
if (e.path == json[0]["path"]) {
|
|
entry = e;
|
|
break;
|
|
}
|
|
}
|
|
if (!entry) {
|
|
console.error(_translations.NT5S_zSi || (_translations.NT5S_zSi = tr("Invalid file list entry. Path: %s")), json[0]["path"]);
|
|
return;
|
|
}
|
|
for (let e of json)
|
|
entry.entries.push(e);
|
|
}
|
|
notifyFileListFinished(json) {
|
|
let entry = undefined;
|
|
for (let e of this.listRequests) {
|
|
if (e.path == json[0]["path"]) {
|
|
entry = e;
|
|
this.listRequests.remove(e);
|
|
break;
|
|
}
|
|
}
|
|
if (!entry) {
|
|
console.error(_translations.LO41aNOW || (_translations.LO41aNOW = tr("Invalid file list entry finish. Path: ")), json[0]["path"]);
|
|
return;
|
|
}
|
|
entry.callback(entry.entries);
|
|
}
|
|
/******************************** File download ********************************/
|
|
requestFileDownload(path, file, channel, password) {
|
|
const _this = this;
|
|
let transfer = new DownloadFileTransfer(this, this.downloadCounter++);
|
|
this.pendingDownloadTransfers.push(transfer);
|
|
return new Promise((resolve, reject) => {
|
|
transfer["_promiseCallback"] = resolve;
|
|
_this.handle.serverConnection.send_command("ftinitdownload", {
|
|
"path": path,
|
|
"name": file,
|
|
"cid": (channel ? channel.channelId : "0"),
|
|
"cpw": (password ? password : ""),
|
|
"clientftfid": transfer.transferId
|
|
}).catch(reason => {
|
|
_this.pendingDownloadTransfers.remove(transfer);
|
|
reject(reason);
|
|
});
|
|
});
|
|
}
|
|
notifyStartDownload(json) {
|
|
json = json[0];
|
|
let transfer;
|
|
for (let e of this.pendingDownloadTransfers)
|
|
if (e.transferId == json["clientftfid"]) {
|
|
transfer = e;
|
|
break;
|
|
}
|
|
transfer.serverTransferId = json["serverftfid"];
|
|
transfer.transferKey = json["ftkey"];
|
|
transfer.totalSize = json["size"];
|
|
transfer.remotePort = json["port"];
|
|
transfer.remoteHost = (json["ip"] ? json["ip"] : "").replace(/,/g, "");
|
|
if (!transfer.remoteHost || transfer.remoteHost == '0.0.0.0' || transfer.remoteHost == '127.168.0.0')
|
|
transfer.remoteHost = this.handle.serverConnection._remote_address.host;
|
|
transfer["_promiseCallback"](transfer);
|
|
this.pendingDownloadTransfers.remove(transfer);
|
|
}
|
|
}
|
|
class Icon {
|
|
}
|
|
var ImageType;
|
|
(function (ImageType) {
|
|
ImageType[ImageType["UNKNOWN"] = 0] = "UNKNOWN";
|
|
ImageType[ImageType["BITMAP"] = 1] = "BITMAP";
|
|
ImageType[ImageType["PNG"] = 2] = "PNG";
|
|
ImageType[ImageType["GIF"] = 3] = "GIF";
|
|
ImageType[ImageType["SVG"] = 4] = "SVG";
|
|
ImageType[ImageType["JPEG"] = 5] = "JPEG";
|
|
})(ImageType || (ImageType = {}));
|
|
function media_image_type(type) {
|
|
switch (type) {
|
|
case ImageType.BITMAP:
|
|
return "bmp";
|
|
case ImageType.GIF:
|
|
return "gif";
|
|
case ImageType.SVG:
|
|
return "svg+xml";
|
|
case ImageType.JPEG:
|
|
return "jpeg";
|
|
case ImageType.UNKNOWN:
|
|
case ImageType.PNG:
|
|
default:
|
|
return "png";
|
|
}
|
|
}
|
|
function image_type(base64) {
|
|
const bin = atob(base64);
|
|
if (bin.length < 10)
|
|
return ImageType.UNKNOWN;
|
|
if (bin[0] == String.fromCharCode(66) && bin[1] == String.fromCharCode(77)) {
|
|
return ImageType.BITMAP;
|
|
}
|
|
else if (bin.substr(0, 8) == "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a") {
|
|
return ImageType.PNG;
|
|
}
|
|
else if (bin.substr(0, 4) == "\x47\x49\x46\x38" && (bin[4] == '\x37' || bin[4] == '\x39') && bin[5] == '\x61') {
|
|
return ImageType.GIF;
|
|
}
|
|
else if (bin[0] == '\x3c') {
|
|
return ImageType.SVG;
|
|
}
|
|
else if (bin[0] == '\xFF' && bin[1] == '\xd8') {
|
|
return ImageType.JPEG;
|
|
}
|
|
return ImageType.UNKNOWN;
|
|
}
|
|
class IconManager {
|
|
constructor(handle) {
|
|
this.loading_icons = [];
|
|
this.handle = handle;
|
|
}
|
|
iconList() {
|
|
return this.handle.requestFileList("/icons");
|
|
}
|
|
downloadIcon(id) {
|
|
return this.handle.download_file("", "/icon_" + id);
|
|
}
|
|
resolveCached(id) {
|
|
let icon = localStorage.getItem("icon_" + id);
|
|
if (icon) {
|
|
let i = JSON.parse(icon);
|
|
if (i.base64.length > 0) { //TODO timestamp?
|
|
return i;
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
load_finished(id) {
|
|
for (let entry of this.loading_icons)
|
|
if (entry.id == id)
|
|
this.loading_icons.remove(entry);
|
|
}
|
|
loadIcon(id) {
|
|
for (let entry of this.loading_icons)
|
|
if (entry.id == id)
|
|
return entry.promise;
|
|
let promise = new Promise((resolve, reject) => {
|
|
let icon = this.resolveCached(id);
|
|
if (icon) {
|
|
this.load_finished(id);
|
|
resolve(icon);
|
|
return;
|
|
}
|
|
this.downloadIcon(id).then(ft => {
|
|
let array = new Uint8Array(0);
|
|
ft.on_fail = reason => {
|
|
this.load_finished(id);
|
|
console.error(_translations.c90b64RT || (_translations.c90b64RT = tr("Could not download icon %s -> %s")), id, tr(reason));
|
|
chat.serverChat().appendError(_translations.XS1yfMFG || (_translations.XS1yfMFG = tr("Fail to download icon {0}. ({1})")), id, JSON.stringify(reason));
|
|
reject(reason);
|
|
};
|
|
ft.on_start = () => { };
|
|
ft.on_data = (data) => {
|
|
array = concatenate(Uint8Array, array, data);
|
|
};
|
|
ft.on_complete = () => {
|
|
let base64 = btoa(String.fromCharCode.apply(null, array));
|
|
let icon = new Icon();
|
|
icon.base64 = base64;
|
|
icon.id = id;
|
|
icon.name = "icon_" + id;
|
|
localStorage.setItem("icon_" + id, JSON.stringify(icon));
|
|
this.load_finished(id);
|
|
resolve(icon);
|
|
};
|
|
ft.start();
|
|
}).catch(reason => {
|
|
console.error(_translations.DtVBEPYe || (_translations.DtVBEPYe = tr("Error while downloading icon! (%s)")), tr(JSON.stringify(reason)));
|
|
chat.serverChat().appendError(_translations.z_jAHQFu || (_translations.z_jAHQFu = tr("Failed to request download for icon {0}. ({1})")), id, tr(JSON.stringify(reason)));
|
|
reject(reason);
|
|
});
|
|
});
|
|
this.loading_icons.push({ promise: promise, id: id });
|
|
return promise;
|
|
}
|
|
//$("<img width=\"16\" height=\"16\" alt=\"tick\" src=\"data:image/png;base64," + value.base64 + "\">")
|
|
generateTag(id) {
|
|
if (id == 0)
|
|
return $.spawn("div").addClass("icon_empty");
|
|
else if (id < 1000)
|
|
return $.spawn("div").addClass("icon client-group_" + id);
|
|
let tag = $.spawn("div");
|
|
tag.addClass("icon-container icon_empty");
|
|
let img = $.spawn("img");
|
|
img.attr("width", 16).attr("height", 16).attr("alt", "");
|
|
let icon = this.resolveCached(id);
|
|
if (icon) {
|
|
const type = image_type(icon.base64);
|
|
const media = media_image_type(type);
|
|
console.debug(_translations.tNuA8Hvx || (_translations.tNuA8Hvx = tr("Icon has an image type of %o (media: %o)")), type, media);
|
|
img.attr("src", "data:image/" + media + ";base64," + icon.base64);
|
|
tag.append(img).removeClass("icon_empty");
|
|
}
|
|
else {
|
|
img.attr("src", "file://null");
|
|
let loader = $.spawn("div");
|
|
loader.addClass("icon_loading");
|
|
tag.append(loader);
|
|
this.loadIcon(id).then(icon => {
|
|
const type = image_type(icon.base64);
|
|
const media = media_image_type(type);
|
|
console.debug(_translations.b0o29_VA || (_translations.b0o29_VA = tr("Icon has an image type of %o (media: %o)")), type, media);
|
|
img.attr("src", "data:image/" + media + ";base64," + icon.base64);
|
|
console.debug(_translations.AI0C0oqC || (_translations.AI0C0oqC = tr("Icon %o loaded :)")), id);
|
|
img.css("opacity", 0);
|
|
tag.append(img).removeClass("icon_empty");
|
|
loader.animate({ opacity: 0 }, 50, function () {
|
|
$(this).detach();
|
|
img.animate({ opacity: 1 }, 150);
|
|
});
|
|
}).catch(reason => {
|
|
console.error(_translations.f9lF4foN || (_translations.f9lF4foN = tr("Could not load icon %o. Reason: %p")), id, reason);
|
|
loader.removeClass("icon_loading").addClass("icon client-warning").attr("tag", "Could not load icon " + id);
|
|
});
|
|
}
|
|
return tag;
|
|
}
|
|
}
|
|
class Avatar {
|
|
}
|
|
class AvatarManager {
|
|
constructor(handle) {
|
|
this.loading_avatars = [];
|
|
this.loaded_urls = [];
|
|
this.handle = handle;
|
|
}
|
|
downloadAvatar(client) {
|
|
console.log(_translations.FXXPuv5A || (_translations.FXXPuv5A = tr("Downloading avatar %s")), client.avatarId());
|
|
return this.handle.download_file("", "/avatar_" + client.avatarId());
|
|
}
|
|
resolveCached(client) {
|
|
let avatar = localStorage.getItem("avatar_" + client.properties.client_unique_identifier);
|
|
if (avatar) {
|
|
let i = JSON.parse(avatar);
|
|
//TODO timestamp?
|
|
if (i.avatarId != client.properties.client_flag_avatar)
|
|
return undefined;
|
|
if (i.base64) {
|
|
if (i.base64.length > 0)
|
|
return i;
|
|
else
|
|
i.base64 = undefined;
|
|
}
|
|
if (i.url) {
|
|
for (let url of this.loaded_urls)
|
|
if (url == i.url)
|
|
return i;
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
load_finished(name) {
|
|
for (let entry of this.loading_avatars)
|
|
if (entry.name == name)
|
|
this.loading_avatars.remove(entry);
|
|
}
|
|
loadAvatar(client) {
|
|
let name = client.avatarId();
|
|
for (let promise of this.loading_avatars)
|
|
if (promise.name == name)
|
|
return promise.promise;
|
|
let promise = new Promise((resolve, reject) => {
|
|
let avatar = this.resolveCached(client);
|
|
if (avatar) {
|
|
this.load_finished(name);
|
|
resolve(avatar);
|
|
return;
|
|
}
|
|
this.downloadAvatar(client).then(ft => {
|
|
let array = new Uint8Array(0);
|
|
ft.on_fail = reason => {
|
|
this.load_finished(name);
|
|
console.error(_translations.H1BS6cr_ || (_translations.H1BS6cr_ = tr("Could not download avatar %o -> %s")), client.properties.client_flag_avatar, reason);
|
|
chat.serverChat().appendError(_translations.FA4tiZqm || (_translations.FA4tiZqm = tr("Fail to download avatar for {0}. ({1})")), client.clientNickName(), JSON.stringify(reason));
|
|
reject(reason);
|
|
};
|
|
ft.on_start = () => { };
|
|
ft.on_data = (data) => {
|
|
array = concatenate(Uint8Array, array, data);
|
|
};
|
|
ft.on_complete = () => {
|
|
let avatar = new Avatar();
|
|
if (array.length >= 1024 * 1024) {
|
|
let blob_image = new Blob([array]);
|
|
avatar.url = URL.createObjectURL(blob_image);
|
|
avatar.blob = blob_image;
|
|
this.loaded_urls.push(avatar.url);
|
|
}
|
|
else {
|
|
avatar.base64 = btoa(String.fromCharCode.apply(null, array));
|
|
}
|
|
avatar.clientUid = client.clientUid();
|
|
avatar.avatarId = client.properties.client_flag_avatar;
|
|
localStorage.setItem("avatar_" + client.properties.client_unique_identifier, JSON.stringify(avatar));
|
|
this.load_finished(name);
|
|
resolve(avatar);
|
|
};
|
|
ft.start();
|
|
}).catch(reason => {
|
|
this.load_finished(name);
|
|
console.error(_translations.ynLLTaB0 || (_translations.ynLLTaB0 = tr("Error while downloading avatar! (%s)")), JSON.stringify(reason));
|
|
chat.serverChat().appendError(_translations.kQSaQY_Z || (_translations.kQSaQY_Z = tr("Failed to request avatar download for {0}. ({1})")), client.clientNickName(), JSON.stringify(reason));
|
|
reject(reason);
|
|
});
|
|
});
|
|
this.loading_avatars.push({ promise: promise, name: name });
|
|
return promise;
|
|
}
|
|
generateTag(client) {
|
|
let tag = $.spawn("div");
|
|
let img = $.spawn("img");
|
|
img.attr("alt", "");
|
|
let avatar = this.resolveCached(client);
|
|
if (avatar) {
|
|
if (avatar.url)
|
|
img.attr("src", avatar.url);
|
|
else {
|
|
const type = image_type(avatar.base64);
|
|
const media = media_image_type(type);
|
|
console.debug(_translations.D7ibedPu || (_translations.D7ibedPu = tr("avatar has an image type of %o (media: %o)")), type, media);
|
|
img.attr("src", "data:image/" + media + ";base64," + avatar.base64);
|
|
}
|
|
tag.append(img);
|
|
}
|
|
else {
|
|
let loader = $.spawn("img");
|
|
loader.attr("src", "img/loading_image.svg").css("width", "75%");
|
|
tag.append(loader);
|
|
this.loadAvatar(client).then(avatar => {
|
|
if (avatar.url)
|
|
img.attr("src", avatar.url);
|
|
else {
|
|
const type = image_type(avatar.base64);
|
|
const media = media_image_type(type);
|
|
console.debug(_translations.e2jUF1F6 || (_translations.e2jUF1F6 = tr("Avatar has an image type of %o (media: %o)")), type, media);
|
|
img.attr("src", "data:image/" + media + ";base64," + avatar.base64);
|
|
}
|
|
console.debug("Avatar " + client.clientNickName() + " loaded :)");
|
|
img.css("opacity", 0);
|
|
tag.append(img);
|
|
loader.animate({ opacity: 0 }, 50, function () {
|
|
$(this).detach();
|
|
img.animate({ opacity: 1 }, 150);
|
|
});
|
|
}).catch(reason => {
|
|
console.error(_translations.yZ0tGu8j || (_translations.yZ0tGu8j = tr("Could not load avatar for %s. Reason: %s")), client.clientNickName(), reason);
|
|
//TODO Broken image
|
|
loader.addClass("icon client-warning").attr("tag", (_translations.u5eqNg06 || (_translations.u5eqNg06 = tr("Could not load avatar "))) + client.clientNickName());
|
|
});
|
|
}
|
|
return tag;
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["571623c0409102f319b482787637afa231f4d6ca51d374eba8c1e5d7c07fcd45"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["571623c0409102f319b482787637afa231f4d6ca51d374eba8c1e5d7c07fcd45"] = "571623c0409102f319b482787637afa231f4d6ca51d374eba8c1e5d7c07fcd45";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "xpLU9Tla", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/PPTListener.ts (41,31)" }, { name: "_szPq66H", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/PPTListener.ts (43,31)" }, { name: "jKer8fsK", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/PPTListener.ts (45,31)" }, { name: "wVOUWzw9", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/PPTListener.ts (47,31)" }, { name: "PGifhkad", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/PPTListener.ts (49,58)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var ppt;
|
|
(function (ppt) {
|
|
let EventType;
|
|
(function (EventType) {
|
|
EventType[EventType["KEY_PRESS"] = 0] = "KEY_PRESS";
|
|
EventType[EventType["KEY_RELEASE"] = 1] = "KEY_RELEASE";
|
|
EventType[EventType["KEY_TYPED"] = 2] = "KEY_TYPED";
|
|
})(EventType = ppt.EventType || (ppt.EventType = {}));
|
|
let SpecialKey;
|
|
(function (SpecialKey) {
|
|
SpecialKey[SpecialKey["CTRL"] = 0] = "CTRL";
|
|
SpecialKey[SpecialKey["WINDOWS"] = 1] = "WINDOWS";
|
|
SpecialKey[SpecialKey["SHIFT"] = 2] = "SHIFT";
|
|
SpecialKey[SpecialKey["ALT"] = 3] = "ALT";
|
|
})(SpecialKey = ppt.SpecialKey || (ppt.SpecialKey = {}));
|
|
function key_description(key) {
|
|
let result = "";
|
|
if (key.key_shift)
|
|
result += " + " + (_translations.xpLU9Tla || (_translations.xpLU9Tla = tr("Shift")));
|
|
if (key.key_alt)
|
|
result += " + " + (_translations._szPq66H || (_translations._szPq66H = tr("Alt")));
|
|
if (key.key_ctrl)
|
|
result += " + " + (_translations.jKer8fsK || (_translations.jKer8fsK = tr("CTRL")));
|
|
if (key.key_windows)
|
|
result += " + " + (_translations.wVOUWzw9 || (_translations.wVOUWzw9 = tr("Win")));
|
|
result += " + " + (key.key_code ? key.key_code : _translations.PGifhkad || (_translations.PGifhkad = tr("unset")));
|
|
return result.substr(3);
|
|
}
|
|
ppt.key_description = key_description;
|
|
/*
|
|
export declare function initialize() : Promise<void>;
|
|
export declare function finalize(); // most the times not really required
|
|
|
|
export declare function register_key_listener(listener: (_: KeyEvent) => any);
|
|
export declare function unregister_key_listener(listener: (_: KeyEvent) => any);
|
|
|
|
export declare function register_key_hook(hook: KeyHook);
|
|
export declare function unregister_key_hook(hook: KeyHook);
|
|
|
|
export declare function key_pressed(code: string | SpecialKey) : boolean;
|
|
*/
|
|
})(ppt || (ppt = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["e54bd5e9d10abe8513ba0439aa8300d50df4deef8e354ea912eb1d498e7ca4e5"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["e54bd5e9d10abe8513ba0439aa8300d50df4deef8e354ea912eb1d498e7ca4e5"] = "e54bd5e9d10abe8513ba0439aa8300d50df4deef8e354ea912eb1d498e7ca4e5";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var bookmarks;
|
|
(function (bookmarks_1) {
|
|
function guid() {
|
|
function s4() {
|
|
return Math
|
|
.floor((1 + Math.random()) * 0x10000)
|
|
.toString(16)
|
|
.substring(1);
|
|
}
|
|
return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
|
|
}
|
|
let BookmarkType;
|
|
(function (BookmarkType) {
|
|
BookmarkType[BookmarkType["ENTRY"] = 0] = "ENTRY";
|
|
BookmarkType[BookmarkType["DIRECTORY"] = 1] = "DIRECTORY";
|
|
})(BookmarkType = bookmarks_1.BookmarkType || (bookmarks_1.BookmarkType = {}));
|
|
let _bookmark_config;
|
|
function bookmark_config() {
|
|
if (_bookmark_config)
|
|
return _bookmark_config;
|
|
let bookmark_json = localStorage.getItem("bookmarks");
|
|
let bookmarks = JSON.parse(bookmark_json) || {};
|
|
_bookmark_config = bookmarks;
|
|
_bookmark_config.root_bookmark = _bookmark_config.root_bookmark || { content: [], display_name: "root", type: BookmarkType.DIRECTORY };
|
|
if (!_bookmark_config.default_added) {
|
|
_bookmark_config.default_added = true;
|
|
create_bookmark("TeaSpeak official Test-Server", _bookmark_config.root_bookmark, {
|
|
server_address: "ts.teaspeak.de",
|
|
server_port: 9987
|
|
}, "Another TeaSpeak user");
|
|
save_config();
|
|
}
|
|
return _bookmark_config;
|
|
}
|
|
function save_config() {
|
|
localStorage.setItem("bookmarks", JSON.stringify(bookmark_config()));
|
|
}
|
|
function bookmarks() {
|
|
return bookmark_config().root_bookmark;
|
|
}
|
|
bookmarks_1.bookmarks = bookmarks;
|
|
function find_bookmark_recursive(parent, uuid) {
|
|
for (const entry of parent.content) {
|
|
if (entry.unique_id == uuid)
|
|
return entry;
|
|
if (entry.type == BookmarkType.DIRECTORY) {
|
|
const result = find_bookmark_recursive(entry, uuid);
|
|
if (result)
|
|
return result;
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
function find_bookmark(uuid) {
|
|
return find_bookmark_recursive(bookmarks(), uuid);
|
|
}
|
|
bookmarks_1.find_bookmark = find_bookmark;
|
|
function parent_bookmark(bookmark) {
|
|
const books = [bookmarks()];
|
|
while (!books.length) {
|
|
const directory = books.pop_front();
|
|
if (directory.type == BookmarkType.DIRECTORY) {
|
|
const cast = directory;
|
|
if (cast.content.indexOf(bookmark) != -1)
|
|
return cast;
|
|
books.push(...cast.content);
|
|
}
|
|
}
|
|
return bookmarks();
|
|
}
|
|
bookmarks_1.parent_bookmark = parent_bookmark;
|
|
function create_bookmark(display_name, directory, server_properties, nickname) {
|
|
const bookmark = {
|
|
display_name: display_name,
|
|
server_properties: server_properties,
|
|
nickname: nickname,
|
|
type: BookmarkType.ENTRY,
|
|
connect_profile: "default",
|
|
unique_id: guid()
|
|
};
|
|
directory.content.push(bookmark);
|
|
return bookmark;
|
|
}
|
|
bookmarks_1.create_bookmark = create_bookmark;
|
|
function create_bookmark_directory(parent, name) {
|
|
const bookmark = {
|
|
type: BookmarkType.DIRECTORY,
|
|
display_name: name,
|
|
content: [],
|
|
unique_id: guid()
|
|
};
|
|
parent.content.push(bookmark);
|
|
return bookmark;
|
|
}
|
|
bookmarks_1.create_bookmark_directory = create_bookmark_directory;
|
|
//TODO test if the new parent is within the old bookmark
|
|
function change_directory(parent, bookmark) {
|
|
delete_bookmark(bookmark);
|
|
parent.content.push(bookmark);
|
|
}
|
|
bookmarks_1.change_directory = change_directory;
|
|
function save_bookmark(bookmark) {
|
|
save_config(); /* nvm we dont give a fuck... saving everything */
|
|
}
|
|
bookmarks_1.save_bookmark = save_bookmark;
|
|
function delete_bookmark_recursive(parent, bookmark) {
|
|
const index = parent.content.indexOf(bookmark);
|
|
if (index != -1)
|
|
parent.content.remove(bookmark);
|
|
else
|
|
for (const entry of parent.content)
|
|
if (entry.type == BookmarkType.DIRECTORY)
|
|
delete_bookmark_recursive(entry, bookmark);
|
|
}
|
|
function delete_bookmark(bookmark) {
|
|
delete_bookmark_recursive(bookmarks(), bookmark);
|
|
}
|
|
bookmarks_1.delete_bookmark = delete_bookmark;
|
|
})(bookmarks || (bookmarks = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["b908bdb2f5592807ec050e926a55d436c86d4c5313c4b46534504e355d917ef2"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["b908bdb2f5592807ec050e926a55d436c86d4c5313c4b46534504e355d917ef2"] = "b908bdb2f5592807ec050e926a55d436c86d4c5313c4b46534504e355d917ef2";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "o9aqigfL", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/chat.ts (68,30)" }, { name: "_OL5avmw", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/chat.ts (73,25)" }, { name: "Ugzovx8b", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/chat.ts (231,23)" }, { name: "DBMAxrab", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/chat.ts (241,27)" }, { name: "xhzWf49Y", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/chat.ts (251,23)" }, { name: "S7KM8qoZ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/chat.ts (274,21)" }, { name: "aiwUHpzW", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/chat.ts (283,21)" }, { name: "MGIa7CAP", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/chat.ts (354,47)" }, { name: "EfA3bz33", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/chat.ts (361,49)" }, { name: "sZZ04N8U", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/chat.ts (362,31)" }, { name: "XY0rgaAe", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/chat.ts (365,34)" }, { name: "YUpKiux0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/chat.ts (369,48)" }, { name: "wtDGBoN6", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/chat.ts (374,50)" }, { name: "AqmT7vNM", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/chat.ts (375,31)" }, { name: "CoEg7HKO", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/chat.ts (378,35)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var ChatType;
|
|
(function (ChatType) {
|
|
ChatType[ChatType["GENERAL"] = 0] = "GENERAL";
|
|
ChatType[ChatType["SERVER"] = 1] = "SERVER";
|
|
ChatType[ChatType["CHANNEL"] = 2] = "CHANNEL";
|
|
ChatType[ChatType["CLIENT"] = 3] = "CLIENT";
|
|
})(ChatType || (ChatType = {}));
|
|
var MessageHelper;
|
|
(function (MessageHelper) {
|
|
function htmlEscape(message) {
|
|
const div = document.createElement('div');
|
|
div.innerText = message;
|
|
message = div.innerHTML;
|
|
return message.replace(/ /g, ' ').split(/<br>/);
|
|
}
|
|
MessageHelper.htmlEscape = htmlEscape;
|
|
function formatElement(object, escape_html = true) {
|
|
if ($.isArray(object)) {
|
|
let result = [];
|
|
for (let element of object)
|
|
result.push(...formatElement(element, escape_html));
|
|
return result;
|
|
}
|
|
else if (typeof (object) == "string") {
|
|
if (object.length == 0)
|
|
return [];
|
|
return escape_html ?
|
|
htmlEscape(object).map((entry, idx, array) => $.spawn("a").css("display", (idx == 0 || idx + 1 == array.length ? "inline" : "") + "block").html(entry == "" && idx != 0 ? " " : entry)) :
|
|
[$.spawn("div").css("display", "inline-block").html(object)];
|
|
}
|
|
else if (typeof (object) === "object") {
|
|
if (object instanceof $)
|
|
return [object];
|
|
return formatElement("<unknwon object>");
|
|
}
|
|
else if (typeof (object) === "function")
|
|
return formatElement(object(), escape_html);
|
|
else if (typeof (object) === "undefined")
|
|
return formatElement("<undefined>");
|
|
else if (typeof (object) === "number")
|
|
return [$.spawn("a").text(object)];
|
|
return formatElement("<unknown object type " + typeof object + ">");
|
|
}
|
|
MessageHelper.formatElement = formatElement;
|
|
function formatMessage(pattern, ...objects) {
|
|
let begin = 0, found = 0;
|
|
let result = [];
|
|
do {
|
|
found = pattern.indexOf('{', found);
|
|
if (found == -1 || pattern.length <= found + 1) {
|
|
result.push(...formatElement(pattern.substr(begin)));
|
|
break;
|
|
}
|
|
if (found > 0 && pattern[found - 1] == '\\') {
|
|
//TODO remove the escape!
|
|
found++;
|
|
continue;
|
|
}
|
|
result.push(...formatElement(pattern.substr(begin, found - begin))); //Append the text
|
|
let number;
|
|
let offset = 0;
|
|
while ("0123456789".includes(pattern[found + 1 + offset]))
|
|
offset++;
|
|
number = parseInt(offset > 0 ? pattern.substr(found + 1, offset) : "0");
|
|
if (pattern[found + offset + 1] != '}') {
|
|
found++;
|
|
continue;
|
|
}
|
|
if (objects.length < number)
|
|
console.warn(_translations.o9aqigfL || (_translations.o9aqigfL = tr("Message to format contains invalid index (%o)")), number);
|
|
result.push(...formatElement(objects[number]));
|
|
found = found + 1 + offset;
|
|
begin = found + 1;
|
|
console.log(_translations._OL5avmw || (_translations._OL5avmw = tr("Offset: %d Number: %d")), offset, number);
|
|
} while (found++);
|
|
return result;
|
|
}
|
|
MessageHelper.formatMessage = formatMessage;
|
|
function bbcode_chat(message) {
|
|
let result = XBBCODE.process({
|
|
text: message,
|
|
escapeHtml: true,
|
|
addInLineBreaks: false,
|
|
/* TODO make this configurable and allow IMG */
|
|
tag_whitelist: [
|
|
"b",
|
|
"i",
|
|
"u",
|
|
"color",
|
|
"url"
|
|
]
|
|
});
|
|
if (result.error) {
|
|
console.log("BBCode parse error: %o", result.errorQueue);
|
|
return formatElement(message);
|
|
}
|
|
return result.html.split("\n").map((entry, idx, array) => $.spawn("a").css("display", (idx == 0 ? "inline" : "") + "block").html(entry == "" && idx != 0 ? " " : entry));
|
|
}
|
|
MessageHelper.bbcode_chat = bbcode_chat;
|
|
})(MessageHelper || (MessageHelper = {}));
|
|
class ChatMessage {
|
|
constructor(message) {
|
|
this.date = new Date();
|
|
this.message = message;
|
|
}
|
|
num(num) {
|
|
let str = num.toString();
|
|
while (str.length < 2)
|
|
str = '0' + str;
|
|
return str;
|
|
}
|
|
get htmlTag() {
|
|
if (this._htmlTag)
|
|
return this._htmlTag;
|
|
let tag = $.spawn("div");
|
|
tag.addClass("message");
|
|
let dateTag = $.spawn("div");
|
|
dateTag.text("<" + this.num(this.date.getUTCHours()) + ":" + this.num(this.date.getUTCMinutes()) + ":" + this.num(this.date.getUTCSeconds()) + "> ");
|
|
dateTag.css("margin-right", "4px");
|
|
dateTag.css("color", "dodgerblue");
|
|
this._htmlTag = tag;
|
|
tag.append(dateTag);
|
|
this.message.forEach(e => e.appendTo(tag));
|
|
tag.hide();
|
|
return tag;
|
|
}
|
|
}
|
|
class ChatEntry {
|
|
constructor(handle, type, key) {
|
|
this.handle = handle;
|
|
this.type = type;
|
|
this.key = key;
|
|
this._name = key;
|
|
this.history = [];
|
|
this.onClose = function () { return true; };
|
|
}
|
|
appendError(message, ...args) {
|
|
let entries = MessageHelper.formatMessage(message, ...args);
|
|
entries.forEach(e => e.css("color", "red"));
|
|
this.pushChatMessage(new ChatMessage(entries));
|
|
}
|
|
appendMessage(message, fmt = true, ...args) {
|
|
this.pushChatMessage(new ChatMessage(MessageHelper.formatMessage(message, ...args)));
|
|
}
|
|
pushChatMessage(entry) {
|
|
this.history.push(entry);
|
|
while (this.history.length > 100) {
|
|
let elm = this.history.pop_front();
|
|
elm.htmlTag.animate({ opacity: 0 }, 200, function () {
|
|
$(this).detach();
|
|
});
|
|
}
|
|
if (this.handle.activeChat === this) {
|
|
let box = $(this.handle.htmlTag).find(".messages");
|
|
let mbox = $(this.handle.htmlTag).find(".message_box");
|
|
let bottom = box.scrollTop() + box.height() + 1 >= mbox.height();
|
|
mbox.append(entry.htmlTag);
|
|
entry.htmlTag.show().css("opacity", "0").animate({ opacity: 1 }, 100);
|
|
if (bottom)
|
|
box.scrollTop(mbox.height());
|
|
}
|
|
else {
|
|
this.unread = true;
|
|
}
|
|
}
|
|
displayHistory() {
|
|
this.unread = false;
|
|
let box = $(this.handle.htmlTag).find(".messages");
|
|
let mbox = $(this.handle.htmlTag).find(".message_box");
|
|
mbox.empty();
|
|
for (let e of this.history) {
|
|
mbox.append(e.htmlTag);
|
|
if (e.htmlTag.is(":hidden"))
|
|
e.htmlTag.show();
|
|
}
|
|
box.scrollTop(mbox.height());
|
|
}
|
|
get htmlTag() {
|
|
if (this._htmlTag)
|
|
return this._htmlTag;
|
|
let tag = $.spawn("div");
|
|
tag.addClass("chat");
|
|
tag.append("<div class=\"chatIcon icon " + this.chatIcon() + "\"></div>");
|
|
tag.append("<a class='name'>" + this._name + "</a>");
|
|
let closeTag = $.spawn("div");
|
|
closeTag.addClass("btn_close icon client-tab_close_button");
|
|
if (!this._closeable)
|
|
closeTag.hide();
|
|
tag.append(closeTag);
|
|
const _this = this;
|
|
tag.click(function () {
|
|
_this.handle.activeChat = _this;
|
|
});
|
|
tag.on("contextmenu", function (e) {
|
|
e.preventDefault();
|
|
let actions = [];
|
|
actions.push({
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "",
|
|
name: _translations.Ugzovx8b || (_translations.Ugzovx8b = tr("Clear")),
|
|
callback: () => {
|
|
_this.history = [];
|
|
_this.displayHistory();
|
|
}
|
|
});
|
|
if (_this.closeable) {
|
|
actions.push({
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-tab_close_button",
|
|
name: _translations.DBMAxrab || (_translations.DBMAxrab = tr("Close")),
|
|
callback: () => {
|
|
chat.deleteChat(_this);
|
|
}
|
|
});
|
|
}
|
|
actions.push({
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-tab_close_button",
|
|
name: _translations.xhzWf49Y || (_translations.xhzWf49Y = tr("Close all private tabs")),
|
|
callback: () => {
|
|
//TODO Implement this?
|
|
}
|
|
});
|
|
spawn_context_menu(e.pageX, e.pageY, ...actions);
|
|
});
|
|
closeTag.click(function () {
|
|
if ($.isFunction(_this.onClose) && !_this.onClose())
|
|
return;
|
|
_this.handle.deleteChat(_this);
|
|
});
|
|
this._htmlTag = tag;
|
|
return tag;
|
|
}
|
|
focus() {
|
|
this.handle.activeChat = this;
|
|
this.handle.htmlTag.find(".input_box").focus();
|
|
}
|
|
set name(newName) {
|
|
console.log(_translations.S7KM8qoZ || (_translations.S7KM8qoZ = tr("Change name!")));
|
|
this._name = newName;
|
|
this.htmlTag.find(".name").text(this._name);
|
|
}
|
|
set closeable(flag) {
|
|
if (this._closeable == flag)
|
|
return;
|
|
this._closeable = flag;
|
|
console.log((_translations.aiwUHpzW || (_translations.aiwUHpzW = tr("Set closeable: "))) + this._closeable);
|
|
if (flag)
|
|
this.htmlTag.find(".btn_close").show();
|
|
else
|
|
this.htmlTag.find(".btn_close").hide();
|
|
}
|
|
set unread(flag) {
|
|
if (this._unread == flag)
|
|
return;
|
|
this._unread = flag;
|
|
this.htmlTag.find(".chatIcon").attr("class", "chatIcon icon " + this.chatIcon());
|
|
if (flag) {
|
|
this.htmlTag.find(".name").css("color", "blue");
|
|
}
|
|
else {
|
|
this.htmlTag.find(".name").css("color", "black");
|
|
}
|
|
}
|
|
chatIcon() {
|
|
if (this._unread) {
|
|
switch (this.type) {
|
|
case ChatType.CLIENT:
|
|
return "client-new_chat";
|
|
}
|
|
}
|
|
switch (this.type) {
|
|
case ChatType.SERVER:
|
|
return "client-server_log";
|
|
case ChatType.CHANNEL:
|
|
return "client-channel_chat";
|
|
case ChatType.CLIENT:
|
|
return "client-player_chat";
|
|
case ChatType.GENERAL:
|
|
return "client-channel_chat";
|
|
}
|
|
return "";
|
|
}
|
|
}
|
|
class ChatBox {
|
|
constructor(htmlTag) {
|
|
this.htmlTag = htmlTag;
|
|
this._button_send = this.htmlTag.find(".button-send");
|
|
this._input_message = this.htmlTag.find(".input-message");
|
|
this._button_send.click(this.onSend.bind(this));
|
|
this._input_message.keypress(event => {
|
|
if (event.keyCode == 13 /* Enter */ && !event.shiftKey) {
|
|
this.onSend();
|
|
return false;
|
|
}
|
|
}).on('input', (event) => {
|
|
let text = $(event.target).val().toString();
|
|
if (this.testMessage(text))
|
|
this._button_send.removeAttr("disabled");
|
|
else
|
|
this._button_send.attr("disabled", "true");
|
|
}).trigger("input");
|
|
this.chats = [];
|
|
this._activeChat = undefined;
|
|
this.createChat("chat_server", ChatType.SERVER).onMessageSend = (text) => {
|
|
if (!globalClient.serverConnection) {
|
|
chat.serverChat().appendError(_translations.MGIa7CAP || (_translations.MGIa7CAP = tr("Could not send chant message (Not connected)")));
|
|
return;
|
|
}
|
|
globalClient.serverConnection.command_helper.sendMessage(text, ChatType.SERVER).catch(error => {
|
|
if (error instanceof CommandResult)
|
|
return;
|
|
chat.serverChat().appendMessage(_translations.EfA3bz33 || (_translations.EfA3bz33 = tr("Failed to send text message.")));
|
|
console.error(_translations.sZZ04N8U || (_translations.sZZ04N8U = tr("Failed to send server text message: %o")), error);
|
|
});
|
|
};
|
|
this.serverChat().name = _translations.XY0rgaAe || (_translations.XY0rgaAe = tr("Server chat"));
|
|
this.createChat("chat_channel", ChatType.CHANNEL).onMessageSend = (text) => {
|
|
if (!globalClient.serverConnection) {
|
|
chat.channelChat().appendError(_translations.YUpKiux0 || (_translations.YUpKiux0 = tr("Could not send chant message (Not connected)")));
|
|
return;
|
|
}
|
|
globalClient.serverConnection.command_helper.sendMessage(text, ChatType.CHANNEL, globalClient.getClient().currentChannel()).catch(error => {
|
|
chat.channelChat().appendMessage(_translations.wtDGBoN6 || (_translations.wtDGBoN6 = tr("Failed to send text message.")));
|
|
console.error(_translations.AqmT7vNM || (_translations.AqmT7vNM = tr("Failed to send channel text message: %o")), error);
|
|
});
|
|
};
|
|
this.channelChat().name = _translations.CoEg7HKO || (_translations.CoEg7HKO = tr("Channel chat"));
|
|
globalClient.permissions.initializedListener.push(flag => {
|
|
if (flag)
|
|
this.activeChat0(this._activeChat);
|
|
});
|
|
}
|
|
createChat(key, type = ChatType.CLIENT) {
|
|
let chat = new ChatEntry(this, type, key);
|
|
this.chats.push(chat);
|
|
this.htmlTag.find(".chats").append(chat.htmlTag);
|
|
if (!this._activeChat)
|
|
this.activeChat = chat;
|
|
return chat;
|
|
}
|
|
findChat(key) {
|
|
for (let e of this.chats)
|
|
if (e.key == key)
|
|
return e;
|
|
return undefined;
|
|
}
|
|
deleteChat(chat) {
|
|
this.chats.remove(chat);
|
|
chat.htmlTag.detach();
|
|
if (this._activeChat === chat) {
|
|
if (this.chats.length > 0)
|
|
this.activeChat = this.chats.last();
|
|
else
|
|
this.activeChat = undefined;
|
|
}
|
|
}
|
|
onSend() {
|
|
let text = this._input_message.val().toString();
|
|
if (!this.testMessage(text))
|
|
return;
|
|
this._input_message.val("");
|
|
this._input_message.trigger("input");
|
|
if (this._activeChat && $.isFunction(this._activeChat.onMessageSend))
|
|
this._activeChat.onMessageSend(text);
|
|
}
|
|
set activeChat(chat) {
|
|
if (this.chats.indexOf(chat) === -1)
|
|
return;
|
|
if (this._activeChat == chat)
|
|
return;
|
|
this.activeChat0(chat);
|
|
}
|
|
activeChat0(chat) {
|
|
this._activeChat = chat;
|
|
for (let e of this.chats)
|
|
e.htmlTag.removeClass("active");
|
|
let flagAllowSend = false;
|
|
if (this._activeChat) {
|
|
this._activeChat.htmlTag.addClass("active");
|
|
this._activeChat.displayHistory();
|
|
if (globalClient && globalClient.permissions && globalClient.permissions.initialized())
|
|
switch (this._activeChat.type) {
|
|
case ChatType.CLIENT:
|
|
flagAllowSend = true;
|
|
break;
|
|
case ChatType.SERVER:
|
|
flagAllowSend = globalClient.permissions.neededPermission(PermissionType.B_CLIENT_SERVER_TEXTMESSAGE_SEND).granted(1);
|
|
break;
|
|
case ChatType.CHANNEL:
|
|
flagAllowSend = globalClient.permissions.neededPermission(PermissionType.B_CLIENT_CHANNEL_TEXTMESSAGE_SEND).granted(1);
|
|
break;
|
|
}
|
|
}
|
|
this._input_message.prop("disabled", !flagAllowSend);
|
|
}
|
|
get activeChat() { return this._activeChat; }
|
|
channelChat() {
|
|
return this.findChat("chat_channel");
|
|
}
|
|
serverChat() {
|
|
return this.findChat("chat_server");
|
|
}
|
|
focus() {
|
|
this._input_message.focus();
|
|
}
|
|
testMessage(message) {
|
|
message = message
|
|
.replace(/ /gi, "")
|
|
.replace(/<br>/gi, "")
|
|
.replace(/\n/gi, "")
|
|
.replace(/<br\/>/gi, "");
|
|
return message.length > 0;
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["99e5c97edd3a1838be9eaa78a48faf59c9bbe7ed486b8c7683192cf4d5717219"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["99e5c97edd3a1838be9eaa78a48faf59c9bbe7ed486b8c7683192cf4d5717219"] = "99e5c97edd3a1838be9eaa78a48faf59c9bbe7ed486b8c7683192cf4d5717219";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "VrIqB5fQ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalConnect.ts (108,22)" }, { name: "bTCq29_B", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalConnect.ts (135,29)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../utils/modal.ts" />
|
|
var Modals;
|
|
(function (Modals) {
|
|
function spawnConnectModal(defaultHost = { url: "ts.TeaSpeak.de", enforce: false }, connect_profile) {
|
|
let selected_profile;
|
|
const random_id = (() => {
|
|
const array = new Uint32Array(10);
|
|
window.crypto.getRandomValues(array);
|
|
return array.join("");
|
|
})();
|
|
const connect_modal = $("#tmpl_connect").renderTag({
|
|
client: native_client,
|
|
forum_path: settings.static("forum_path"),
|
|
password_id: random_id
|
|
}).modalize((header, body, footer) => {
|
|
const button_connect = footer.find(".button-connect");
|
|
const button_manage = body.find(".button-manage-profiles");
|
|
const input_profile = body.find(".container-select-profile select");
|
|
const input_address = body.find(".container-address input");
|
|
const input_nickname = body.find(".container-nickname input");
|
|
const input_password = body.find(".container-password input");
|
|
let updateFields = function () {
|
|
console.log("Updating");
|
|
if (selected_profile)
|
|
input_nickname.attr("placeholder", selected_profile.default_username);
|
|
else
|
|
input_nickname.attr("placeholder", "");
|
|
let address = input_address.val().toString();
|
|
settings.changeGlobal("connect_address", address);
|
|
let flag_address = !!address.match(Regex.IP_V4) || !!address.match(Regex.DOMAIN);
|
|
let nickname = input_nickname.val().toString();
|
|
settings.changeGlobal("connect_name", nickname);
|
|
let flag_nickname = (nickname.length == 0 && selected_profile && selected_profile.default_username.length > 0) || nickname.length >= 3 && nickname.length <= 32;
|
|
input_address.attr('pattern', flag_address ? null : '^[a]{1000}$').toggleClass('is-invalid', !flag_address);
|
|
input_nickname.attr('pattern', flag_nickname ? null : '^[a]{1000}$').toggleClass('is-invalid', !flag_nickname);
|
|
if (!flag_nickname || !flag_address || !selected_profile || !selected_profile.valid()) {
|
|
button_connect.prop("disabled", true);
|
|
}
|
|
else {
|
|
button_connect.prop("disabled", false);
|
|
}
|
|
};
|
|
input_nickname.val(settings.static_global("connect_name", undefined));
|
|
input_address.val(defaultHost.enforce ? defaultHost.url : settings.static_global("connect_address", defaultHost.url));
|
|
input_address
|
|
.on("keyup", () => updateFields())
|
|
.on('keydown', event => {
|
|
if (event.keyCode == 13 /* Enter */ && !event.shiftKey)
|
|
button_connect.trigger('click');
|
|
});
|
|
button_manage.on('click', event => {
|
|
const modal = Modals.spawnSettingsModal();
|
|
setTimeout(() => {
|
|
modal.htmlTag.find(".tab-profiles").parent(".entry").trigger('click');
|
|
}, 100);
|
|
modal.close_listener.push(() => {
|
|
input_profile.trigger('change');
|
|
});
|
|
return true;
|
|
});
|
|
{
|
|
for (const profile of profiles.profiles()) {
|
|
input_profile.append($.spawn("option").text(profile.profile_name).val(profile.id));
|
|
}
|
|
input_profile.on('change', event => {
|
|
selected_profile = profiles.find_profile(input_profile.val());
|
|
input_profile.toggleClass("is-invalid", !selected_profile || !selected_profile.valid());
|
|
updateFields();
|
|
});
|
|
input_profile.val(connect_profile && connect_profile.enforce ? connect_profile.profile.id : connect_profile && connect_profile.profile ? connect_profile.profile.id : 'default').trigger('change');
|
|
}
|
|
input_nickname.on("keyup", () => updateFields());
|
|
setTimeout(() => updateFields(), 100);
|
|
button_connect.on('click', event => {
|
|
connect_modal.close();
|
|
globalClient.startConnection(input_address.val().toString(), selected_profile, input_nickname.val().toString() || selected_profile.default_username, { password: input_password.val().toString(), hashed: false });
|
|
});
|
|
}, {
|
|
width: '70%'
|
|
});
|
|
connect_modal.open();
|
|
return;
|
|
const connectModal = createModal({
|
|
header: (_translations.VrIqB5fQ || (_translations.VrIqB5fQ = tr("Create a new connection"))),
|
|
body: function () {
|
|
const random_id = (() => {
|
|
const array = new Uint32Array(10);
|
|
window.crypto.getRandomValues(array);
|
|
return array.join("");
|
|
})();
|
|
let tag = $("#tmpl_connect").renderTag({
|
|
client: native_client,
|
|
forum_path: settings.static("forum_path"),
|
|
password_id: random_id
|
|
});
|
|
//connect_address
|
|
return tag;
|
|
},
|
|
footer: function () {
|
|
let tag = $.spawn("div");
|
|
tag.css("text-align", "right");
|
|
tag.css("margin-top", "3px");
|
|
tag.css("margin-bottom", "6px");
|
|
tag.addClass("modal-button-group");
|
|
let button = $.spawn("button");
|
|
button.addClass("connect_connect_button");
|
|
button.text(_translations.bTCq29_B || (_translations.bTCq29_B = tr("Connect")));
|
|
button.on("click", function () {
|
|
connectModal.close();
|
|
let field_address = tag.parents(".modal-content").find(".connect_address");
|
|
let address = field_address.val().toString();
|
|
globalClient.startConnection(address, selected_profile, tag.parents(".modal-content").find(".connect_nickname").val().toString() || selected_profile.default_username, { password: tag.parents(".modal-content").find(".connect_password").val().toString(), hashed: false });
|
|
});
|
|
tag.append(button);
|
|
return tag;
|
|
},
|
|
width: '70%',
|
|
});
|
|
connectModal.open();
|
|
}
|
|
Modals.spawnConnectModal = spawnConnectModal;
|
|
let Regex = {
|
|
//DOMAIN<:port>
|
|
DOMAIN: /^(localhost|((([a-zA-Z0-9_-]{0,63}\.){0,253})?[a-zA-Z0-9_-]{0,63}\.[a-zA-Z]{2,5}))(|:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[0-5]?[0-9]{1,4}))$/,
|
|
//IP<:port>
|
|
IP_V4: /(^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))(|:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[0-5]?[0-9]{1,4}))$/,
|
|
IP_V6: /(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))/,
|
|
IP: /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,
|
|
};
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["b8e4f60078c1425a1d8af9663d67add823c93e182cd404cdbdebb0fb94615d1c"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["b8e4f60078c1425a1d8af9663d67add823c93e182cd404cdbdebb0fb94615d1c"] = "b8e4f60078c1425a1d8af9663d67add823c93e182cd404cdbdebb0fb94615d1c";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "b5sCmZ9x", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBanCreate.ts (8,46)" }, { name: "bTAny5Zt", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBanCreate.ts (8,63)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var Modals;
|
|
(function (Modals) {
|
|
function spawnBanCreate(base, callback) {
|
|
let result = {};
|
|
result.banid = base ? base.banid : 0;
|
|
let modal;
|
|
modal = createModal({
|
|
header: base && base.banid > 0 ? _translations.b5sCmZ9x || (_translations.b5sCmZ9x = tr("Edit ban")) : _translations.bTAny5Zt || (_translations.bTAny5Zt = tr("Add ban")),
|
|
body: () => {
|
|
let template = $("#tmpl_ban_create").renderTag();
|
|
const input_name = template.find(".input-name");
|
|
const input_name_type = template.find(".input-name-type");
|
|
const input_ip = template.find(".input-ip");
|
|
const input_uid = template.find(".input-uid");
|
|
const input_reason = template.find(".input-reason");
|
|
const input_time = template.find(".input-time");
|
|
const input_time_type = template.find(".input-time-unit");
|
|
const input_hwid = template.find(".input-hwid");
|
|
const input_global = template.find(".input-global");
|
|
{
|
|
let maxTime = 0; //globalClient.permissions.neededPermission(PermissionType.I_CLIENT_BAN_MAX_BANTIME).value;
|
|
let unlimited = maxTime == 0 || maxTime == -1;
|
|
if (unlimited)
|
|
maxTime = 0;
|
|
input_time_type.find("option[value=\"sec\"]").prop("disabled", !unlimited && 1 > maxTime)
|
|
.attr("duration-scale", 1)
|
|
.attr("duration-max", maxTime);
|
|
input_time_type.find("option[value=\"min\"]").prop("disabled", !unlimited && 60 > maxTime)
|
|
.attr("duration-scale", 60)
|
|
.attr("duration-max", maxTime / 60);
|
|
input_time_type.find("option[value=\"hours\"]").prop("disabled", !unlimited && 60 * 60 > maxTime)
|
|
.attr("duration-scale", 60 * 60)
|
|
.attr("duration-max", maxTime / (60 * 60));
|
|
input_time_type.find("option[value=\"days\"]").prop("disabled", !unlimited && 60 * 60 * 24 > maxTime)
|
|
.attr("duration-scale", 60 * 60 * 24)
|
|
.attr("duration-max", maxTime / (60 * 60 * 24));
|
|
input_time_type.find("option[value=\"perm\"]").prop("disabled", !unlimited)
|
|
.attr("duration-scale", 0);
|
|
input_time_type.change(event => {
|
|
let element = $(event.target.selectedOptions.item(0));
|
|
if (element.val() !== "perm") {
|
|
input_time.prop("disabled", false);
|
|
let current = input_time.val();
|
|
let max = parseInt(element.attr("duration-max"));
|
|
if (max > 0 && current > max)
|
|
input_time.val(max);
|
|
else if (current <= 0)
|
|
input_time.val(1);
|
|
input_time.attr("max", max);
|
|
}
|
|
else {
|
|
input_time.prop("disabled", true);
|
|
}
|
|
});
|
|
}
|
|
template.find('input, textarea').on('keyup change', event => {
|
|
let valid = false;
|
|
if (input_name.val() || input_ip.val() || input_uid.val())
|
|
valid = true;
|
|
modal.htmlTag.find(".button-success").prop("disabled", !valid);
|
|
});
|
|
if (base) {
|
|
input_ip.val(base.ip);
|
|
input_uid.val(base.unique_id);
|
|
input_name.val(base.name);
|
|
input_hwid.val(base.hardware_id);
|
|
input_name_type[0].selectedIndex = base.name_type || 0;
|
|
input_reason.val(base.reason);
|
|
if (base.timestamp_expire.getTime() == 0) {
|
|
input_time_type.find("option[value=\"perm\"]").prop("selected", true);
|
|
}
|
|
else {
|
|
const time = (base.timestamp_expire.getTime() - base.timestamp_created.getTime()) / 1000;
|
|
if (time % (60 * 60 * 24) === 0) {
|
|
input_time_type.find("option[value=\"days\"]").prop("selected", true);
|
|
input_time.val(time / (60 * 60 * 24));
|
|
}
|
|
else if (time % (60 * 60) === 0) {
|
|
input_time_type.find("option[value=\"hours\"]").prop("selected", true);
|
|
input_time.val(time / (60 * 60));
|
|
}
|
|
else if (time % (60) === 0) {
|
|
input_time_type.find("option[value=\"min\"]").prop("selected", true);
|
|
input_time.val(time / (60));
|
|
}
|
|
else {
|
|
input_time_type.find("option[value=\"sec\"]").prop("selected", true);
|
|
input_time.val(time);
|
|
}
|
|
}
|
|
template.find(".container-global").detach(); //We cant edit this
|
|
input_global.prop("checked", base.server_id == 0);
|
|
}
|
|
if (globalClient && globalClient.permissions)
|
|
input_global.prop("disabled", !globalClient.permissions.neededPermission(base ? PermissionType.B_CLIENT_BAN_EDIT_GLOBAL : PermissionType.B_CLIENT_BAN_CREATE_GLOBAL));
|
|
return template;
|
|
},
|
|
footer: undefined
|
|
});
|
|
modal.htmlTag.find(".button-close").on('click', () => modal.close());
|
|
modal.htmlTag.find(".button-success").on('click', () => {
|
|
{
|
|
let length = modal.htmlTag.find(".input-time").val();
|
|
let duration = modal.htmlTag.find(".input-time-unit option:selected");
|
|
console.log(duration);
|
|
console.log(length + "*" + duration.attr("duration-scale"));
|
|
const time = length * parseInt(duration.attr("duration-scale"));
|
|
if (!result.timestamp_created)
|
|
result.timestamp_created = new Date();
|
|
if (time > 0)
|
|
result.timestamp_expire = new Date(result.timestamp_created.getTime() + time * 1000);
|
|
else
|
|
result.timestamp_expire = new Date(0);
|
|
}
|
|
{
|
|
result.name = modal.htmlTag.find(".input-name").val();
|
|
{
|
|
const name_type = modal.htmlTag.find(".input-name-type");
|
|
result.name_type = name_type[0].selectedIndex;
|
|
}
|
|
result.ip = modal.htmlTag.find(".input-ip").val();
|
|
result.unique_id = modal.htmlTag.find(".input-uid").val();
|
|
result.reason = modal.htmlTag.find(".input-reason").val();
|
|
result.hardware_id = modal.htmlTag.find(".input-hwid").val();
|
|
result.server_id = modal.htmlTag.find(".input-global").prop("checked") ? 0 : -1;
|
|
}
|
|
modal.close();
|
|
if (callback)
|
|
callback(result);
|
|
});
|
|
modal.htmlTag.find("input").trigger("change");
|
|
modal.open();
|
|
}
|
|
Modals.spawnBanCreate = spawnBanCreate;
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["b1eccee991e042e75ec3bb4e9a36bffeb9655687560ce4b5f831f3b55f9695bd"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["b1eccee991e042e75ec3bb4e9a36bffeb9655687560ce4b5f831f3b55f9695bd"] = "b1eccee991e042e75ec3bb4e9a36bffeb9655687560ce4b5f831f3b55f9695bd";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "oY1dCM4N", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBanClient.ts (15,24)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../utils/modal.ts" />
|
|
/// <reference path="../../proto.ts" />
|
|
/// <reference path="../../client.ts" />
|
|
var Modals;
|
|
(function (Modals) {
|
|
function spawnBanClient(name, callback) {
|
|
const connectModal = createModal({
|
|
header: function () {
|
|
return _translations.oY1dCM4N || (_translations.oY1dCM4N = tr("Ban client"));
|
|
},
|
|
body: function () {
|
|
let tag = $("#tmpl_client_ban").renderTag({
|
|
client_name: $.isArray(name) ? '"' + name.join('", "') + '"' : name
|
|
});
|
|
let maxTime = 0; //globalClient.permissions.neededPermission(PermissionType.I_CLIENT_BAN_MAX_BANTIME).value;
|
|
let unlimited = maxTime == 0 || maxTime == -1;
|
|
if (unlimited)
|
|
maxTime = 0;
|
|
let banTag = tag.find(".ban_duration_type");
|
|
let durationTag = tag.find(".ban_duration");
|
|
banTag.find("option[value=\"sec\"]").prop("disabled", !unlimited && 1 > maxTime)
|
|
.attr("duration-scale", 1)
|
|
.attr("duration-max", maxTime);
|
|
banTag.find("option[value=\"min\"]").prop("disabled", !unlimited && 60 > maxTime)
|
|
.attr("duration-scale", 60)
|
|
.attr("duration-max", maxTime / 60);
|
|
banTag.find("option[value=\"hours\"]").prop("disabled", !unlimited && 60 * 60 > maxTime)
|
|
.attr("duration-scale", 60 * 60)
|
|
.attr("duration-max", maxTime / (60 * 60));
|
|
banTag.find("option[value=\"days\"]").prop("disabled", !unlimited && 60 * 60 * 24 > maxTime)
|
|
.attr("duration-scale", 60 * 60 * 24)
|
|
.attr("duration-max", maxTime / (60 * 60 * 24));
|
|
banTag.find("option[value=\"perm\"]").prop("disabled", !unlimited)
|
|
.attr("duration-scale", 0);
|
|
durationTag.change(() => banTag.trigger('change'));
|
|
banTag.change(event => {
|
|
let element = $(event.target.selectedOptions.item(0));
|
|
if (element.val() !== "perm") {
|
|
durationTag.prop("disabled", false);
|
|
let current = durationTag.val();
|
|
let max = parseInt(element.attr("duration-max"));
|
|
if (max > 0 && current > max)
|
|
durationTag.val(max);
|
|
else if (current <= 0)
|
|
durationTag.val(1);
|
|
durationTag.attr("max", max);
|
|
}
|
|
else {
|
|
durationTag.prop("disabled", true);
|
|
}
|
|
});
|
|
return tag;
|
|
},
|
|
footer: function () {
|
|
let tag = $.spawn("div");
|
|
tag.css("text-align", "right");
|
|
tag.css("margin-top", "3px");
|
|
tag.css("margin-bottom", "6px");
|
|
tag.addClass("modal-button-group");
|
|
let buttonCancel = $.spawn("button");
|
|
buttonCancel.text("Cancel");
|
|
buttonCancel.on("click", () => connectModal.close());
|
|
tag.append(buttonCancel);
|
|
let buttonOk = $.spawn("button");
|
|
buttonOk.text("OK").addClass("btn_success");
|
|
tag.append(buttonOk);
|
|
return tag;
|
|
},
|
|
width: 450
|
|
});
|
|
connectModal.open();
|
|
connectModal.htmlTag.find(".btn_success").on('click', () => {
|
|
connectModal.close();
|
|
let length = connectModal.htmlTag.find(".ban_duration").val();
|
|
let duration = connectModal.htmlTag.find(".ban_duration_type option:selected");
|
|
console.log(duration);
|
|
console.log(length + "*" + duration.attr("duration-scale"));
|
|
callback({
|
|
length: length * parseInt(duration.attr("duration-scale")),
|
|
reason: connectModal.htmlTag.find(".ban_reason").val(),
|
|
no_hwid: !connectModal.htmlTag.find(".ban-type-hardware-id").prop("checked"),
|
|
no_ip: !connectModal.htmlTag.find(".ban-type-ip").prop("checked"),
|
|
no_name: !connectModal.htmlTag.find(".ban-type-nickname").prop("checked")
|
|
});
|
|
});
|
|
}
|
|
Modals.spawnBanClient = spawnBanClient;
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["65037f2c6d919416a95acc097f67bbba896dd13dbfecd2adeb8837e042710bd5"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["65037f2c6d919416a95acc097f67bbba896dd13dbfecd2adeb8837e042710bd5"] = "65037f2c6d919416a95acc097f67bbba896dd13dbfecd2adeb8837e042710bd5";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "ihb8iu3f", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalYesNo.ts (12,69)" }, { name: "aM9nGh0r", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalYesNo.ts (13,67)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../utils/modal.ts" />
|
|
var Modals;
|
|
(function (Modals) {
|
|
function spawnYesNo(header, body, callback, properties) {
|
|
properties = properties || {};
|
|
const props = ModalFunctions.warpProperties({});
|
|
props.template_properties || (props.template_properties = {});
|
|
props.template_properties.text_yes = properties.text_yes || (_translations.ihb8iu3f || (_translations.ihb8iu3f = tr("Yes")));
|
|
props.template_properties.text_no = properties.text_no || (_translations.aM9nGh0r || (_translations.aM9nGh0r = tr("No")));
|
|
props.template = "#tmpl_modal_yesno";
|
|
props.header = header;
|
|
props.template_properties.question = ModalFunctions.jqueriefy(body);
|
|
const modal = createModal(props);
|
|
let submited = false;
|
|
const button_yes = modal.htmlTag.find(".button-yes");
|
|
const button_no = modal.htmlTag.find(".button-no");
|
|
button_yes.on('click', event => {
|
|
if (!submited) {
|
|
submited = true;
|
|
callback(true);
|
|
}
|
|
modal.close();
|
|
});
|
|
button_no.on('click', event => {
|
|
if (!submited) {
|
|
submited = true;
|
|
callback(false);
|
|
}
|
|
modal.close();
|
|
});
|
|
modal.close_listener.push(() => button_no.trigger('click'));
|
|
modal.open();
|
|
return modal;
|
|
}
|
|
Modals.spawnYesNo = spawnYesNo;
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["b66fb0e58435bfead237d2b8cad56e8fc65416f10f426108cc9a389a32365d95"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["b66fb0e58435bfead237d2b8cad56e8fc65416f10f426108cc9a389a32365d95"] = "b66fb0e58435bfead237d2b8cad56e8fc65416f10f426108cc9a389a32365d95";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "XXGJLzMB", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/main.ts (107,23)" }, { name: "OKomiF7N", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/main.ts (116,28)" }, { name: "sfdo9OmQ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/main.ts (117,23)" }, { name: "tfe6lvUm", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/main.ts (127,28)" }, { name: "B4PHs4eG", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/main.ts (137,23)" }, { name: "MAC72mNf", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/main.ts (138,30)" }, { name: "XYBSTh0P", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/main.ts (293,45)" }, { name: "yBDIX0TS", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/main.ts (295,35)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="chat.ts" />
|
|
/// <reference path="client.ts" />
|
|
/// <reference path="utils/modal.ts" />
|
|
/// <reference path="ui/modal/ModalConnect.ts" />
|
|
/// <reference path="ui/modal/ModalCreateChannel.ts" />
|
|
/// <reference path="ui/modal/ModalBanCreate.ts" />
|
|
/// <reference path="ui/modal/ModalBanClient.ts" />
|
|
/// <reference path="ui/modal/ModalYesNo.ts" />
|
|
/// <reference path="ui/modal/ModalBanList.ts" />
|
|
/// <reference path="settings.ts" />
|
|
/// <reference path="log.ts" />
|
|
let settings;
|
|
let globalClient;
|
|
let chat;
|
|
const js_render = window.jsrender || $;
|
|
const native_client = window.require !== undefined;
|
|
function getUserMediaFunction() {
|
|
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia)
|
|
return (settings, success, fail) => { navigator.mediaDevices.getUserMedia(settings).then(success).catch(fail); };
|
|
return navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
|
|
}
|
|
function setup_close() {
|
|
window.onbeforeunload = event => {
|
|
if (profiles.requires_save())
|
|
profiles.save();
|
|
if (!settings.static(Settings.KEY_DISABLE_UNLOAD_DIALOG, false)) {
|
|
if (!globalClient.serverConnection || !globalClient.serverConnection.connected)
|
|
return;
|
|
if (!native_client) {
|
|
event.returnValue = "Are you really sure?<br>You're still connected!";
|
|
}
|
|
else {
|
|
event.preventDefault();
|
|
event.returnValue = "question";
|
|
const { remote } = require('electron');
|
|
const dialog = remote.dialog;
|
|
dialog.showMessageBox(remote.getCurrentWindow(), {
|
|
type: 'question',
|
|
buttons: ['Yes', 'No'],
|
|
title: 'Confirm',
|
|
message: 'Are you really sure?\nYou\'re still connected!'
|
|
}, choice => {
|
|
if (choice === 0) {
|
|
window.onbeforeunload = undefined;
|
|
remote.getCurrentWindow().close();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
};
|
|
}
|
|
function setup_jsrender() {
|
|
if (!js_render) {
|
|
displayCriticalError("Missing jsrender extension!");
|
|
return false;
|
|
}
|
|
if (!js_render.views) {
|
|
displayCriticalError("Missing jsrender viewer extension!");
|
|
return false;
|
|
}
|
|
js_render.views.settings.allowCode(true);
|
|
js_render.views.tags("rnd", (argument) => {
|
|
let min = parseInt(argument.substr(0, argument.indexOf('~')));
|
|
let max = parseInt(argument.substr(argument.indexOf('~') + 1));
|
|
return (Math.round(Math.random() * (min + max + 1) - min)).toString();
|
|
});
|
|
js_render.views.tags("fmt_date", (...args) => {
|
|
return moment(args[0]).format(args[1]);
|
|
});
|
|
js_render.views.tags("tr", (...args) => {
|
|
return tr(args[0]);
|
|
});
|
|
$(".jsrender-template").each((idx, _entry) => {
|
|
if (!js_render.templates(_entry.id, _entry.innerHTML)) { //, _entry.innerHTML
|
|
console.error("Failed to cache template " + _entry.id + " for js render!");
|
|
}
|
|
else
|
|
console.debug("Successfully loaded jsrender template " + _entry.id);
|
|
});
|
|
return true;
|
|
}
|
|
function initialize() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const display_load_error = message => {
|
|
if (typeof (display_critical_load) !== "undefined")
|
|
display_critical_load(message);
|
|
else
|
|
displayCriticalError(message);
|
|
};
|
|
settings = new Settings();
|
|
try {
|
|
yield i18n.initialize();
|
|
}
|
|
catch (error) {
|
|
console.error(_translations.XXGJLzMB || (_translations.XXGJLzMB = tr("Failed to initialized the translation system!\nError: %o")), error);
|
|
displayCriticalError("Failed to setup the translation system");
|
|
return;
|
|
}
|
|
try {
|
|
if (!setup_jsrender())
|
|
throw "invalid load";
|
|
}
|
|
catch (error) {
|
|
display_load_error(_translations.OKomiF7N || (_translations.OKomiF7N = tr("Failed to setup jsrender")));
|
|
console.error(_translations.sfdo9OmQ || (_translations.sfdo9OmQ = tr("Failed to load jsrender! %o")), error);
|
|
return;
|
|
}
|
|
try { //Initialize main template
|
|
const main = $("#tmpl_main").renderTag().dividerfy();
|
|
$("body").append(main);
|
|
}
|
|
catch (error) {
|
|
console.error(error);
|
|
display_load_error(_translations.tfe6lvUm || (_translations.tfe6lvUm = tr("Failed to setup main page!")));
|
|
return;
|
|
}
|
|
AudioController.initializeAudioController();
|
|
yield profiles.load();
|
|
try {
|
|
yield ppt.initialize();
|
|
}
|
|
catch (error) {
|
|
console.error(_translations.B4PHs4eG || (_translations.B4PHs4eG = tr("Failed to initialize ppt!\nError: %o")), error);
|
|
displayCriticalError(_translations.MAC72mNf || (_translations.MAC72mNf = tr("Failed to initialize ppt!")));
|
|
return;
|
|
}
|
|
setup_close();
|
|
});
|
|
}
|
|
function ab2str(buf) {
|
|
return String.fromCharCode.apply(null, new Uint16Array(buf));
|
|
}
|
|
function str2ab8(str) {
|
|
const buf = new ArrayBuffer(str.length);
|
|
const bufView = new Uint8Array(buf);
|
|
for (let i = 0, strLen = str.length; i < strLen; i++) {
|
|
bufView[i] = str.charCodeAt(i);
|
|
}
|
|
return buf;
|
|
}
|
|
/* FIXME Dont use atob, because it sucks for non UTF-8 tings */
|
|
function arrayBufferBase64(base64) {
|
|
base64 = atob(base64);
|
|
const buf = new ArrayBuffer(base64.length);
|
|
const bufView = new Uint8Array(buf);
|
|
for (let i = 0, strLen = base64.length; i < strLen; i++) {
|
|
bufView[i] = base64.charCodeAt(i);
|
|
}
|
|
return buf;
|
|
}
|
|
function base64ArrayBuffer(arrayBuffer) {
|
|
var base64 = '';
|
|
var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
var bytes = new Uint8Array(arrayBuffer);
|
|
var byteLength = bytes.byteLength;
|
|
var byteRemainder = byteLength % 3;
|
|
var mainLength = byteLength - byteRemainder;
|
|
var a, b, c, d;
|
|
var chunk;
|
|
// Main loop deals with bytes in chunks of 3
|
|
for (var i = 0; i < mainLength; i = i + 3) {
|
|
// Combine the three bytes into a single integer
|
|
chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
|
|
// Use bitmasks to extract 6-bit segments from the triplet
|
|
a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
|
|
b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12
|
|
c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6
|
|
d = chunk & 63; // 63 = 2^6 - 1
|
|
// Convert the raw binary segments to the appropriate ASCII encoding
|
|
base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
|
|
}
|
|
// Deal with the remaining bytes and padding
|
|
if (byteRemainder == 1) {
|
|
chunk = bytes[mainLength];
|
|
a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2
|
|
// Set the 4 least significant bits to zero
|
|
b = (chunk & 3) << 4; // 3 = 2^2 - 1
|
|
base64 += encodings[a] + encodings[b] + '==';
|
|
}
|
|
else if (byteRemainder == 2) {
|
|
chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1];
|
|
a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10
|
|
b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4
|
|
// Set the 2 least significant bits to zero
|
|
c = (chunk & 15) << 2; // 15 = 2^4 - 1
|
|
base64 += encodings[a] + encodings[b] + encodings[c] + '=';
|
|
}
|
|
return base64;
|
|
}
|
|
function Base64EncodeUrl(str) {
|
|
return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, '');
|
|
}
|
|
function Base64DecodeUrl(str, pad) {
|
|
if (typeof (pad) === 'undefined' || pad)
|
|
str = (str + '===').slice(0, str.length + (str.length % 4));
|
|
return str.replace(/-/g, '+').replace(/_/g, '/');
|
|
}
|
|
function main() {
|
|
//http://localhost:63343/Web-Client/index.php?_ijt=omcpmt8b9hnjlfguh8ajgrgolr&default_connect_url=true&default_connect_type=teamspeak&default_connect_url=localhost%3A9987&disableUnloadDialog=1&loader_ignore_age=1
|
|
globalClient = new TSClient();
|
|
/** Setup the XF forum identity **/
|
|
profiles.identities.setup_forum();
|
|
chat = new ChatBox($("#chat"));
|
|
globalClient.setup();
|
|
if (settings.static("connect_default", false) && settings.static("connect_address", "")) {
|
|
const profile_uuid = settings.static("connect_profile");
|
|
console.log("UUID: %s", profile_uuid);
|
|
const profile = profiles.find_profile(profile_uuid) || profiles.default_profile();
|
|
const address = settings.static("connect_address", "");
|
|
const username = settings.static("connect_username", "Another TeaSpeak user");
|
|
const password = settings.static("connect_password", "");
|
|
const password_hashed = settings.static("connect_password_hashed", false);
|
|
if (profile && profile.valid()) {
|
|
globalClient.startConnection(address, profile, username, password.length > 0 ? {
|
|
password: password,
|
|
hashed: password_hashed
|
|
} : undefined);
|
|
}
|
|
else {
|
|
Modals.spawnConnectModal({
|
|
url: address,
|
|
enforce: true
|
|
}, {
|
|
profile: profile,
|
|
enforce: true
|
|
});
|
|
}
|
|
}
|
|
let _resize_timeout;
|
|
$(window).on('resize', () => {
|
|
if (_resize_timeout)
|
|
clearTimeout(_resize_timeout);
|
|
_resize_timeout = setTimeout(() => {
|
|
globalClient.channelTree.handle_resized();
|
|
}, 1000);
|
|
});
|
|
stats.initialize({
|
|
verbose: true,
|
|
anonymize_ip_addresses: true,
|
|
volatile_collection_only: false
|
|
});
|
|
stats.register_user_count_listener(status => {
|
|
console.log("Received user count update: %o", status);
|
|
});
|
|
}
|
|
loader.register_task(loader.Stage.LOADED, {
|
|
name: "async main invoke",
|
|
function: () => __awaiter(this, void 0, void 0, function* () {
|
|
try {
|
|
yield initialize();
|
|
main();
|
|
if (!audio.player.initialized()) {
|
|
log.info(LogCategory.VOICE, _translations.XYBSTh0P || (_translations.XYBSTh0P = tr("Initialize audio controller later!")));
|
|
if (!audio.player.initializeFromGesture) {
|
|
console.error(_translations.yBDIX0TS || (_translations.yBDIX0TS = tr("Missing audio.player.initializeFromGesture")));
|
|
}
|
|
else
|
|
$(document).one('click', event => audio.player.initializeFromGesture());
|
|
}
|
|
}
|
|
catch (ex) {
|
|
console.error(ex.stack);
|
|
if (ex instanceof ReferenceError || ex instanceof TypeError)
|
|
ex = ex.name + ": " + ex.message;
|
|
displayCriticalError("Failed to invoke main function:<br>" + ex);
|
|
}
|
|
}),
|
|
priority: 10
|
|
});
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["22225479565e3b4bafc85629870ed7c1fbd292de3ee4e385bac4ec01beab7af6"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["22225479565e3b4bafc85629870ed7c1fbd292de3ee4e385bac4ec01beab7af6"] = "22225479565e3b4bafc85629870ed7c1fbd292de3ee4e385bac4ec01beab7af6";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "sCcGqyZs", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/stats.ts (76,38)" }, { name: "hYfNfpY2", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/stats.ts (113,50)" }, { name: "ed4qDxmJ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/stats.ts (123,50)" }, { name: "X1087nBI", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/stats.ts (133,50)" }, { name: "YQ1xbSKD", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/stats.ts (144,55)" }, { name: "McuKHkxC", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/stats.ts (173,42)" }, { name: "dYrfWrvw", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/stats.ts (177,46)" }, { name: "VMpPaDl0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/stats.ts (215,48)" }, { name: "qpgGDXwk", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/stats.ts (218,43)" }, { name: "DLaaN9c_", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/stats.ts (234,46)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var stats;
|
|
(function (stats) {
|
|
const LOG_PREFIX = "[Statistics] ";
|
|
let CloseCodes;
|
|
(function (CloseCodes) {
|
|
CloseCodes[CloseCodes["UNSET"] = 3000] = "UNSET";
|
|
CloseCodes[CloseCodes["RECONNECT"] = 3001] = "RECONNECT";
|
|
CloseCodes[CloseCodes["INTERNAL_ERROR"] = 3002] = "INTERNAL_ERROR";
|
|
CloseCodes[CloseCodes["BANNED"] = 3100] = "BANNED";
|
|
})(CloseCodes = stats.CloseCodes || (stats.CloseCodes = {}));
|
|
let ConnectionState;
|
|
(function (ConnectionState) {
|
|
ConnectionState[ConnectionState["CONNECTING"] = 0] = "CONNECTING";
|
|
ConnectionState[ConnectionState["INITIALIZING"] = 1] = "INITIALIZING";
|
|
ConnectionState[ConnectionState["CONNECTED"] = 2] = "CONNECTED";
|
|
ConnectionState[ConnectionState["UNSET"] = 3] = "UNSET";
|
|
})(ConnectionState || (ConnectionState = {}));
|
|
class SessionConfig {
|
|
}
|
|
stats.SessionConfig = SessionConfig;
|
|
class Config extends SessionConfig {
|
|
}
|
|
stats.Config = Config;
|
|
let reconnect_timer;
|
|
let current_config;
|
|
let last_user_count_update;
|
|
let user_count_listener = [];
|
|
const DEFAULT_CONFIG = {
|
|
verbose: true,
|
|
reconnect_interval: 5000,
|
|
anonymize_ip_addresses: true,
|
|
volatile_collection_only: false
|
|
};
|
|
function initialize_config_object(target_object, source_object) {
|
|
for (const key of Object.keys(source_object)) {
|
|
if (typeof (source_object[key]) === 'object')
|
|
initialize_config_object(target_object[key] || (target_object[key] = {}), source_object[key]);
|
|
if (typeof (target_object[key]) !== 'undefined')
|
|
continue;
|
|
target_object[key] = source_object[key];
|
|
}
|
|
return target_object;
|
|
}
|
|
function initialize(config) {
|
|
current_config = initialize_config_object(config || {}, DEFAULT_CONFIG);
|
|
if (current_config.verbose)
|
|
console.log(LOG_PREFIX + (_translations.sCcGqyZs || (_translations.sCcGqyZs = tr("Initializing statistics with this config: %o"))), current_config);
|
|
connection.start_connection();
|
|
}
|
|
stats.initialize = initialize;
|
|
function register_user_count_listener(listener) {
|
|
user_count_listener.push(listener);
|
|
}
|
|
stats.register_user_count_listener = register_user_count_listener;
|
|
function all_user_count_listener() {
|
|
return user_count_listener;
|
|
}
|
|
stats.all_user_count_listener = all_user_count_listener;
|
|
function deregister_user_count_listener(listener) {
|
|
user_count_listener.remove(listener);
|
|
}
|
|
stats.deregister_user_count_listener = deregister_user_count_listener;
|
|
let connection;
|
|
(function (connection_2) {
|
|
let connection;
|
|
connection_2.connection_state = ConnectionState.UNSET;
|
|
function start_connection() {
|
|
cancel_reconnect();
|
|
close_connection();
|
|
connection_2.connection_state = ConnectionState.CONNECTING;
|
|
connection = new WebSocket('wss://web-stats.teaspeak.de:27790');
|
|
if (!connection)
|
|
connection = new WebSocket('wss://localhost:27788');
|
|
{
|
|
const connection_copy = connection;
|
|
connection.onclose = (event) => {
|
|
if (connection_copy !== connection)
|
|
return;
|
|
if (current_config.verbose)
|
|
console.log(LOG_PREFIX + (_translations.hYfNfpY2 || (_translations.hYfNfpY2 = tr("Lost connection to statistics server (Connection closed). Reason: %o. Event object: %o"))), CloseCodes[event.code] || event.code, event);
|
|
if (event.code != CloseCodes.BANNED)
|
|
invoke_reconnect();
|
|
};
|
|
connection.onopen = () => {
|
|
if (connection_copy !== connection)
|
|
return;
|
|
if (current_config.verbose)
|
|
console.log(LOG_PREFIX + (_translations.ed4qDxmJ || (_translations.ed4qDxmJ = tr("Successfully connected to server. Initializing session."))));
|
|
connection_2.connection_state = ConnectionState.INITIALIZING;
|
|
initialize_session();
|
|
};
|
|
connection.onerror = (event) => {
|
|
if (connection_copy !== connection)
|
|
return;
|
|
if (current_config.verbose)
|
|
console.log(LOG_PREFIX + (_translations.X1087nBI || (_translations.X1087nBI = tr("Received an error. Closing connection. Object: %o"))), event);
|
|
connection.close(CloseCodes.INTERNAL_ERROR);
|
|
invoke_reconnect();
|
|
};
|
|
connection.onmessage = (event) => {
|
|
if (connection_copy !== connection)
|
|
return;
|
|
if (typeof (event.data) !== 'string') {
|
|
if (current_config.verbose)
|
|
console.warn(LOG_PREFIX + (_translations.YQ1xbSKD || (_translations.YQ1xbSKD = tr("Received an message which isn't a string. Event object: %o"))), event);
|
|
return;
|
|
}
|
|
handle_message(event.data);
|
|
};
|
|
}
|
|
}
|
|
connection_2.start_connection = start_connection;
|
|
function close_connection() {
|
|
if (connection) {
|
|
const connection_copy = connection;
|
|
connection = undefined;
|
|
try {
|
|
connection_copy.close(3001);
|
|
}
|
|
catch (_) { }
|
|
}
|
|
}
|
|
connection_2.close_connection = close_connection;
|
|
function invoke_reconnect() {
|
|
close_connection();
|
|
if (reconnect_timer) {
|
|
clearTimeout(reconnect_timer);
|
|
reconnect_timer = undefined;
|
|
}
|
|
if (current_config.verbose)
|
|
console.log(LOG_PREFIX + (_translations.McuKHkxC || (_translations.McuKHkxC = tr("Scheduled reconnect in %dms"))), current_config.reconnect_interval);
|
|
reconnect_timer = setTimeout(() => {
|
|
if (current_config.verbose)
|
|
console.log(LOG_PREFIX + (_translations.dYrfWrvw || (_translations.dYrfWrvw = tr("Reconnecting"))));
|
|
start_connection();
|
|
}, current_config.reconnect_interval);
|
|
}
|
|
function cancel_reconnect() {
|
|
if (reconnect_timer) {
|
|
clearTimeout(reconnect_timer);
|
|
reconnect_timer = undefined;
|
|
}
|
|
}
|
|
connection_2.cancel_reconnect = cancel_reconnect;
|
|
function send_message(type, data) {
|
|
connection.send(JSON.stringify({
|
|
type: type,
|
|
data: data
|
|
}));
|
|
}
|
|
function initialize_session() {
|
|
const config_object = {};
|
|
for (const key in SessionConfig) {
|
|
if (SessionConfig.hasOwnProperty(key))
|
|
config_object[key] = current_config[key];
|
|
}
|
|
send_message('initialize', {
|
|
config: config_object
|
|
});
|
|
}
|
|
function handle_message(message) {
|
|
const data_object = JSON.parse(message);
|
|
const type = data_object.type;
|
|
const data = data_object.data;
|
|
if (typeof (handler[type]) === 'function') {
|
|
if (current_config.verbose)
|
|
console.debug(LOG_PREFIX + (_translations.VMpPaDl0 || (_translations.VMpPaDl0 = tr("Handling message of type %s"))), type);
|
|
handler[type](data);
|
|
}
|
|
else if (current_config.verbose) {
|
|
console.warn(LOG_PREFIX + (_translations.qpgGDXwk || (_translations.qpgGDXwk = tr("Received message with an unknown type (%s). Dropping message. Full message: %o"))), type, data_object);
|
|
}
|
|
}
|
|
let handler;
|
|
(function (handler) {
|
|
function handle_notify_user_count(data) {
|
|
last_user_count_update = Date.now();
|
|
for (const listener of [...user_count_listener])
|
|
listener(data);
|
|
}
|
|
function handle_notify_initialized(json) {
|
|
if (current_config.verbose)
|
|
console.log(LOG_PREFIX + (_translations.DLaaN9c_ || (_translations.DLaaN9c_ = tr("Session successfully initialized."))));
|
|
connection_2.connection_state = ConnectionState.CONNECTED;
|
|
}
|
|
handler["notifyinitialized"] = handle_notify_initialized;
|
|
handler["notifyusercount"] = handle_notify_user_count;
|
|
})(handler || (handler = {}));
|
|
})(connection || (connection = {}));
|
|
})(stats || (stats = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["7a121df37aea016cf9035da97ff8c312caed0597dd07d2e78dcb684543854f7b"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["7a121df37aea016cf9035da97ff8c312caed0597dd07d2e78dcb684543854f7b"] = "7a121df37aea016cf9035da97ff8c312caed0597dd07d2e78dcb684543854f7b";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "c4oCx1uR", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/codec/BasicCodec.ts (52,74)" }, { name: "pzkU8E2k", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/codec/BasicCodec.ts (53,101)" }, { name: "cePIMcCz", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/codec/BasicCodec.ts (77,39)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="Codec.ts"/>
|
|
class AVGCalculator {
|
|
constructor() {
|
|
this.history_size = 100;
|
|
this.history = [];
|
|
}
|
|
push(entry) {
|
|
while (this.history.length > this.history_size)
|
|
this.history.pop();
|
|
this.history.unshift(entry);
|
|
}
|
|
avg() {
|
|
let count = 0;
|
|
for (let entry of this.history)
|
|
count += entry;
|
|
return count / this.history.length;
|
|
}
|
|
}
|
|
class BasicCodec {
|
|
constructor(codecSampleRate) {
|
|
this._latenz = new AVGCalculator();
|
|
this.on_encoded_data = $ => { };
|
|
this.channelCount = 1;
|
|
this.samplesPerUnit = 960;
|
|
this.channelCount = 1;
|
|
this.samplesPerUnit = 960;
|
|
this._audioContext = new (window.webkitOfflineAudioContext || window.OfflineAudioContext)(audio.player.destination().channelCount, 1024, audio.player.context().sampleRate);
|
|
this._codecSampleRate = codecSampleRate;
|
|
this._decodeResampler = new AudioResampler(audio.player.context().sampleRate);
|
|
this._encodeResampler = new AudioResampler(codecSampleRate);
|
|
}
|
|
encodeSamples(cache, pcm) {
|
|
this._encodeResampler.resample(pcm).catch(error => console.error(_translations.c4oCx1uR || (_translations.c4oCx1uR = tr("Could not resample PCM data for codec. Error: %o")), error))
|
|
.then(buffer => this.encodeSamples0(cache, buffer)).catch(error => console.error(_translations.pzkU8E2k || (_translations.pzkU8E2k = tr("Could not encode PCM data for codec. Error: %o")), error));
|
|
}
|
|
encodeSamples0(cache, buffer) {
|
|
cache._chunks.push(new BufferChunk(buffer)); //TODO multi channel!
|
|
while (cache.bufferedSamples(this.samplesPerUnit) >= this.samplesPerUnit) {
|
|
let buffer = this._audioContext.createBuffer(this.channelCount, this.samplesPerUnit, this._codecSampleRate);
|
|
let index = 0;
|
|
while (index < this.samplesPerUnit) {
|
|
let buf = cache._chunks[0];
|
|
let cpyBytes = buf.copyRangeTo(buffer, this.samplesPerUnit - index, index);
|
|
index += cpyBytes;
|
|
buf.index += cpyBytes;
|
|
if (buf.index == buf.buffer.length)
|
|
cache._chunks.pop_front();
|
|
}
|
|
let encodeBegin = Date.now();
|
|
this.encode(buffer).then(result => {
|
|
if (result instanceof Uint8Array) {
|
|
let time = Date.now() - encodeBegin;
|
|
if (time > 20)
|
|
console.error(_translations.cePIMcCz || (_translations.cePIMcCz = tr("Required time: %d")), time);
|
|
//if(time > 20)
|
|
// chat.serverChat().appendMessage("Required decode time: " + time);
|
|
this.on_encoded_data(result);
|
|
}
|
|
else
|
|
console.error("[Codec][" + this.name() + "] Could not encode buffer. Result: " + result); //TODO tr
|
|
});
|
|
}
|
|
return true;
|
|
}
|
|
decodeSamples(cache, data) {
|
|
return this.decode(data).then(buffer => this._decodeResampler.resample(buffer));
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["aab3a372abbb05d1f95e507d5b92d24b652b81c75a3f0d8163d1344cf0046b79"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["aab3a372abbb05d1f95e507d5b92d24b652b81c75a3f0d8163d1344cf0046b79"] = "aab3a372abbb05d1f95e507d5b92d24b652b81c75a3f0d8163d1344cf0046b79";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="BasicCodec.ts"/>
|
|
class CodecWrapperRaw extends BasicCodec {
|
|
constructor(codecSampleRate) {
|
|
super(codecSampleRate);
|
|
this.bufferSize = 4096 * 4;
|
|
}
|
|
name() {
|
|
return "raw";
|
|
}
|
|
initialise() {
|
|
this.converterRaw = Module._malloc(this.bufferSize);
|
|
this.converter = new Uint8Array(Module.HEAPU8.buffer, this.converterRaw, this.bufferSize);
|
|
return new Promise(resolve => resolve());
|
|
}
|
|
initialized() {
|
|
return true;
|
|
}
|
|
deinitialise() { }
|
|
decode(data) {
|
|
return new Promise((resolve, reject) => {
|
|
this.converter.set(data);
|
|
let buf = Module.HEAPF32.slice(this.converter.byteOffset / 4, (this.converter.byteOffset / 4) + data.length / 4);
|
|
let audioBuf = this._audioContext.createBuffer(1, data.length / 4, this._codecSampleRate);
|
|
audioBuf.copyToChannel(buf, 0);
|
|
resolve(audioBuf);
|
|
});
|
|
}
|
|
encode(data) {
|
|
return new Promise(resolve => resolve(new Uint8Array(data.getChannelData(0))));
|
|
}
|
|
reset() { return true; }
|
|
processLatency() {
|
|
return 0;
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["7ad8220e27cab46acc322af547c49bd0c5d1136722ba934f57c1a3a43669f66b"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["7ad8220e27cab46acc322af547c49bd0c5d1136722ba934f57c1a3a43669f66b"] = "7ad8220e27cab46acc322af547c49bd0c5d1136722ba934f57c1a3a43669f66b";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "mVOeydNI", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/codec/CodecWrapperWorker.ts (156,26)" }, { name: "UY6zlrk1", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/codec/CodecWrapperWorker.ts (158,27)" }, { name: "yWCPu1Vl", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/codec/CodecWrapperWorker.ts (164,29)" }, { name: "k3gMhK6X", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/codec/CodecWrapperWorker.ts (179,25)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="BasicCodec.ts"/>
|
|
class CodecWrapperWorker extends BasicCodec {
|
|
constructor(type) {
|
|
super(48000);
|
|
this._workerListener = [];
|
|
this._workerCallbackToken = "callback_token";
|
|
this._workerTokeIndex = 0;
|
|
this._initialized = false;
|
|
this.type = type;
|
|
switch (type) {
|
|
case CodecType.OPUS_MUSIC:
|
|
this.channelCount = 2;
|
|
break;
|
|
case CodecType.OPUS_VOICE:
|
|
this.channelCount = 1;
|
|
break;
|
|
default:
|
|
throw "invalid codec type!";
|
|
}
|
|
}
|
|
name() {
|
|
return "Worker for " + CodecType[this.type] + " Channels " + this.channelCount;
|
|
}
|
|
initialise() {
|
|
if (this._initializePromise)
|
|
return this._initializePromise;
|
|
return this._initializePromise = this.spawnWorker().then(() => new Promise((resolve, reject) => {
|
|
const token = this.generateToken();
|
|
this.sendWorkerMessage({
|
|
command: "initialise",
|
|
type: this.type,
|
|
channelCount: this.channelCount,
|
|
token: token
|
|
});
|
|
this._workerListener.push({
|
|
token: token,
|
|
resolve: data => {
|
|
this._initialized = data["success"] == true;
|
|
if (data["success"] == true)
|
|
resolve();
|
|
else
|
|
reject(data.message);
|
|
}
|
|
});
|
|
}));
|
|
}
|
|
initialized() {
|
|
return this._initialized;
|
|
}
|
|
deinitialise() {
|
|
this.sendWorkerMessage({
|
|
command: "deinitialise"
|
|
});
|
|
}
|
|
decode(data) {
|
|
let token = this.generateToken();
|
|
let result = new Promise((resolve, reject) => {
|
|
this._workerListener.push({
|
|
token: token,
|
|
resolve: (data) => {
|
|
if (data.success) {
|
|
let array = new Float32Array(data.dataLength);
|
|
for (let index = 0; index < array.length; index++)
|
|
array[index] = data.data[index];
|
|
let audioBuf = this._audioContext.createBuffer(this.channelCount, array.length / this.channelCount, this._codecSampleRate);
|
|
for (let channel = 0; channel < this.channelCount; channel++) {
|
|
for (let offset = 0; offset < audioBuf.length; offset++) {
|
|
audioBuf.getChannelData(channel)[offset] = array[channel + offset * this.channelCount];
|
|
}
|
|
}
|
|
resolve(audioBuf);
|
|
}
|
|
else {
|
|
reject(data.message);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
this.sendWorkerMessage({
|
|
command: "decodeSamples",
|
|
token: token,
|
|
data: data,
|
|
dataLength: data.length
|
|
});
|
|
return result;
|
|
}
|
|
encode(data) {
|
|
let token = this.generateToken();
|
|
let result = new Promise((resolve, reject) => {
|
|
this._workerListener.push({
|
|
token: token,
|
|
resolve: (data) => {
|
|
if (data.success) {
|
|
let array = new Uint8Array(data.dataLength);
|
|
for (let index = 0; index < array.length; index++)
|
|
array[index] = data.data[index];
|
|
resolve(array);
|
|
}
|
|
else {
|
|
reject(data.message);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
let buffer = new Float32Array(this.channelCount * data.length);
|
|
for (let offset = 0; offset < data.length; offset++) {
|
|
for (let channel = 0; channel < this.channelCount; channel++)
|
|
buffer[offset * this.channelCount + channel] = data.getChannelData(channel)[offset];
|
|
}
|
|
this.sendWorkerMessage({
|
|
command: "encodeSamples",
|
|
token: token,
|
|
data: buffer,
|
|
dataLength: buffer.length
|
|
});
|
|
return result;
|
|
}
|
|
reset() {
|
|
this.sendWorkerMessage({
|
|
command: "reset"
|
|
});
|
|
return true;
|
|
}
|
|
generateToken() {
|
|
return this._workerTokeIndex++ + "_token";
|
|
}
|
|
sendWorkerMessage(message, transfare) {
|
|
message["timestamp"] = Date.now();
|
|
this._worker.postMessage(message, transfare);
|
|
}
|
|
onWorkerMessage(message) {
|
|
if (Date.now() - message["timestamp"] > 5)
|
|
console.warn(_translations.mVOeydNI || (_translations.mVOeydNI = tr("Worker message stock time: %d")), Date.now() - message["timestamp"]);
|
|
if (!message["token"]) {
|
|
console.error(_translations.UY6zlrk1 || (_translations.UY6zlrk1 = tr("Invalid worker token!")));
|
|
return;
|
|
}
|
|
if (message["token"] == this._workerCallbackToken) {
|
|
if (message["type"] == "loaded") {
|
|
console.log(_translations.yWCPu1Vl || (_translations.yWCPu1Vl = tr("[Codec] Got worker init response: Success: %o Message: %o")), message["success"], message["message"]);
|
|
if (message["success"]) {
|
|
if (this._workerCallbackResolve)
|
|
this._workerCallbackResolve();
|
|
}
|
|
else {
|
|
if (this._workerCallbackReject)
|
|
this._workerCallbackReject(message["message"]);
|
|
}
|
|
this._workerCallbackReject = undefined;
|
|
this._workerCallbackResolve = undefined;
|
|
return;
|
|
}
|
|
else if (message["type"] == "chatmessage_server") {
|
|
chat.serverChat().appendMessage(message["message"]);
|
|
return;
|
|
}
|
|
console.log(_translations.k3gMhK6X || (_translations.k3gMhK6X = tr("Costume callback! (%o)")), message);
|
|
return;
|
|
}
|
|
for (let entry of this._workerListener) {
|
|
if (entry.token == message["token"]) {
|
|
entry.resolve(message);
|
|
this._workerListener.remove(entry);
|
|
return;
|
|
}
|
|
}
|
|
//TODO tr
|
|
console.error("Could not find worker token entry! (" + message["token"] + ")");
|
|
}
|
|
spawnWorker() {
|
|
return new Promise((resolve, reject) => {
|
|
this._workerCallbackReject = reject;
|
|
this._workerCallbackResolve = resolve;
|
|
this._worker = new Worker(settings.static("worker_directory", "js/workers/") + "WorkerCodec.js");
|
|
this._worker.onmessage = event => this.onWorkerMessage(event.data);
|
|
this._worker.onerror = (error) => reject("Failed to load worker (" + error.message + ")"); //TODO tr
|
|
});
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["6233fb4b35a2d6fc524440f68ed7419bdafb5eae2edbf36a5a9cbdec1e836438"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["6233fb4b35a2d6fc524440f68ed7419bdafb5eae2edbf36a5a9cbdec1e836438"] = "6233fb4b35a2d6fc524440f68ed7419bdafb5eae2edbf36a5a9cbdec1e836438";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "TFD2Zvsi", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (65,29)" }, { name: "o1_kIuJm", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (84,25)" }, { name: "a9gYXNmN", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (107,45)" }, { name: "qiMXyXQE", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (121,39)" }, { name: "KzoM1Aru", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (128,35)" }, { name: "pzcd68lU", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (160,25)" }, { name: "ORQmYQxR", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (181,25)" }, { name: "ZnMmybHj", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (185,35)" }, { name: "H8Ljrp8b", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (195,25)" }, { name: "wNE6Yk8v", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (199,35)" }, { name: "yBTs793E", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (240,57)" }, { name: "ld0SEFgV", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (242,57)" }, { name: "H2m5xkNS", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (248,53)" }, { name: "G8shumQI", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (258,53)" }, { name: "wGPL0vDb", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (266,34)" }, { name: "yddBhUW8", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (297,31)" }, { name: "dQP_9bwx", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (320,53)" }, { name: "wiWY_KPc", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (325,53)" }, { name: "Oru0Sje5", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (333,51)" }, { name: "zwEFh23K", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (341,51)" }, { name: "FKmT074Q", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (355,51)" }, { name: "vTWtjrtn", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (365,35)" }, { name: "mP6ACPD5", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (380,31)" }, { name: "JApmNtuz", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (385,31)" }, { name: "DA87rt4L", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (389,31)" }, { name: "NcqTc0dn", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (405,56)" }, { name: "qeasUFNW", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (405,109)" }, { name: "dtUR49jo", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (418,56)" }, { name: "YFVVq1QK", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (418,101)" }, { name: "icEV8veV", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (429,56)" }, { name: "mui2Bvyn", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (429,127)" }, { name: "v33Oxo4X", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (443,30)" }, { name: "mzojB4K9", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (455,31)" }, { name: "ZF_a7vjl", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (461,31)" }, { name: "JOU61YqT", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (467,31)" }, { name: "c6E0QRE0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (480,31)" }, { name: "HvOzEfon", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (508,35)" }, { name: "WjJ09uxh", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (512,35)" }, { name: "Wy_4Q6WO", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (538,31)" }, { name: "bVJCAzRK", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHandler.ts (601,46)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var connection;
|
|
(function (connection_3) {
|
|
class ServerConnectionCommandBoss extends connection_3.AbstractCommandHandlerBoss {
|
|
constructor(connection) {
|
|
super(connection);
|
|
}
|
|
}
|
|
connection_3.ServerConnectionCommandBoss = ServerConnectionCommandBoss;
|
|
class ConnectionCommandHandler extends connection_3.AbstractCommandHandler {
|
|
constructor(connection) {
|
|
super(connection);
|
|
this["error"] = this.handleCommandResult;
|
|
this["channellist"] = this.handleCommandChannelList;
|
|
this["channellistfinished"] = this.handleCommandChannelListFinished;
|
|
this["notifychannelcreated"] = this.handleCommandChannelCreate;
|
|
this["notifychanneldeleted"] = this.handleCommandChannelDelete;
|
|
this["notifychannelhide"] = this.handleCommandChannelHide;
|
|
this["notifychannelshow"] = this.handleCommandChannelShow;
|
|
this["notifycliententerview"] = this.handleCommandClientEnterView;
|
|
this["notifyclientleftview"] = this.handleCommandClientLeftView;
|
|
this["notifyclientmoved"] = this.handleNotifyClientMoved;
|
|
this["initserver"] = this.handleCommandServerInit;
|
|
this["notifychannelmoved"] = this.handleNotifyChannelMoved;
|
|
this["notifychanneledited"] = this.handleNotifyChannelEdited;
|
|
this["notifytextmessage"] = this.handleNotifyTextMessage;
|
|
this["notifyclientupdated"] = this.handleNotifyClientUpdated;
|
|
this["notifyserveredited"] = this.handleNotifyServerEdited;
|
|
this["notifyserverupdated"] = this.handleNotifyServerUpdated;
|
|
this["notifyclientpoke"] = this.handleNotifyClientPoke;
|
|
this["notifymusicplayerinfo"] = this.handleNotifyMusicPlayerInfo;
|
|
this["notifyservergroupclientadded"] = this.handleNotifyServerGroupClientAdd;
|
|
this["notifyservergroupclientdeleted"] = this.handleNotifyServerGroupClientRemove;
|
|
this["notifyclientchannelgroupchanged"] = this.handleNotifyClientChannelGroupChanged;
|
|
}
|
|
handle_command(command) {
|
|
if (this[command.command]) {
|
|
this[command.command](command.arguments);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
set_handler(command, handler) {
|
|
this[command] = handler;
|
|
}
|
|
unset_handler(command, handler) {
|
|
if (handler && this[command] != handler)
|
|
return;
|
|
this[command] = undefined;
|
|
}
|
|
handleCommandResult(json) {
|
|
json = json[0]; //Only one bulk
|
|
let code = json["return_code"];
|
|
if (code.length == 0) {
|
|
console.log(_translations.TFD2Zvsi || (_translations.TFD2Zvsi = tr("Invalid return code! (%o)")), json);
|
|
return;
|
|
}
|
|
let retListeners = this.connection["_retListener"];
|
|
for (let e of retListeners) {
|
|
if (e.code != code)
|
|
continue;
|
|
retListeners.remove(e);
|
|
let result = new CommandResult(json);
|
|
if (result.success)
|
|
e.resolve(result);
|
|
else
|
|
e.reject(result);
|
|
break;
|
|
}
|
|
}
|
|
handleCommandServerInit(json) {
|
|
//We could setup the voice channel
|
|
console.log(_translations.o1_kIuJm || (_translations.o1_kIuJm = tr("Setting up voice")));
|
|
this.connection.client.voiceConnection.createSession();
|
|
json = json[0]; //Only one bulk
|
|
this.connection.client.clientId = parseInt(json["aclid"]);
|
|
this.connection.client.getClient().updateVariables({ key: "client_nickname", value: json["acn"] });
|
|
let updates = [];
|
|
for (let key in json) {
|
|
if (key === "aclid")
|
|
continue;
|
|
if (key === "acn")
|
|
continue;
|
|
updates.push({ key: key, value: json[key] });
|
|
}
|
|
this.connection.client.channelTree.server.updateVariables(false, ...updates);
|
|
chat.serverChat().name = this.connection.client.channelTree.server.properties["virtualserver_name"];
|
|
chat.serverChat().appendMessage(_translations.a9gYXNmN || (_translations.a9gYXNmN = tr("Connected as {0}")), true, this.connection.client.getClient().createChatTag(true));
|
|
sound.play(Sound.CONNECTION_CONNECTED);
|
|
globalClient.onConnected();
|
|
}
|
|
createChannelFromJson(json, ignoreOrder = false) {
|
|
let tree = this.connection.client.channelTree;
|
|
let channel = new ChannelEntry(parseInt(json["cid"]), json["channel_name"], tree.findChannel(json["cpid"]));
|
|
tree.insertChannel(channel);
|
|
if (json["channel_order"] !== "0") {
|
|
let prev = tree.findChannel(json["channel_order"]);
|
|
if (!prev && json["channel_order"] != 0) {
|
|
if (!ignoreOrder) {
|
|
console.error(_translations.qiMXyXQE || (_translations.qiMXyXQE = tr("Invalid channel order id!")));
|
|
return;
|
|
}
|
|
}
|
|
let parent = tree.findChannel(json["cpid"]);
|
|
if (!parent && json["cpid"] != 0) {
|
|
console.error(_translations.KzoM1Aru || (_translations.KzoM1Aru = tr("Invalid channel parent")));
|
|
return;
|
|
}
|
|
tree.moveChannel(channel, prev, parent); //TODO test if channel exists!
|
|
}
|
|
if (ignoreOrder) {
|
|
for (let ch of tree.channels) {
|
|
if (ch.properties.channel_order == channel.channelId) {
|
|
tree.moveChannel(ch, channel, channel.parent); //Corrent the order :)
|
|
}
|
|
}
|
|
}
|
|
let updates = [];
|
|
for (let key in json) {
|
|
if (key === "cid")
|
|
continue;
|
|
if (key === "cpid")
|
|
continue;
|
|
if (key === "invokerid")
|
|
continue;
|
|
if (key === "invokername")
|
|
continue;
|
|
if (key === "invokeruid")
|
|
continue;
|
|
if (key === "reasonid")
|
|
continue;
|
|
updates.push({ key: key, value: json[key] });
|
|
}
|
|
channel.updateVariables(...updates);
|
|
}
|
|
handleCommandChannelList(json) {
|
|
this.connection.client.channelTree.hide_channel_tree(); /* dont perform channel inserts on the dom to prevent style recalculations */
|
|
console.log(_translations.pzcd68lU || (_translations.pzcd68lU = tr("Got %d new channels")), json.length);
|
|
for (let index = 0; index < json.length; index++)
|
|
this.createChannelFromJson(json[index], true);
|
|
}
|
|
handleCommandChannelListFinished(json) {
|
|
this.connection.client.channelTree.show_channel_tree();
|
|
}
|
|
handleCommandChannelCreate(json) {
|
|
this.createChannelFromJson(json[0]);
|
|
}
|
|
handleCommandChannelShow(json) {
|
|
this.createChannelFromJson(json[0]); //TODO may chat?
|
|
}
|
|
handleCommandChannelDelete(json) {
|
|
let tree = this.connection.client.channelTree;
|
|
console.log(_translations.ORQmYQxR || (_translations.ORQmYQxR = tr("Got %d channel deletions")), json.length);
|
|
for (let index = 0; index < json.length; index++) {
|
|
let channel = tree.findChannel(json[index]["cid"]);
|
|
if (!channel) {
|
|
console.error(_translations.ZnMmybHj || (_translations.ZnMmybHj = tr("Invalid channel onDelete (Unknown channel)")));
|
|
continue;
|
|
}
|
|
tree.deleteChannel(channel);
|
|
}
|
|
}
|
|
handleCommandChannelHide(json) {
|
|
let tree = this.connection.client.channelTree;
|
|
console.log(_translations.H8Ljrp8b || (_translations.H8Ljrp8b = tr("Got %d channel hides")), json.length);
|
|
for (let index = 0; index < json.length; index++) {
|
|
let channel = tree.findChannel(json[index]["cid"]);
|
|
if (!channel) {
|
|
console.error(_translations.wNE6Yk8v || (_translations.wNE6Yk8v = tr("Invalid channel on hide (Unknown channel)")));
|
|
continue;
|
|
}
|
|
tree.deleteChannel(channel);
|
|
}
|
|
}
|
|
handleCommandClientEnterView(json) {
|
|
json = json[0]; //Only one bulk
|
|
let tree = this.connection.client.channelTree;
|
|
let client;
|
|
let channel = tree.findChannel(json["ctid"]);
|
|
let old_channel = tree.findChannel(json["cfid"]);
|
|
client = tree.findClient(json["clid"]);
|
|
if (!client) {
|
|
if (parseInt(json["client_type_exact"]) == ClientType.CLIENT_MUSIC) {
|
|
client = new MusicClientEntry(parseInt(json["clid"]), json["client_nickname"]);
|
|
}
|
|
else {
|
|
client = new ClientEntry(parseInt(json["clid"]), json["client_nickname"]);
|
|
}
|
|
client.properties.client_type = parseInt(json["client_type"]);
|
|
client = tree.insertClient(client, channel);
|
|
}
|
|
else {
|
|
if (client == this.connection.client.getClient())
|
|
chat.channelChat().name = channel.channelName();
|
|
tree.moveClient(client, channel);
|
|
}
|
|
if (this.connection.client.controlBar.query_visible || client.properties.client_type != ClientType.CLIENT_QUERY) {
|
|
const own_channel = this.connection.client.getClient().currentChannel();
|
|
if (json["reasonid"] == ViewReasonId.VREASON_USER_ACTION) {
|
|
if (own_channel == channel)
|
|
if (old_channel)
|
|
sound.play(Sound.USER_ENTERED);
|
|
else
|
|
sound.play(Sound.USER_ENTERED_CONNECT);
|
|
if (old_channel) {
|
|
chat.serverChat().appendMessage(_translations.yBTs793E || (_translations.yBTs793E = tr("{0} appeared from {1} to {2}")), true, client.createChatTag(true), old_channel.generate_tag(true), channel.generate_tag(true));
|
|
}
|
|
else {
|
|
chat.serverChat().appendMessage(_translations.ld0SEFgV || (_translations.ld0SEFgV = tr("{0} connected to channel {1}")), true, client.createChatTag(true), channel.generate_tag(true));
|
|
}
|
|
}
|
|
else if (json["reasonid"] == ViewReasonId.VREASON_MOVED) {
|
|
if (own_channel == channel)
|
|
sound.play(Sound.USER_ENTERED_MOVED);
|
|
chat.serverChat().appendMessage(_translations.H2m5xkNS || (_translations.H2m5xkNS = tr("{0} appeared from {1} to {2}, moved by {3}")), true, client.createChatTag(true), old_channel ? old_channel.generate_tag(true) : undefined, channel.generate_tag(true), ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]));
|
|
}
|
|
else if (json["reasonid"] == ViewReasonId.VREASON_CHANNEL_KICK) {
|
|
if (own_channel == channel)
|
|
sound.play(Sound.USER_ENTERED_KICKED);
|
|
chat.serverChat().appendMessage(_translations.G8shumQI || (_translations.G8shumQI = tr("{0} appeared from {1} to {2}, kicked by {3}{4}")), true, client.createChatTag(true), old_channel ? old_channel.generate_tag(true) : undefined, channel.generate_tag(true), ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]), json["reasonmsg"] > 0 ? " (" + json["msg"] + ")" : "");
|
|
}
|
|
else {
|
|
console.warn(_translations.wGPL0vDb || (_translations.wGPL0vDb = tr("Unknown reasonid for %o")), json["reasonid"]);
|
|
}
|
|
}
|
|
let updates = [];
|
|
for (let key in json) {
|
|
if (key == "cfid")
|
|
continue;
|
|
if (key == "ctid")
|
|
continue;
|
|
if (key === "invokerid")
|
|
continue;
|
|
if (key === "invokername")
|
|
continue;
|
|
if (key === "invokeruid")
|
|
continue;
|
|
if (key === "reasonid")
|
|
continue;
|
|
updates.push({ key: key, value: json[key] });
|
|
}
|
|
client.updateVariables(...updates);
|
|
if (client instanceof LocalClientEntry)
|
|
this.connection.client.controlBar.updateVoice();
|
|
}
|
|
handleCommandClientLeftView(json) {
|
|
json = json[0]; //Only one bulk
|
|
let tree = this.connection.client.channelTree;
|
|
let client = tree.findClient(json["clid"]);
|
|
if (!client) {
|
|
console.error(_translations.yddBhUW8 || (_translations.yddBhUW8 = tr("Unknown client left!")));
|
|
return 0;
|
|
}
|
|
if (client == this.connection.client.getClient()) {
|
|
if (json["reasonid"] == ViewReasonId.VREASON_BAN) {
|
|
this.connection.client.handleDisconnect(DisconnectReason.CLIENT_BANNED, json);
|
|
}
|
|
else if (json["reasonid"] == ViewReasonId.VREASON_SERVER_KICK) {
|
|
this.connection.client.handleDisconnect(DisconnectReason.CLIENT_KICKED, json);
|
|
}
|
|
else if (json["reasonid"] == ViewReasonId.VREASON_SERVER_SHUTDOWN) {
|
|
this.connection.client.handleDisconnect(DisconnectReason.SERVER_CLOSED, json);
|
|
}
|
|
else if (json["reasonid"] == ViewReasonId.VREASON_SERVER_STOPPED) {
|
|
this.connection.client.handleDisconnect(DisconnectReason.SERVER_CLOSED, json);
|
|
}
|
|
else
|
|
this.connection.client.handleDisconnect(DisconnectReason.UNKNOWN, json);
|
|
return;
|
|
}
|
|
if (this.connection.client.controlBar.query_visible || client.properties.client_type != ClientType.CLIENT_QUERY) {
|
|
const own_channel = this.connection.client.getClient().currentChannel();
|
|
let channel_from = tree.findChannel(json["cfid"]);
|
|
let channel_to = tree.findChannel(json["ctid"]);
|
|
if (json["reasonid"] == ViewReasonId.VREASON_USER_ACTION) {
|
|
chat.serverChat().appendMessage(_translations.dQP_9bwx || (_translations.dQP_9bwx = tr("{0} disappeared from {1} to {2}")), true, client.createChatTag(true), channel_from.generate_tag(true), channel_to.generate_tag(true));
|
|
if (channel_from == own_channel)
|
|
sound.play(Sound.USER_LEFT);
|
|
}
|
|
else if (json["reasonid"] == ViewReasonId.VREASON_SERVER_LEFT) {
|
|
chat.serverChat().appendMessage(_translations.wiWY_KPc || (_translations.wiWY_KPc = tr("{0} left the server{1}")), true, client.createChatTag(true), json["reasonmsg"] ? " (" + json["reasonmsg"] + ")" : "");
|
|
if (channel_from == own_channel)
|
|
sound.play(Sound.USER_LEFT_DISCONNECT);
|
|
}
|
|
else if (json["reasonid"] == ViewReasonId.VREASON_SERVER_KICK) {
|
|
chat.serverChat().appendError(_translations.Oru0Sje5 || (_translations.Oru0Sje5 = tr("{0} was kicked from the server by {1}.{2}")), client.createChatTag(true), ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]), json["reasonmsg"] ? " (" + json["reasonmsg"] + ")" : "");
|
|
if (channel_from == own_channel)
|
|
sound.play(Sound.USER_LEFT_KICKED_SERVER);
|
|
}
|
|
else if (json["reasonid"] == ViewReasonId.VREASON_CHANNEL_KICK) {
|
|
chat.serverChat().appendError(_translations.zwEFh23K || (_translations.zwEFh23K = tr("{0} was kicked from your channel by {1}.{2}")), client.createChatTag(true), ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]), json["reasonmsg"] ? " (" + json["reasonmsg"] + ")" : "");
|
|
if (channel_from == own_channel)
|
|
sound.play(Sound.USER_LEFT_KICKED_CHANNEL);
|
|
}
|
|
else if (json["reasonid"] == ViewReasonId.VREASON_BAN) {
|
|
//"Mulus" was banned for 1 second from the server by "WolverinDEV" (Sry brauchte kurz ein opfer :P <3 (Nohomo))
|
|
let duration = "permanently";
|
|
if (json["bantime"])
|
|
duration = "for " + formatDate(Number.parseInt(json["bantime"]));
|
|
chat.serverChat().appendError(_translations.FKmT074Q || (_translations.FKmT074Q = tr("{0} was banned {1} by {2}.{3}")), client.createChatTag(true), duration, ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]), json["reasonmsg"] ? " (" + json["reasonmsg"] + ")" : "");
|
|
if (channel_from == own_channel)
|
|
sound.play(Sound.USER_LEFT_BANNED);
|
|
}
|
|
else {
|
|
console.error(_translations.vTWtjrtn || (_translations.vTWtjrtn = tr("Unknown client left reason!")));
|
|
}
|
|
}
|
|
tree.deleteClient(client);
|
|
}
|
|
handleNotifyClientMoved(json) {
|
|
json = json[0]; //Only one bulk
|
|
let tree = this.connection.client.channelTree;
|
|
let client = tree.findClient(json["clid"]);
|
|
let channel_to = tree.findChannel(json["ctid"]);
|
|
let channel_from = tree.findChannel(json["cfid"]);
|
|
if (!client) {
|
|
console.error(_translations.mP6ACPD5 || (_translations.mP6ACPD5 = tr("Unknown client move (Client)!")));
|
|
return 0;
|
|
}
|
|
if (!channel_to) {
|
|
console.error(_translations.JApmNtuz || (_translations.JApmNtuz = tr("Unknown client move (Channel to)!")));
|
|
return 0;
|
|
}
|
|
if (!channel_from) //Not critical
|
|
console.error(_translations.DA87rt4L || (_translations.DA87rt4L = tr("Unknown client move (Channel from)!")));
|
|
let self = client instanceof LocalClientEntry;
|
|
let current_clients;
|
|
if (self) {
|
|
chat.channelChat().name = channel_to.channelName();
|
|
current_clients = client.channelTree.clientsByChannel(client.currentChannel());
|
|
this.connection.client.controlBar.updateVoice(channel_to);
|
|
}
|
|
tree.moveClient(client, channel_to);
|
|
for (const entry of current_clients || [])
|
|
if (entry !== client)
|
|
entry.getAudioController().stopAudio(true);
|
|
const own_channel = this.connection.client.getClient().currentChannel();
|
|
if (json["reasonid"] == ViewReasonId.VREASON_MOVED) {
|
|
chat.serverChat().appendMessage(self ? _translations.NcqTc0dn || (_translations.NcqTc0dn = tr("You was moved by {3} from channel {1} to {2}")) : _translations.qeasUFNW || (_translations.qeasUFNW = tr("{0} was moved from channel {1} to {2} by {3}")), true, client.createChatTag(true), channel_from ? channel_from.generate_tag(true) : undefined, channel_to.generate_tag(true), ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]));
|
|
if (self)
|
|
sound.play(Sound.USER_MOVED_SELF);
|
|
else if (own_channel == channel_to)
|
|
sound.play(Sound.USER_ENTERED_MOVED);
|
|
else if (own_channel == channel_from)
|
|
sound.play(Sound.USER_LEFT_MOVED);
|
|
}
|
|
else if (json["reasonid"] == ViewReasonId.VREASON_USER_ACTION) {
|
|
chat.serverChat().appendMessage(self ? _translations.dtUR49jo || (_translations.dtUR49jo = tr("You switched from channel {1} to {2}")) : _translations.YFVVq1QK || (_translations.YFVVq1QK = tr("{0} switched from channel {1} to {2}")), true, client.createChatTag(true), channel_from ? channel_from.generate_tag(true) : undefined, channel_to.generate_tag(true));
|
|
if (self) { } //If we do an action we wait for the error response
|
|
else if (own_channel == channel_to)
|
|
sound.play(Sound.USER_ENTERED);
|
|
else if (own_channel == channel_from)
|
|
sound.play(Sound.USER_LEFT);
|
|
}
|
|
else if (json["reasonid"] == ViewReasonId.VREASON_CHANNEL_KICK) {
|
|
chat.serverChat().appendMessage(self ? _translations.icEV8veV || (_translations.icEV8veV = tr("You got kicked out of the channel {1} to channel {2} by {3}{4}")) : _translations.mui2Bvyn || (_translations.mui2Bvyn = tr("{0} got kicked from channel {1} to {2} by {3}{4}")), true, client.createChatTag(true), channel_from ? channel_from.generate_tag(true) : undefined, channel_to.generate_tag(true), ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]), json["reasonmsg"] ? " (" + json["reasonmsg"] + ")" : "");
|
|
if (self) {
|
|
sound.play(Sound.CHANNEL_KICKED);
|
|
}
|
|
else if (own_channel == channel_to)
|
|
sound.play(Sound.USER_ENTERED_KICKED);
|
|
else if (own_channel == channel_from)
|
|
sound.play(Sound.USER_LEFT_KICKED_CHANNEL);
|
|
}
|
|
else {
|
|
console.warn(_translations.v33Oxo4X || (_translations.v33Oxo4X = tr("Unknown reason id %o")), json["reasonid"]);
|
|
}
|
|
}
|
|
handleNotifyChannelMoved(json) {
|
|
json = json[0]; //Only one bulk
|
|
for (let key in json)
|
|
console.log("Key: " + key + " Value: " + json[key]);
|
|
let tree = this.connection.client.channelTree;
|
|
let channel = tree.findChannel(json["cid"]);
|
|
if (!channel) {
|
|
console.error(_translations.mzojB4K9 || (_translations.mzojB4K9 = tr("Unknown channel move (Channel)!")));
|
|
return 0;
|
|
}
|
|
let prev = tree.findChannel(json["order"]);
|
|
if (!prev && json["order"] != 0) {
|
|
console.error(_translations.ZF_a7vjl || (_translations.ZF_a7vjl = tr("Unknown channel move (prev)!")));
|
|
return 0;
|
|
}
|
|
let parent = tree.findChannel(json["cpid"]);
|
|
if (!parent && json["cpid"] != 0) {
|
|
console.error(_translations.JOU61YqT || (_translations.JOU61YqT = tr("Unknown channel move (parent)!")));
|
|
return 0;
|
|
}
|
|
tree.moveChannel(channel, prev, parent);
|
|
}
|
|
handleNotifyChannelEdited(json) {
|
|
json = json[0]; //Only one bulk
|
|
let tree = this.connection.client.channelTree;
|
|
let channel = tree.findChannel(json["cid"]);
|
|
if (!channel) {
|
|
console.error(_translations.c6E0QRE0 || (_translations.c6E0QRE0 = tr("Unknown channel edit (Channel)!")));
|
|
return 0;
|
|
}
|
|
let updates = [];
|
|
for (let key in json) {
|
|
if (key === "cid")
|
|
continue;
|
|
if (key === "invokerid")
|
|
continue;
|
|
if (key === "invokername")
|
|
continue;
|
|
if (key === "invokeruid")
|
|
continue;
|
|
if (key === "reasonid")
|
|
continue;
|
|
updates.push({ key: key, value: json[key] });
|
|
}
|
|
channel.updateVariables(...updates);
|
|
}
|
|
handleNotifyTextMessage(json) {
|
|
json = json[0]; //Only one bulk
|
|
//TODO chat format?
|
|
let mode = json["targetmode"];
|
|
if (mode == 1) {
|
|
let invoker = this.connection.client.channelTree.findClient(json["invokerid"]);
|
|
let target = this.connection.client.channelTree.findClient(json["target"]);
|
|
if (!invoker) { //TODO spawn chat (Client is may invisible)
|
|
console.error(_translations.HvOzEfon || (_translations.HvOzEfon = tr("Got private message from invalid client!")));
|
|
return;
|
|
}
|
|
if (!target) { //TODO spawn chat (Client is may invisible)
|
|
console.error(_translations.WjJ09uxh || (_translations.WjJ09uxh = tr("Got private message from invalid client!")));
|
|
return;
|
|
}
|
|
if (invoker == this.connection.client.getClient()) {
|
|
sound.play(Sound.MESSAGE_SEND, { default_volume: .5 });
|
|
target.chat(true).appendMessage("{0}: {1}", true, this.connection.client.getClient().createChatTag(true), MessageHelper.bbcode_chat(json["msg"]));
|
|
}
|
|
else {
|
|
sound.play(Sound.MESSAGE_RECEIVED, { default_volume: .5 });
|
|
invoker.chat(true).appendMessage("{0}: {1}", true, ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"], true), MessageHelper.bbcode_chat(json["msg"]));
|
|
}
|
|
}
|
|
else if (mode == 2) {
|
|
if (json["invokerid"] == this.connection.client.clientId)
|
|
sound.play(Sound.MESSAGE_SEND, { default_volume: .5 });
|
|
else
|
|
sound.play(Sound.MESSAGE_RECEIVED, { default_volume: .5 });
|
|
chat.channelChat().appendMessage("{0}: {1}", true, ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"], true), MessageHelper.bbcode_chat(json["msg"]));
|
|
}
|
|
else if (mode == 3) {
|
|
chat.serverChat().appendMessage("{0}: {1}", true, ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"], true), MessageHelper.bbcode_chat(json["msg"]));
|
|
}
|
|
}
|
|
handleNotifyClientUpdated(json) {
|
|
json = json[0]; //Only one bulk
|
|
let client = this.connection.client.channelTree.findClient(json["clid"]);
|
|
if (!client) {
|
|
console.error(_translations.Wy_4Q6WO || (_translations.Wy_4Q6WO = tr("Tried to update an non existing client")));
|
|
return;
|
|
}
|
|
let updates = [];
|
|
for (let key in json) {
|
|
if (key == "clid")
|
|
continue;
|
|
updates.push({ key: key, value: json[key] });
|
|
}
|
|
client.updateVariables(...updates);
|
|
if (this.connection.client.selectInfo.currentSelected == client)
|
|
this.connection.client.selectInfo.update();
|
|
}
|
|
handleNotifyServerEdited(json) {
|
|
json = json[0];
|
|
let updates = [];
|
|
for (let key in json) {
|
|
if (key === "invokerid")
|
|
continue;
|
|
if (key === "invokername")
|
|
continue;
|
|
if (key === "invokeruid")
|
|
continue;
|
|
if (key === "reasonid")
|
|
continue;
|
|
updates.push({ key: key, value: json[key] });
|
|
}
|
|
this.connection.client.channelTree.server.updateVariables(false, ...updates);
|
|
if (this.connection.client.selectInfo.currentSelected == this.connection.client.channelTree.server)
|
|
this.connection.client.selectInfo.update();
|
|
}
|
|
handleNotifyServerUpdated(json) {
|
|
json = json[0];
|
|
let updates = [];
|
|
for (let key in json) {
|
|
if (key === "invokerid")
|
|
continue;
|
|
if (key === "invokername")
|
|
continue;
|
|
if (key === "invokeruid")
|
|
continue;
|
|
if (key === "reasonid")
|
|
continue;
|
|
updates.push({ key: key, value: json[key] });
|
|
}
|
|
this.connection.client.channelTree.server.updateVariables(true, ...updates);
|
|
let info = this.connection.client.selectInfo;
|
|
if (info.currentSelected instanceof ServerEntry)
|
|
info.update();
|
|
}
|
|
handleNotifyMusicPlayerInfo(json) {
|
|
json = json[0];
|
|
let bot = this.connection.client.channelTree.find_client_by_dbid(json["bot_id"]);
|
|
if (!bot || !(bot instanceof MusicClientEntry)) {
|
|
log.warn(LogCategory.CLIENT, _translations.bVJCAzRK || (_translations.bVJCAzRK = tr("Got music player info for unknown or invalid bot! (ID: %i, Entry: %o)")), json["bot_id"], bot);
|
|
return;
|
|
}
|
|
bot.handlePlayerInfo(json);
|
|
}
|
|
handleNotifyClientPoke(json) {
|
|
json = json[0];
|
|
Modals.spawnPoke({
|
|
id: parseInt(json["invokerid"]),
|
|
name: json["invokername"],
|
|
unique_id: json["invokeruid"]
|
|
}, json["msg"]);
|
|
sound.play(Sound.USER_POKED_SELF);
|
|
}
|
|
//TODO server chat message
|
|
handleNotifyServerGroupClientAdd(json) {
|
|
json = json[0];
|
|
const self = this.connection.client.getClient();
|
|
if (json["clid"] == self.clientId())
|
|
sound.play(Sound.GROUP_SERVER_ASSIGNED_SELF);
|
|
}
|
|
//TODO server chat message
|
|
handleNotifyServerGroupClientRemove(json) {
|
|
json = json[0];
|
|
const self = this.connection.client.getClient();
|
|
if (json["clid"] == self.clientId()) {
|
|
sound.play(Sound.GROUP_SERVER_REVOKED_SELF);
|
|
}
|
|
else {
|
|
}
|
|
}
|
|
//TODO server chat message
|
|
handleNotifyClientChannelGroupChanged(json) {
|
|
json = json[0];
|
|
const self = this.connection.client.getClient();
|
|
if (json["clid"] == self.clientId()) {
|
|
sound.play(Sound.GROUP_CHANNEL_CHANGED_SELF);
|
|
}
|
|
}
|
|
}
|
|
connection_3.ConnectionCommandHandler = ConnectionCommandHandler;
|
|
})(connection || (connection = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["2d8c483dec3a421dac4e03bac009ca3c2324d36b3e3cfa6e28d50456f043f9df"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["2d8c483dec3a421dac4e03bac009ca3c2324d36b3e3cfa6e28d50456f043f9df"] = "2d8c483dec3a421dac4e03bac009ca3c2324d36b3e3cfa6e28d50456f043f9df";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "kQ6oVqzx", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHelper.ts (141,67)" }, { name: "UD2e8fqR", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHelper.ts (173,63)" }, { name: "GA8yGY40", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHelper.ts (192,67)" }, { name: "YAugHF1M", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHelper.ts (222,63)" }, { name: "VQ3mQXnH", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/CommandHelper.ts (243,63)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var connection;
|
|
(function (connection_4) {
|
|
class CommandHelper extends connection_4.AbstractCommandHandler {
|
|
constructor(connection) {
|
|
super(connection);
|
|
this._callbacks_namefromuid = [];
|
|
this.volatile_handler_boss = false;
|
|
this.ignore_consumed = true;
|
|
}
|
|
initialize() {
|
|
this.connection.command_handler_boss().register_handler(this);
|
|
/* notifyquerylist */
|
|
}
|
|
handle_command(command) {
|
|
if (command.command == "notifyclientnamefromuid")
|
|
this.handle_notifyclientnamefromuid(command.arguments);
|
|
else
|
|
return false;
|
|
return true;
|
|
}
|
|
joinChannel(channel, password) {
|
|
return this.connection.send_command("clientmove", {
|
|
"clid": this.connection.client.getClientId(),
|
|
"cid": channel.getChannelId(),
|
|
"cpw": password || ""
|
|
});
|
|
}
|
|
sendMessage(message, type, target) {
|
|
if (type == ChatType.SERVER)
|
|
return this.connection.send_command("sendtextmessage", { "targetmode": 3, "target": 0, "msg": message });
|
|
else if (type == ChatType.CHANNEL)
|
|
return this.connection.send_command("sendtextmessage", { "targetmode": 2, "target": target.getChannelId(), "msg": message });
|
|
else if (type == ChatType.CLIENT)
|
|
return this.connection.send_command("sendtextmessage", { "targetmode": 1, "target": target.clientId(), "msg": message });
|
|
}
|
|
updateClient(key, value) {
|
|
let data = {};
|
|
data[key] = value;
|
|
return this.connection.send_command("clientupdate", data);
|
|
}
|
|
info_from_uid(...uid) {
|
|
let uids = [...uid];
|
|
for (let p of this._callbacks_namefromuid)
|
|
if (p.keys == uids)
|
|
return p.promise;
|
|
let req = {};
|
|
req.keys = uids;
|
|
req.response = new Array(uids.length);
|
|
req.promise = new LaterPromise();
|
|
for (let uid of uids) {
|
|
this.connection.send_command("clientgetnamefromuid", {
|
|
cluid: uid
|
|
}).catch(req.promise.function_rejected());
|
|
}
|
|
this._callbacks_namefromuid.push(req);
|
|
return req.promise;
|
|
}
|
|
request_query_list(server_id = undefined) {
|
|
return new Promise((resolve, reject) => {
|
|
const single_handler = {
|
|
command: "notifyquerylist",
|
|
function: command => {
|
|
const json = command.arguments;
|
|
const result = {};
|
|
result.flag_all = json[0]["flag_all"];
|
|
result.flag_own = json[0]["flag_own"];
|
|
result.queries = [];
|
|
for (const entry of json) {
|
|
const rentry = {};
|
|
rentry.bounded_server = entry["client_bounded_server"];
|
|
rentry.username = entry["client_login_name"];
|
|
rentry.unique_id = entry["client_unique_identifier"];
|
|
result.queries.push(rentry);
|
|
}
|
|
resolve(result);
|
|
return true;
|
|
}
|
|
};
|
|
this.handler_boss.register_single_handler(single_handler);
|
|
let data = {};
|
|
if (server_id !== undefined)
|
|
data["server_id"] = server_id;
|
|
this.connection.send_command("querylist", data).catch(error => {
|
|
this.handler_boss.remove_single_handler(single_handler);
|
|
if (error instanceof CommandResult) {
|
|
if (error.id == ErrorID.EMPTY_RESULT) {
|
|
resolve(undefined);
|
|
return;
|
|
}
|
|
}
|
|
reject(error);
|
|
});
|
|
});
|
|
}
|
|
request_playlist_list() {
|
|
return new Promise((resolve, reject) => {
|
|
const single_handler = {
|
|
command: "notifyplaylistlist",
|
|
function: command => {
|
|
const json = command.arguments;
|
|
const result = [];
|
|
for (const entry of json) {
|
|
try {
|
|
result.push({
|
|
playlist_id: parseInt(entry["playlist_id"]),
|
|
playlist_bot_id: parseInt(entry["playlist_bot_id"]),
|
|
playlist_title: entry["playlist_title"],
|
|
playlist_type: parseInt(entry["playlist_type"]),
|
|
playlist_owner_dbid: parseInt(entry["playlist_owner_dbid"]),
|
|
playlist_owner_name: entry["playlist_owner_name"],
|
|
needed_power_modify: parseInt(entry["needed_power_modify"]),
|
|
needed_power_permission_modify: parseInt(entry["needed_power_permission_modify"]),
|
|
needed_power_delete: parseInt(entry["needed_power_delete"]),
|
|
needed_power_song_add: parseInt(entry["needed_power_song_add"]),
|
|
needed_power_song_move: parseInt(entry["needed_power_song_move"]),
|
|
needed_power_song_remove: parseInt(entry["needed_power_song_remove"])
|
|
});
|
|
}
|
|
catch (error) {
|
|
log.error(LogCategory.NETWORKING, _translations.kQ6oVqzx || (_translations.kQ6oVqzx = tr("Failed to parse playlist entry: %o")), error);
|
|
}
|
|
}
|
|
resolve(result);
|
|
return true;
|
|
}
|
|
};
|
|
this.handler_boss.register_single_handler(single_handler);
|
|
this.connection.send_command("playlistlist").catch(error => {
|
|
this.handler_boss.remove_single_handler(single_handler);
|
|
if (error instanceof CommandResult) {
|
|
if (error.id == ErrorID.EMPTY_RESULT) {
|
|
resolve([]);
|
|
return;
|
|
}
|
|
}
|
|
reject(error);
|
|
});
|
|
});
|
|
}
|
|
request_playlist_songs(playlist_id) {
|
|
return new Promise((resolve, reject) => {
|
|
const single_handler = {
|
|
command: "notifyplaylistsonglist",
|
|
function: command => {
|
|
const json = command.arguments;
|
|
if (json[0]["playlist_id"] != playlist_id) {
|
|
log.error(LogCategory.NETWORKING, _translations.UD2e8fqR || (_translations.UD2e8fqR = tr("Received invalid notification for playlist songs")));
|
|
return false;
|
|
}
|
|
const result = [];
|
|
for (const entry of json) {
|
|
try {
|
|
result.push({
|
|
song_id: parseInt(entry["song_id"]),
|
|
song_invoker: entry["song_invoker"],
|
|
song_previous_song_id: parseInt(entry["song_previous_song_id"]),
|
|
song_url: entry["song_url"],
|
|
song_url_loader: entry["song_url_loader"],
|
|
song_loaded: entry["song_loaded"] == true || entry["song_loaded"] == "1",
|
|
song_metadata: entry["song_metadata"]
|
|
});
|
|
}
|
|
catch (error) {
|
|
log.error(LogCategory.NETWORKING, _translations.GA8yGY40 || (_translations.GA8yGY40 = tr("Failed to parse playlist song entry: %o")), error);
|
|
}
|
|
}
|
|
resolve(result);
|
|
return true;
|
|
}
|
|
};
|
|
this.handler_boss.register_single_handler(single_handler);
|
|
this.connection.send_command("playlistsonglist", { playlist_id: playlist_id }).catch(error => {
|
|
this.handler_boss.remove_single_handler(single_handler);
|
|
if (error instanceof CommandResult) {
|
|
if (error.id == ErrorID.EMPTY_RESULT) {
|
|
resolve([]);
|
|
return;
|
|
}
|
|
}
|
|
reject(error);
|
|
});
|
|
});
|
|
}
|
|
request_playlist_info(playlist_id) {
|
|
return new Promise((resolve, reject) => {
|
|
const single_handler = {
|
|
command: "notifyplaylistinfo",
|
|
function: command => {
|
|
const json = command.arguments[0];
|
|
if (json["playlist_id"] != playlist_id) {
|
|
log.error(LogCategory.NETWORKING, _translations.YAugHF1M || (_translations.YAugHF1M = tr("Received invalid notification for playlist info")));
|
|
return;
|
|
}
|
|
try {
|
|
//resolve
|
|
resolve({
|
|
playlist_id: parseInt(json["playlist_id"]),
|
|
playlist_title: json["playlist_title"],
|
|
playlist_description: json["playlist_description"],
|
|
playlist_type: parseInt(json["playlist_type"]),
|
|
playlist_owner_dbid: parseInt(json["playlist_owner_dbid"]),
|
|
playlist_owner_name: json["playlist_owner_name"],
|
|
playlist_flag_delete_played: json["playlist_flag_delete_played"] == true || json["playlist_flag_delete_played"] == "1",
|
|
playlist_flag_finished: json["playlist_flag_finished"] == true || json["playlist_flag_finished"] == "1",
|
|
playlist_replay_mode: parseInt(json["playlist_replay_mode"]),
|
|
playlist_current_song_id: parseInt(json["playlist_current_song_id"]),
|
|
});
|
|
}
|
|
catch (error) {
|
|
log.error(LogCategory.NETWORKING, _translations.VQ3mQXnH || (_translations.VQ3mQXnH = tr("Failed to parse playlist info: %o")), error);
|
|
reject("failed to parse info");
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
this.handler_boss.register_single_handler(single_handler);
|
|
this.connection.send_command("playlistinfo", { playlist_id: playlist_id }).catch(error => {
|
|
this.handler_boss.remove_single_handler(single_handler);
|
|
reject(error);
|
|
});
|
|
});
|
|
}
|
|
/**
|
|
* @deprecated
|
|
* Its just a workaround for the query management.
|
|
* There is no garante that the whoami trick will work forever
|
|
*/
|
|
current_virtual_server_id() {
|
|
if (this._who_am_i)
|
|
return Promise.resolve(parseInt(this._who_am_i["virtualserver_id"]));
|
|
return new Promise((resolve, reject) => {
|
|
const single_handler = {
|
|
function: command => {
|
|
if (command.command != "")
|
|
return false;
|
|
this._who_am_i = command.arguments[0];
|
|
resolve(parseInt(this._who_am_i["virtualserver_id"]));
|
|
return true;
|
|
}
|
|
};
|
|
this.handler_boss.register_single_handler(single_handler);
|
|
this.connection.send_command("whoami").catch(error => {
|
|
this.handler_boss.remove_single_handler(single_handler);
|
|
reject(error);
|
|
});
|
|
});
|
|
}
|
|
handle_notifyclientnamefromuid(json) {
|
|
for (let entry of json) {
|
|
let info = {};
|
|
info.client_unique_id = entry["cluid"];
|
|
info.client_nickname = entry["clname"];
|
|
info.client_database_id = parseInt(entry["cldbid"]);
|
|
for (let elm of this._callbacks_namefromuid.slice(0)) {
|
|
let unset = 0;
|
|
for (let index = 0; index < elm.keys.length; index++) {
|
|
if (elm.keys[index] == info.client_unique_id) {
|
|
elm.response[index] = info;
|
|
}
|
|
if (elm.response[index] == undefined)
|
|
unset++;
|
|
}
|
|
if (unset == 0) {
|
|
this._callbacks_namefromuid.remove(elm);
|
|
elm.promise.resolved(elm.response);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
connection_4.CommandHelper = CommandHelper;
|
|
})(connection || (connection = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["e2e8defd9f6e149e9be9fc5c1a7241df7e196dd487817e50265229048abf6e85"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["e2e8defd9f6e149e9be9fc5c1a7241df7e196dd487817e50265229048abf6e85"] = "e2e8defd9f6e149e9be9fc5c1a7241df7e196dd487817e50265229048abf6e85";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "CJwFvFn2", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/HandshakeHandler.ts (57,39)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var connection;
|
|
(function (connection) {
|
|
class HandshakeHandler {
|
|
constructor(profile, name, password) {
|
|
this.failed = false;
|
|
this.profile = profile;
|
|
this.server_password = password;
|
|
this.name = name;
|
|
}
|
|
setConnection(con) {
|
|
this.connection = con;
|
|
}
|
|
startHandshake() {
|
|
this.handshake_handler = this.profile.spawn_identity_handshake_handler(this.connection);
|
|
if (!this.handshake_handler) {
|
|
this.handshake_failed("failed to create identity handler");
|
|
return;
|
|
}
|
|
this.handshake_handler.register_callback((flag, message) => {
|
|
if (flag)
|
|
this.handshake_finished();
|
|
else
|
|
this.handshake_failed(message);
|
|
});
|
|
this.handshake_handler.start_handshake();
|
|
}
|
|
handshake_failed(message) {
|
|
if (this.failed)
|
|
return;
|
|
this.failed = true;
|
|
this.connection.client.handleDisconnect(DisconnectReason.HANDSHAKE_FAILED, message);
|
|
}
|
|
handshake_finished(version) {
|
|
if (native_client && window["native"] && native.client_version && !version) {
|
|
native.client_version()
|
|
.then(this.handshake_finished.bind(this))
|
|
.catch(error => {
|
|
console.error(_translations.CJwFvFn2 || (_translations.CJwFvFn2 = tr("Failed to get version:")));
|
|
console.error(error);
|
|
this.handshake_finished("?.?.?");
|
|
});
|
|
return;
|
|
}
|
|
const git_version = settings.static_global("version", "unknown");
|
|
const browser_name = (navigator.browserSpecs || {})["name"] || " ";
|
|
let data = {
|
|
//TODO variables!
|
|
client_nickname: this.name,
|
|
client_platform: (browser_name ? browser_name + " " : "") + navigator.platform,
|
|
client_version: "TeaWeb " + git_version + " (" + navigator.userAgent + ")",
|
|
client_server_password: this.server_password,
|
|
client_browser_engine: navigator.product
|
|
};
|
|
if (version) {
|
|
data.client_version = "TeaClient ";
|
|
data.client_version += " " + version;
|
|
const os = require("os");
|
|
const arch_mapping = {
|
|
"x32": "32bit",
|
|
"x64": "64bit"
|
|
};
|
|
data.client_version += " " + (arch_mapping[os.arch()] || os.arch());
|
|
const os_mapping = {
|
|
"win32": "Windows",
|
|
"linux": "Linux"
|
|
};
|
|
data.client_platform = (os_mapping[os.platform()] || os.platform());
|
|
}
|
|
this.connection.send_command("clientinit", data).catch(error => {
|
|
this.connection.disconnect();
|
|
if (error instanceof CommandResult) {
|
|
if (error.id == 1028) {
|
|
this.connection.client.handleDisconnect(DisconnectReason.SERVER_REQUIRES_PASSWORD);
|
|
}
|
|
else {
|
|
this.connection.client.handleDisconnect(DisconnectReason.CLIENT_KICKED, error);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
connection.HandshakeHandler = HandshakeHandler;
|
|
})(connection || (connection = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["1b9ed7673e14dd8de7643659af5c37ce4645985797c33e3983c5ffa25edd9f06"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["1b9ed7673e14dd8de7643659af5c37ce4645985797c33e3983c5ffa25edd9f06"] = "1b9ed7673e14dd8de7643659af5c37ce4645985797c33e3983c5ffa25edd9f06";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "XIh9afcf", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (66,25)" }, { name: "fPGOWwqS", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (67,45)" }, { name: "fiJGXlYF", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (84,35)" }, { name: "BPotoUYu", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (93,45)" }, { name: "aUBpWo3n", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (101,33)" }, { name: "wsab4Jcl", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (105,58)" }, { name: "JKog4HLT", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (137,33)" }, { name: "rFu5r2U1", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (150,54)" }, { name: "I3PKHBHP", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (172,49)" }, { name: "X9OVEeHc", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (175,31)" }, { name: "ipPP5zUT", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (187,35)" }, { name: "fokLKoGU", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (192,33)" }, { name: "imXS9kEs", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (196,86)" }, { name: "sPbDX5nM", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (197,31)" }, { name: "oZM5phD0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (198,52)" }, { name: "FcNk8Ozi", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (207,33)" }, { name: "JnGgKqKA", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (210,50)" }, { name: "mU5d8pLA", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (216,50)" }, { name: "Hhxp4jDK", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (235,30)" }, { name: "pSyJGvv3", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (275,51)" }, { name: "t9MJiTw7", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (276,67)" }, { name: "pyddVpEH", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (283,59)" }, { name: "xQuEHP07", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/connection/ServerConnection.ts (285,43)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var ErrorID;
|
|
(function (ErrorID) {
|
|
ErrorID[ErrorID["PERMISSION_ERROR"] = 2568] = "PERMISSION_ERROR";
|
|
ErrorID[ErrorID["EMPTY_RESULT"] = 1281] = "EMPTY_RESULT";
|
|
ErrorID[ErrorID["PLAYLIST_IS_IN_USE"] = 8451] = "PLAYLIST_IS_IN_USE";
|
|
})(ErrorID || (ErrorID = {}));
|
|
class CommandResult {
|
|
constructor(json) {
|
|
this.json = json;
|
|
this.id = json["id"];
|
|
this.message = json["msg"];
|
|
this.extra_message = "";
|
|
if (json["extra_msg"])
|
|
this.extra_message = json["extra_msg"];
|
|
this.success = this.id == 0;
|
|
}
|
|
}
|
|
class ReturnListener {
|
|
}
|
|
var connection;
|
|
(function (connection) {
|
|
class ServerConnection extends connection.AbstractServerConnection {
|
|
constructor(client) {
|
|
super(client);
|
|
this._connectionState = ConnectionState.UNCONNECTED;
|
|
this._connect_timeout_timer = undefined;
|
|
this._connected = false;
|
|
this.on_connect = () => {
|
|
console.log(_translations.XIh9afcf || (_translations.XIh9afcf = tr("Socket connected")));
|
|
chat.serverChat().appendMessage(_translations.fPGOWwqS || (_translations.fPGOWwqS = tr("Logging in...")));
|
|
this._handshakeHandler.startHandshake();
|
|
};
|
|
this._socket = null;
|
|
this._retCodeIdx = 0;
|
|
this._retListener = [];
|
|
this._command_boss = new connection.ServerConnectionCommandBoss(this);
|
|
this._command_handler_default = new connection.ConnectionCommandHandler(this);
|
|
this._command_boss.register_handler(this._command_handler_default);
|
|
this.command_helper.initialize();
|
|
}
|
|
generateReturnCode() {
|
|
return (this._retCodeIdx++).toString();
|
|
}
|
|
connect(address, handshake, timeout) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
timeout = typeof (timeout) === "number" ? timeout : 0;
|
|
if (this._connect_timeout_timer) {
|
|
clearTimeout(this._connect_timeout_timer);
|
|
this._connect_timeout_timer = null;
|
|
try {
|
|
yield this.disconnect();
|
|
}
|
|
catch (error) {
|
|
console.error(_translations.fiJGXlYF || (_translations.fiJGXlYF = tr("Failed to close old connection properly. Error: %o")), error);
|
|
throw "failed to cleanup old connection";
|
|
}
|
|
}
|
|
this.updateConnectionState(ConnectionState.CONNECTING);
|
|
this._remote_address = address;
|
|
this._handshakeHandler = handshake;
|
|
this._handshakeHandler.setConnection(this);
|
|
this._connected = false;
|
|
chat.serverChat().appendMessage(_translations.BPotoUYu || (_translations.BPotoUYu = tr("Connecting to {0}:{1}")), true, address.host, address.port);
|
|
const self = this;
|
|
try {
|
|
let local_socket;
|
|
let local_timeout_timer;
|
|
local_timeout_timer = setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
console.log(_translations.aUBpWo3n || (_translations.aUBpWo3n = tr("Connect timeout triggered!")));
|
|
try {
|
|
yield this.disconnect();
|
|
}
|
|
catch (error) {
|
|
log.warn(LogCategory.NETWORKING, _translations.wsab4Jcl || (_translations.wsab4Jcl = tr("Failed to close connection after timeout had been triggered! (%o)")), error);
|
|
}
|
|
this.client.handleDisconnect(DisconnectReason.CONNECT_FAILURE);
|
|
}), timeout);
|
|
this._connect_timeout_timer = local_timeout_timer;
|
|
this._socket = (local_socket = new WebSocket('wss://' + address.host + ":" + address.port)); /* this may hangs */
|
|
clearTimeout(local_timeout_timer);
|
|
if (this._connect_timeout_timer == local_timeout_timer)
|
|
this._connect_timeout_timer = undefined;
|
|
if (this._socket != local_socket)
|
|
return; /* something had changed and we dont use this connection anymore! */
|
|
local_socket.onopen = () => {
|
|
if (this._socket != local_socket)
|
|
return; /* this socket isn't from interest anymore */
|
|
this._connected = true;
|
|
this.on_connect();
|
|
};
|
|
local_socket.onclose = event => {
|
|
if (this._socket != local_socket)
|
|
return; /* this socket isn't from interest anymore */
|
|
this.client.handleDisconnect(this._connected ? DisconnectReason.CONNECTION_CLOSED : DisconnectReason.CONNECT_FAILURE, {
|
|
code: event.code,
|
|
reason: event.reason,
|
|
event: event
|
|
});
|
|
};
|
|
local_socket.onerror = e => {
|
|
if (this._socket != local_socket)
|
|
return; /* this socket isn't from interest anymore */
|
|
console.log(_translations.JKog4HLT || (_translations.JKog4HLT = tr("Received web socket error: (%o)")), e);
|
|
};
|
|
local_socket.onmessage = msg => {
|
|
if (this._socket != local_socket)
|
|
return; /* this socket isn't from interest anymore */
|
|
self.handle_socket_message(msg.data);
|
|
};
|
|
this.updateConnectionState(ConnectionState.INITIALISING);
|
|
}
|
|
catch (e) {
|
|
try {
|
|
yield this.disconnect();
|
|
}
|
|
catch (error) {
|
|
log.warn(LogCategory.NETWORKING, _translations.rFu5r2U1 || (_translations.rFu5r2U1 = tr("Failed to close connection after connect attempt failed (%o)")), error);
|
|
}
|
|
this.client.handleDisconnect(DisconnectReason.CONNECT_FAILURE, e);
|
|
}
|
|
});
|
|
}
|
|
updateConnectionState(state) {
|
|
this._connectionState = state;
|
|
this.client.controlBar.update_connection_state();
|
|
}
|
|
disconnect(reason) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
if (typeof (reason) === "string") {
|
|
//TODO send disconnect reason
|
|
}
|
|
if (this._connectionState == ConnectionState.UNCONNECTED)
|
|
return;
|
|
this.updateConnectionState(ConnectionState.UNCONNECTED);
|
|
if (this._socket)
|
|
this._socket.close(3000 + 0xFF, _translations.I3PKHBHP || (_translations.I3PKHBHP = tr("request disconnect")));
|
|
this._socket = null;
|
|
for (let future of this._retListener)
|
|
future.reject(_translations.X9OVEeHc || (_translations.X9OVEeHc = tr("Connection closed")));
|
|
this._retListener = [];
|
|
this._retCodeIdx = 0;
|
|
this._connected = false;
|
|
});
|
|
}
|
|
handle_socket_message(data) {
|
|
if (typeof (data) === "string") {
|
|
let json;
|
|
try {
|
|
json = JSON.parse(data);
|
|
}
|
|
catch (e) {
|
|
console.error(_translations.ipPP5zUT || (_translations.ipPP5zUT = tr("Could not parse message json!")));
|
|
alert(e); // error in the above string (in this case, yes)!
|
|
return;
|
|
}
|
|
if (json["type"] === undefined) {
|
|
console.log(_translations.fokLKoGU || (_translations.fokLKoGU = tr("Missing data type!")));
|
|
return;
|
|
}
|
|
if (json["type"] === "command") {
|
|
let group = log.group(log.LogType.DEBUG, LogCategory.NETWORKING, _translations.imXS9kEs || (_translations.imXS9kEs = tr("Handling command '%s'")), json["command"]);
|
|
group.log(_translations.sPbDX5nM || (_translations.sPbDX5nM = tr("Handling command '%s'")), json["command"]);
|
|
group.group(log.LogType.TRACE, _translations.oZM5phD0 || (_translations.oZM5phD0 = tr("Json:"))).collapsed(true).log("%o", json).end();
|
|
this._command_boss.invoke_handle({
|
|
command: json["command"],
|
|
arguments: json["data"]
|
|
});
|
|
group.end();
|
|
}
|
|
else if (json["type"] === "WebRTC")
|
|
this.client.voiceConnection.handleControlPacket(json);
|
|
else {
|
|
console.log(_translations.FcNk8Ozi || (_translations.FcNk8Ozi = tr("Unknown command type %o")), json["type"]);
|
|
}
|
|
}
|
|
else {
|
|
log.warn(LogCategory.NETWORKING, _translations.JnGgKqKA || (_translations.JnGgKqKA = tr("Received unknown message of type %s. Dropping message")), typeof (data));
|
|
}
|
|
}
|
|
sendData(data) {
|
|
if (!this._socket || this._socket.readyState != 1) {
|
|
log.warn(LogCategory.NETWORKING, _translations.mU5d8pLA || (_translations.mU5d8pLA = tr("Tried to send on a invalid socket (%s)")), this._socket ? "invalid state (" + this._socket.readyState + ")" : "invalid socket");
|
|
return;
|
|
}
|
|
this._socket.send(data);
|
|
}
|
|
commandiefy(input) {
|
|
return JSON.stringify(input, (key, value) => {
|
|
switch (typeof value) {
|
|
case "boolean": return value == true ? "1" : "0";
|
|
case "function": return value();
|
|
default:
|
|
return value;
|
|
}
|
|
});
|
|
}
|
|
send_command(command, data, _options) {
|
|
if (!this._socket || !this.connected()) {
|
|
console.warn(_translations.Hhxp4jDK || (_translations.Hhxp4jDK = tr("Tried to send a command without a valid connection.")));
|
|
return;
|
|
}
|
|
const options = {};
|
|
Object.assign(options, connection.CommandOptionDefaults);
|
|
Object.assign(options, _options);
|
|
data = $.isArray(data) ? data : [data || {}];
|
|
const _this = this;
|
|
let result = new Promise((resolve, failed) => {
|
|
let _data = $.isArray(data) ? data : [data];
|
|
let retCode = _data[0]["return_code"] !== undefined ? _data[0].return_code : _this.generateReturnCode();
|
|
_data[0].return_code = retCode;
|
|
let listener = new ReturnListener();
|
|
listener.resolve = resolve;
|
|
listener.reject = failed;
|
|
listener.code = retCode;
|
|
listener.timeout = setTimeout(() => {
|
|
_this._retListener.remove(listener);
|
|
listener.reject("timeout");
|
|
}, 1500);
|
|
this._retListener.push(listener);
|
|
this._socket.send(this.commandiefy({
|
|
"type": "command",
|
|
"command": command,
|
|
"data": _data,
|
|
"flags": options.flagset.filter(entry => entry.length != 0)
|
|
}));
|
|
});
|
|
return new Promise((resolve, failed) => {
|
|
result.then(resolve).catch(ex => {
|
|
if (options.process_result) {
|
|
if (ex instanceof CommandResult) {
|
|
let res = ex;
|
|
if (!res.success) {
|
|
if (res.id == 2568) { //Permission error
|
|
res.message = (_translations.pSyJGvv3 || (_translations.pSyJGvv3 = tr("Insufficient client permissions. Failed on permission "))) + this.client.permissions.resolveInfo(res.json["failed_permid"]).name;
|
|
chat.serverChat().appendError(_translations.t9MJiTw7 || (_translations.t9MJiTw7 = tr("Insufficient client permissions. Failed on permission {}")), this.client.permissions.resolveInfo(res.json["failed_permid"]).name);
|
|
sound.play(Sound.ERROR_INSUFFICIENT_PERMISSIONS);
|
|
}
|
|
else {
|
|
chat.serverChat().appendError(res.extra_message.length == 0 ? res.message : res.extra_message);
|
|
}
|
|
}
|
|
}
|
|
else if (typeof (ex) === "string") {
|
|
chat.serverChat().appendError((_translations.pyddVpEH || (_translations.pyddVpEH = tr("Command execution results in "))) + ex);
|
|
}
|
|
else {
|
|
console.error(_translations.xQuEHP07 || (_translations.xQuEHP07 = tr("Invalid promise result type: %o. Result:")), typeof (ex));
|
|
console.error(ex);
|
|
}
|
|
}
|
|
failed(ex);
|
|
});
|
|
});
|
|
}
|
|
connected() {
|
|
return this._socket && this._socket.readyState == WebSocket.OPEN;
|
|
}
|
|
support_voice() {
|
|
return false;
|
|
}
|
|
voice_connection() {
|
|
return undefined;
|
|
}
|
|
command_handler_boss() {
|
|
return this._command_boss;
|
|
}
|
|
}
|
|
connection.ServerConnection = ServerConnection;
|
|
})(connection || (connection = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["f2cb5cb5e81993856f75ec86d34cbd93c355ed6cf975364a656f0337431d38c1"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["f2cb5cb5e81993856f75ec86d34cbd93c355ed6cf975364a656f0337431d38c1"] = "f2cb5cb5e81993856f75ec86d34cbd93c355ed6cf975364a656f0337431d38c1";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
// ASN.1 JavaScript decoder
|
|
// Copyright (c) 2008-2018 Lapo Luchini <lapo@lapo.it>
|
|
// Copyright (c) 2019-2019 Markus Hadenfeldt <git@teaspeak.de>
|
|
// Permission to use, copy, modify, and/or distribute this software for any
|
|
// purpose with or without fee is hereby granted, provided that the above
|
|
// copyright notice and this permission notice appear in all copies.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
var asn1;
|
|
(function (asn1) {
|
|
const ellipsis = "\u2026";
|
|
function string_cut(str, len) {
|
|
if (str.length > len)
|
|
str = str.substring(0, len) + ellipsis;
|
|
return str;
|
|
}
|
|
class Stream {
|
|
constructor(data, position) {
|
|
if (data instanceof Stream)
|
|
this.data = data.data;
|
|
else
|
|
this.data = data;
|
|
this.position = position;
|
|
}
|
|
length() {
|
|
if (this.data instanceof ArrayBuffer)
|
|
return this.data.byteLength;
|
|
return this.data.length;
|
|
}
|
|
get(position) {
|
|
if (position === undefined)
|
|
position = this.position++;
|
|
if (position >= this.length())
|
|
throw 'Requesting byte offset ' + this.position + ' on a stream of length ' + this.length();
|
|
return (typeof (this.data) === "string") ? this.data.charCodeAt(position) : this.data[position];
|
|
}
|
|
hexByte(byte) {
|
|
return Stream.HEX_DIGITS.charAt((byte >> 4) & 0xF) + Stream.HEX_DIGITS.charAt(byte & 0xF);
|
|
}
|
|
parseStringISO(start, end) {
|
|
let s = "";
|
|
for (let i = start; i < end; ++i)
|
|
s += String.fromCharCode(this.get(i));
|
|
return s;
|
|
}
|
|
parseStringUTF(start, end) {
|
|
let s = "";
|
|
for (let i = start; i < end;) {
|
|
let c = this.get(i++);
|
|
if (c < 128)
|
|
s += String.fromCharCode(c);
|
|
else if ((c > 191) && (c < 224))
|
|
s += String.fromCharCode(((c & 0x1F) << 6) | (this.get(i++) & 0x3F));
|
|
else
|
|
s += String.fromCharCode(((c & 0x0F) << 12) | ((this.get(i++) & 0x3F) << 6) | (this.get(i++) & 0x3F));
|
|
}
|
|
return s;
|
|
}
|
|
parseStringBMP(start, end) {
|
|
let str = "", hi, lo;
|
|
for (let i = start; i < end;) {
|
|
hi = this.get(i++);
|
|
lo = this.get(i++);
|
|
str += String.fromCharCode((hi << 8) | lo);
|
|
}
|
|
return str;
|
|
}
|
|
parseTime(start, end, shortYear) {
|
|
let s = this.parseStringISO(start, end), m = (shortYear ? Stream.reTimeS : Stream.reTimeL).exec(s);
|
|
if (!m)
|
|
return "Unrecognized time: " + s;
|
|
if (shortYear) {
|
|
// to avoid querying the timer, use the fixed range [1970, 2069]
|
|
// it will conform with ITU X.400 [-10, +40] sliding window until 2030
|
|
//m[1] = +m[1];
|
|
//m[1] += (parseInt(m[1]) < 70) ? 2000 : 1900;
|
|
throw "fixme!";
|
|
}
|
|
s = m[1] + "-" + m[2] + "-" + m[3] + " " + m[4];
|
|
if (m[5]) {
|
|
s += ":" + m[5];
|
|
if (m[6]) {
|
|
s += ":" + m[6];
|
|
if (m[7])
|
|
s += "." + m[7];
|
|
}
|
|
}
|
|
if (m[8]) {
|
|
s += " UTC";
|
|
if (m[8] != 'Z') {
|
|
s += m[8];
|
|
if (m[9])
|
|
s += ":" + m[9];
|
|
}
|
|
}
|
|
return s;
|
|
}
|
|
;
|
|
parseInteger(start, end) {
|
|
let current = this.get(start);
|
|
let negative = (current > 127);
|
|
let padding = negative ? 255 : 0;
|
|
let length;
|
|
let descriptor;
|
|
// skip unuseful bits (not allowed in DER)
|
|
while (current == padding && ++start < end)
|
|
current = this.get(start);
|
|
length = end - start;
|
|
if (length === 0)
|
|
return negative ? '-1' : '0';
|
|
// show bit length of huge integers
|
|
if (length > 4) {
|
|
descriptor = current;
|
|
length <<= 3; /* calculate bit length */
|
|
while (((descriptor ^ padding) & 0x80) == 0) {
|
|
descriptor <<= 1;
|
|
--length;
|
|
}
|
|
descriptor = "(" + length + " bit)\n";
|
|
}
|
|
// decode the integer
|
|
if (negative)
|
|
current = current - 256;
|
|
let number = "";
|
|
if (typeof (Int10) !== "undefined") {
|
|
let n = new Int10(current);
|
|
for (let i = start + 1; i < end; ++i)
|
|
n.mulAdd(256, this.get(i));
|
|
number = n.toString();
|
|
}
|
|
else {
|
|
let n = 0;
|
|
for (let i = start + 1; i < end; ++i) {
|
|
n <<= 8;
|
|
n += this.get(i);
|
|
}
|
|
number = n.toString();
|
|
}
|
|
return descriptor + number;
|
|
}
|
|
;
|
|
isASCII(start, end) {
|
|
for (let i = start; i < end; ++i) {
|
|
const c = this.get(i);
|
|
if (c < 32 || c > 176)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
;
|
|
parseBitString(start, end, maxLength) {
|
|
let unusedBit = this.get(start), lenBit = ((end - start - 1) << 3) - unusedBit, intro = "(" + lenBit + " bit)\n", s = "";
|
|
for (let i = start + 1; i < end; ++i) {
|
|
let b = this.get(i), skip = (i == end - 1) ? unusedBit : 0;
|
|
for (let j = 7; j >= skip; --j)
|
|
s += (b >> j) & 1 ? "1" : "0";
|
|
if (s.length > maxLength)
|
|
return intro + string_cut(s, maxLength);
|
|
}
|
|
return intro + s;
|
|
}
|
|
;
|
|
parseOctetString(start, end, maxLength) {
|
|
if (this.isASCII(start, end))
|
|
return string_cut(this.parseStringISO(start, end), maxLength);
|
|
let len = end - start, s = "(" + len + " byte)\n";
|
|
maxLength /= 2; // we work in bytes
|
|
if (len > maxLength)
|
|
end = start + maxLength;
|
|
for (let i = start; i < end; ++i)
|
|
s += this.hexByte(this.get(i));
|
|
if (len > maxLength)
|
|
s += ellipsis;
|
|
return s;
|
|
}
|
|
;
|
|
parseOID(start, end, maxLength) {
|
|
let s = '', n = new Int10(), bits = 0;
|
|
for (let i = start; i < end; ++i) {
|
|
let v = this.get(i);
|
|
n.mulAdd(128, v & 0x7F);
|
|
bits += 7;
|
|
if (!(v & 0x80)) { // finished
|
|
if (s === '') {
|
|
n = n.simplify();
|
|
if (n instanceof Int10) {
|
|
n.sub(80);
|
|
s = "2." + n.toString();
|
|
}
|
|
else {
|
|
let m = n < 80 ? n < 40 ? 0 : 1 : 2;
|
|
s = m + "." + (n - m * 40);
|
|
}
|
|
}
|
|
else
|
|
s += "." + n.toString();
|
|
if (s.length > maxLength)
|
|
return string_cut(s, maxLength);
|
|
n = new Int10();
|
|
bits = 0;
|
|
}
|
|
}
|
|
if (bits > 0)
|
|
s += ".incomplete";
|
|
/* FIXME
|
|
if (typeof oids === 'object') {
|
|
let oid = oids[s];
|
|
if (oid) {
|
|
if (oid.d) s += "\n" + oid.d;
|
|
if (oid.c) s += "\n" + oid.c;
|
|
if (oid.w) s += "\n(warning!)";
|
|
}
|
|
}
|
|
*/
|
|
return s;
|
|
}
|
|
;
|
|
}
|
|
Stream.HEX_DIGITS = "0123456789ABCDEF";
|
|
Stream.reTimeS = /^(\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/;
|
|
Stream.reTimeL = /^(\d\d\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/;
|
|
asn1.Stream = Stream;
|
|
let TagClass;
|
|
(function (TagClass) {
|
|
TagClass[TagClass["UNIVERSAL"] = 0] = "UNIVERSAL";
|
|
TagClass[TagClass["APPLICATION"] = 1] = "APPLICATION";
|
|
TagClass[TagClass["CONTEXT"] = 2] = "CONTEXT";
|
|
TagClass[TagClass["PRIVATE"] = 3] = "PRIVATE";
|
|
})(TagClass = asn1.TagClass || (asn1.TagClass = {}));
|
|
let TagType;
|
|
(function (TagType) {
|
|
TagType[TagType["EOC"] = 0] = "EOC";
|
|
TagType[TagType["BOOLEAN"] = 1] = "BOOLEAN";
|
|
TagType[TagType["INTEGER"] = 2] = "INTEGER";
|
|
TagType[TagType["BIT_STRING"] = 3] = "BIT_STRING";
|
|
TagType[TagType["OCTET_STRING"] = 4] = "OCTET_STRING";
|
|
TagType[TagType["NULL"] = 5] = "NULL";
|
|
TagType[TagType["OBJECT_IDENTIFIER"] = 6] = "OBJECT_IDENTIFIER";
|
|
TagType[TagType["ObjectDescriptor"] = 7] = "ObjectDescriptor";
|
|
TagType[TagType["EXTERNAL"] = 8] = "EXTERNAL";
|
|
TagType[TagType["REAL"] = 9] = "REAL";
|
|
TagType[TagType["ENUMERATED"] = 10] = "ENUMERATED";
|
|
TagType[TagType["EMBEDDED_PDV"] = 11] = "EMBEDDED_PDV";
|
|
TagType[TagType["UTF8String"] = 12] = "UTF8String";
|
|
TagType[TagType["SEQUENCE"] = 16] = "SEQUENCE";
|
|
TagType[TagType["SET"] = 17] = "SET";
|
|
TagType[TagType["NumericString"] = 18] = "NumericString";
|
|
TagType[TagType["PrintableString"] = 19] = "PrintableString";
|
|
TagType[TagType["TeletextString"] = 20] = "TeletextString";
|
|
TagType[TagType["VideotexString"] = 21] = "VideotexString";
|
|
TagType[TagType["IA5String"] = 22] = "IA5String";
|
|
TagType[TagType["UTCTime"] = 23] = "UTCTime";
|
|
TagType[TagType["GeneralizedTime"] = 24] = "GeneralizedTime";
|
|
TagType[TagType["GraphicString"] = 25] = "GraphicString";
|
|
TagType[TagType["VisibleString"] = 26] = "VisibleString";
|
|
TagType[TagType["GeneralString"] = 27] = "GeneralString";
|
|
TagType[TagType["UniversalString"] = 28] = "UniversalString";
|
|
TagType[TagType["BMPString"] = 30] = "BMPString";
|
|
})(TagType = asn1.TagType || (asn1.TagType = {}));
|
|
class ASN1Tag {
|
|
constructor(stream) {
|
|
let buf = stream.get();
|
|
this.tagClass = buf >> 6;
|
|
this.tagConstructed = ((buf & 0x20) !== 0);
|
|
this.tagNumber = buf & 0x1F;
|
|
if (this.tagNumber == 0x1F) { // long tag
|
|
let n = new Int10();
|
|
do {
|
|
buf = stream.get();
|
|
n.mulAdd(128, buf & 0x7F);
|
|
} while (buf & 0x80);
|
|
this.tagNumber = n.simplify();
|
|
}
|
|
}
|
|
isUniversal() {
|
|
return this.tagClass === 0x00;
|
|
}
|
|
;
|
|
isEOC() {
|
|
return this.tagClass === 0x00 && this.tagNumber === 0x00;
|
|
}
|
|
;
|
|
}
|
|
class ASN1 {
|
|
constructor(stream, header, length, tag, children) {
|
|
this.stream = stream;
|
|
this.header = header;
|
|
this.length = length;
|
|
this.tag = tag;
|
|
this.children = children;
|
|
}
|
|
content(max_length, type) {
|
|
if (this.tag === undefined)
|
|
return null;
|
|
if (max_length === undefined)
|
|
max_length = Infinity;
|
|
let content = this.posContent(), len = Math.abs(this.length);
|
|
if (!this.tag.isUniversal()) {
|
|
if (this.children !== null)
|
|
return "(" + this.children.length + " elem)";
|
|
return this.stream.parseOctetString(content, content + len, max_length);
|
|
}
|
|
switch (type || this.tag.tagNumber) {
|
|
case 0x01: // BOOLEAN
|
|
return (this.stream.get(content) === 0) ? "false" : "true";
|
|
case 0x02: // INTEGER
|
|
return this.stream.parseInteger(content, content + len);
|
|
case 0x03: // BIT_STRING
|
|
return this.children ? "(" + this.children.length + " elem)" :
|
|
this.stream.parseBitString(content, content + len, max_length);
|
|
case 0x04: // OCTET_STRING
|
|
return this.children ? "(" + this.children.length + " elem)" :
|
|
this.stream.parseOctetString(content, content + len, max_length);
|
|
//case 0x05: // NULL
|
|
case 0x06: // OBJECT_IDENTIFIER
|
|
return this.stream.parseOID(content, content + len, max_length);
|
|
//case 0x07: // ObjectDescriptor
|
|
//case 0x08: // EXTERNAL
|
|
//case 0x09: // REAL
|
|
//case 0x0A: // ENUMERATED
|
|
//case 0x0B: // EMBEDDED_PDV
|
|
case 0x10: // SEQUENCE
|
|
case 0x11: // SET
|
|
if (this.children !== null)
|
|
return "(" + this.children.length + " elem)";
|
|
else
|
|
return "(no elem)";
|
|
case 0x0C: // UTF8String
|
|
return string_cut(this.stream.parseStringUTF(content, content + len), max_length);
|
|
case 0x12: // NumericString
|
|
case 0x13: // PrintableString
|
|
case 0x14: // TeletexString
|
|
case 0x15: // VideotexString
|
|
case 0x16: // IA5String
|
|
//case 0x19: // GraphicString
|
|
case 0x1A: // VisibleString
|
|
//case 0x1B: // GeneralString
|
|
//case 0x1C: // UniversalString
|
|
return string_cut(this.stream.parseStringISO(content, content + len), max_length);
|
|
case 0x1E: // BMPString
|
|
return string_cut(this.stream.parseStringBMP(content, content + len), max_length);
|
|
case 0x17: // UTCTime
|
|
case 0x18: // GeneralizedTime
|
|
return this.stream.parseTime(content, content + len, (this.tag.tagNumber == 0x17));
|
|
}
|
|
return null;
|
|
}
|
|
;
|
|
typeName() {
|
|
switch (this.tag.tagClass) {
|
|
case 0: // universal
|
|
return TagType[this.tag.tagNumber] || ("Universal_" + this.tag.tagNumber.toString());
|
|
case 1:
|
|
return "Application_" + this.tag.tagNumber.toString();
|
|
case 2:
|
|
return "[" + this.tag.tagNumber.toString() + "]"; // Context
|
|
case 3:
|
|
return "Private_" + this.tag.tagNumber.toString();
|
|
}
|
|
}
|
|
;
|
|
toString() {
|
|
return this.typeName() + "@" + this.stream.position + "[header:" + this.header + ",length:" + this.length + ",sub:" + ((this.children === null) ? 'null' : this.children.length) + "]";
|
|
}
|
|
toPrettyString(indent) {
|
|
if (indent === undefined)
|
|
indent = '';
|
|
let s = indent + this.typeName() + " @" + this.stream.position;
|
|
if (this.length >= 0)
|
|
s += "+";
|
|
s += this.length;
|
|
if (this.tag.tagConstructed)
|
|
s += " (constructed)";
|
|
else if ((this.tag.isUniversal() && ((this.tag.tagNumber == 0x03) || (this.tag.tagNumber == 0x04))) && (this.children !== null))
|
|
s += " (encapsulates)";
|
|
let content = this.content();
|
|
if (content)
|
|
s += ": " + content.replace(/\n/g, '|');
|
|
s += "\n";
|
|
if (this.children !== null) {
|
|
indent += ' ';
|
|
for (let i = 0, max = this.children.length; i < max; ++i)
|
|
s += this.children[i].toPrettyString(indent);
|
|
}
|
|
return s;
|
|
}
|
|
;
|
|
posStart() {
|
|
return this.stream.position;
|
|
}
|
|
;
|
|
posContent() {
|
|
return this.stream.position + this.header;
|
|
}
|
|
;
|
|
posEnd() {
|
|
return this.stream.position + this.header + Math.abs(this.length);
|
|
}
|
|
;
|
|
static decodeLength(stream) {
|
|
let buf = stream.get();
|
|
const len = buf & 0x7F;
|
|
if (len == buf)
|
|
return len;
|
|
if (len > 6) // no reason to use Int10, as it would be a huge buffer anyways
|
|
throw "Length over 48 bits not supported at position " + (stream.position - 1);
|
|
if (len === 0)
|
|
return null; // undefined
|
|
buf = 0;
|
|
for (let i = 0; i < len; ++i)
|
|
buf = (buf << 8) + stream.get();
|
|
return buf;
|
|
}
|
|
;
|
|
static encodeLength(buffer, offset, length) {
|
|
if (length < 0x7F) {
|
|
buffer[offset] = length;
|
|
}
|
|
else {
|
|
buffer[offset] = 0x80;
|
|
let index = 1;
|
|
while (length > 0) {
|
|
buffer[offset + index++] = length & 0xFF;
|
|
length >>= 8;
|
|
buffer[offset] += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
asn1.ASN1 = ASN1;
|
|
function decode0(stream) {
|
|
const streamStart = new Stream(stream, 0); /* copy */
|
|
const tag = new ASN1Tag(stream);
|
|
let len = ASN1.decodeLength(stream);
|
|
const start = stream.position;
|
|
const length_header = start - streamStart.position;
|
|
let children = null;
|
|
const query_children = () => {
|
|
children = [];
|
|
if (len !== null) {
|
|
const end = start + len;
|
|
if (end > stream.length())
|
|
throw 'Container at offset ' + start + ' has a length of ' + len + ', which is past the end of the stream';
|
|
while (stream.position < end)
|
|
children[children.length] = decode0(stream);
|
|
if (stream.position != end)
|
|
throw 'Content size is not correct for container at offset ' + start;
|
|
}
|
|
else {
|
|
// undefined length
|
|
try {
|
|
while (true) {
|
|
const s = decode0(stream);
|
|
if (s.tag.isEOC())
|
|
break;
|
|
children[children.length] = s;
|
|
}
|
|
len = start - stream.position; // undefined lengths are represented as negative values
|
|
}
|
|
catch (e) {
|
|
throw 'Exception while decoding undefined length content at offset ' + start + ': ' + e;
|
|
}
|
|
}
|
|
};
|
|
if (tag.tagConstructed) {
|
|
// must have valid content
|
|
query_children();
|
|
}
|
|
else if (tag.isUniversal() && ((tag.tagNumber == 0x03) || (tag.tagNumber == 0x04))) {
|
|
// sometimes BitString and OctetString are used to encapsulate ASN.1
|
|
try {
|
|
if (tag.tagNumber == 0x03)
|
|
if (stream.get() != 0)
|
|
throw "BIT STRINGs with unused bits cannot encapsulate.";
|
|
query_children();
|
|
for (let i = 0; i < children.length; ++i)
|
|
if (children[i].tag.isEOC())
|
|
throw 'EOC is not supposed to be actual content.';
|
|
}
|
|
catch (e) {
|
|
// but silently ignore when they don't
|
|
children = null;
|
|
//DEBUG console.log('Could not decode structure at ' + start + ':', e);
|
|
}
|
|
}
|
|
if (children === null) {
|
|
if (len === null)
|
|
throw "We can't skip over an invalid tag with undefined length at offset " + start;
|
|
stream.position = start + Math.abs(len);
|
|
}
|
|
return new ASN1(streamStart, length_header, len, tag, children);
|
|
}
|
|
function decode(stream) {
|
|
return decode0(new Stream(stream, 0));
|
|
}
|
|
asn1.decode = decode;
|
|
})(asn1 || (asn1 = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["6bde651a74cdd2d05932f19f8fa848464eeb568c660e1ec7f4831839c5744f96"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["6bde651a74cdd2d05932f19f8fa848464eeb568c660e1ec7f4831839c5744f96"] = "6bde651a74cdd2d05932f19f8fa848464eeb568c660e1ec7f4831839c5744f96";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var hex;
|
|
(function (hex) {
|
|
function encode(buffer) {
|
|
let hexCodes = [];
|
|
let view = new DataView(buffer);
|
|
for (let i = 0; i < view.byteLength % 4; i++) {
|
|
let value = view.getUint32(i * 4);
|
|
let stringValue = value.toString(16);
|
|
let padding = '00000000';
|
|
let paddedValue = (padding + stringValue).slice(-padding.length);
|
|
hexCodes.push(paddedValue);
|
|
}
|
|
for (let i = (view.byteLength % 4) * 4; i < view.byteLength; i++) {
|
|
let value = view.getUint8(i).toString(16);
|
|
let padding = '00';
|
|
hexCodes.push((padding + value).slice(-padding.length));
|
|
}
|
|
return hexCodes.join("");
|
|
}
|
|
hex.encode = encode;
|
|
})(hex || (hex = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["b288268cc16167231d1a5363ccc537a63bd4a36290992fde1b42a45e12e530d4"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["b288268cc16167231d1a5363ccc537a63bd4a36290992fde1b42a45e12e530d4"] = "b288268cc16167231d1a5363ccc537a63bd4a36290992fde1b42a45e12e530d4";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "XlrqGY18", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/profiles/ConnectionProfile.ts (122,35)" }, { name: "w5lXn91e", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/profiles/ConnectionProfile.ts (142,38)" }, { name: "OUsmYl99", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/profiles/ConnectionProfile.ts (142,81)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var profiles;
|
|
(function (profiles_1) {
|
|
class ConnectionProfile {
|
|
constructor(id) {
|
|
this.selected_identity_type = "unset";
|
|
this.identities = {};
|
|
this.id = id;
|
|
}
|
|
selected_identity(current_type) {
|
|
if (!current_type)
|
|
current_type = this.selected_type();
|
|
if (current_type === undefined)
|
|
return undefined;
|
|
if (current_type == profiles_1.identities.IdentitifyType.TEAFORO) {
|
|
return profiles_1.identities.static_forum_identity();
|
|
}
|
|
else if (current_type == profiles_1.identities.IdentitifyType.TEAMSPEAK || current_type == profiles_1.identities.IdentitifyType.NICKNAME) {
|
|
return this.identities[this.selected_identity_type.toLowerCase()];
|
|
}
|
|
return undefined;
|
|
}
|
|
selected_type() {
|
|
return profiles_1.identities.IdentitifyType[this.selected_identity_type.toUpperCase()];
|
|
}
|
|
set_identity(type, identity) {
|
|
this.identities[profiles_1.identities.IdentitifyType[type].toLowerCase()] = identity;
|
|
}
|
|
spawn_identity_handshake_handler(connection) {
|
|
const identity = this.selected_identity();
|
|
if (!identity)
|
|
return undefined;
|
|
return identity.spawn_identity_handshake_handler(connection);
|
|
}
|
|
encode() {
|
|
const identity_data = {};
|
|
for (const key in this.identities)
|
|
if (this.identities[key])
|
|
identity_data[key] = this.identities[key].encode();
|
|
return JSON.stringify({
|
|
version: 1,
|
|
username: this.default_username,
|
|
password: this.default_password,
|
|
profile_name: this.profile_name,
|
|
identity_type: this.selected_identity_type,
|
|
identity_data: identity_data,
|
|
id: this.id
|
|
});
|
|
}
|
|
valid() {
|
|
const identity = this.selected_identity();
|
|
if (!identity || !identity.valid())
|
|
return false;
|
|
return this.default_username !== undefined;
|
|
}
|
|
}
|
|
profiles_1.ConnectionProfile = ConnectionProfile;
|
|
function decode_profile(data) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
data = JSON.parse(data);
|
|
if (data.version !== 1)
|
|
return "invalid version";
|
|
const result = new ConnectionProfile(data.id);
|
|
result.default_username = data.username;
|
|
result.default_password = data.password;
|
|
result.profile_name = data.profile_name;
|
|
result.selected_identity_type = (data.identity_type || "").toLowerCase();
|
|
if (data.identity_data) {
|
|
for (const key in data.identity_data) {
|
|
const type = profiles_1.identities.IdentitifyType[key.toUpperCase()];
|
|
const _data = data.identity_data[key];
|
|
if (type == undefined)
|
|
continue;
|
|
const identity = yield profiles_1.identities.decode_identity(type, _data);
|
|
if (identity == undefined)
|
|
continue;
|
|
result.identities[key.toLowerCase()] = identity;
|
|
}
|
|
}
|
|
return result;
|
|
});
|
|
}
|
|
let available_profiles = [];
|
|
function load() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
available_profiles = [];
|
|
const profiles_json = localStorage.getItem("profiles");
|
|
let profiles_data = profiles_json ? JSON.parse(profiles_json) : { version: 0 };
|
|
if (profiles_data.version === 0) {
|
|
profiles_data = {
|
|
version: 1,
|
|
profiles: []
|
|
};
|
|
}
|
|
if (profiles_data.version == 1) {
|
|
for (const profile_data of profiles_data.profiles) {
|
|
const profile = yield decode_profile(profile_data);
|
|
if (typeof (profile) === 'string') {
|
|
console.error(_translations.XlrqGY18 || (_translations.XlrqGY18 = tr("Failed to load profile. Reason: %s, Profile data: %s")), profile, profiles_data);
|
|
continue;
|
|
}
|
|
available_profiles.push(profile);
|
|
}
|
|
}
|
|
if (!find_profile("default")) { //Create a default profile and teaforo profile
|
|
{
|
|
const profile = create_new_profile("default", "default");
|
|
profile.default_password = "";
|
|
profile.default_username = "Another TeaSpeak user";
|
|
profile.profile_name = "Default Profile";
|
|
/* generate default identity */
|
|
try {
|
|
const identity = yield profiles_1.identities.TeaSpeakIdentity.generate_new();
|
|
profile.set_identity(profiles_1.identities.IdentitifyType.TEAMSPEAK, identity);
|
|
profile.selected_identity_type = profiles_1.identities.IdentitifyType[profiles_1.identities.IdentitifyType.TEAMSPEAK];
|
|
}
|
|
catch (error) {
|
|
createErrorModal(_translations.w5lXn91e || (_translations.w5lXn91e = tr("Failed to generate default identity")), _translations.OUsmYl99 || (_translations.OUsmYl99 = tr("Failed to generate default identity!<br>Please manually generate the identity within your settings => profiles"))).open();
|
|
}
|
|
}
|
|
{ /* forum identity (works only when connected to the forum) */
|
|
const profile = create_new_profile("TeaSpeak Forum", "teaforo");
|
|
profile.default_password = "";
|
|
profile.default_username = "Another TeaSpeak user";
|
|
profile.profile_name = "TeaSpeak Forum profile";
|
|
}
|
|
save();
|
|
}
|
|
});
|
|
}
|
|
profiles_1.load = load;
|
|
function create_new_profile(name, id) {
|
|
const profile = new ConnectionProfile(id || guid());
|
|
profile.profile_name = name;
|
|
profile.default_username = "Another TeaSpeak user";
|
|
available_profiles.push(profile);
|
|
return profile;
|
|
}
|
|
profiles_1.create_new_profile = create_new_profile;
|
|
let _requires_save = false;
|
|
function save() {
|
|
const profiles = [];
|
|
for (const profile of available_profiles)
|
|
profiles.push(profile.encode());
|
|
const data = JSON.stringify({
|
|
version: 1,
|
|
profiles: profiles
|
|
});
|
|
localStorage.setItem("profiles", data);
|
|
}
|
|
profiles_1.save = save;
|
|
function mark_need_save() {
|
|
_requires_save = true;
|
|
}
|
|
profiles_1.mark_need_save = mark_need_save;
|
|
function requires_save() {
|
|
return _requires_save;
|
|
}
|
|
profiles_1.requires_save = requires_save;
|
|
function profiles() {
|
|
return available_profiles;
|
|
}
|
|
profiles_1.profiles = profiles;
|
|
function find_profile(id) {
|
|
for (const profile of profiles())
|
|
if (profile.id == id)
|
|
return profile;
|
|
return undefined;
|
|
}
|
|
profiles_1.find_profile = find_profile;
|
|
function find_profile_by_name(name) {
|
|
name = name.toLowerCase();
|
|
for (const profile of profiles())
|
|
if ((profile.profile_name || "").toLowerCase() == name)
|
|
return profile;
|
|
return undefined;
|
|
}
|
|
profiles_1.find_profile_by_name = find_profile_by_name;
|
|
function default_profile() {
|
|
return find_profile("default");
|
|
}
|
|
profiles_1.default_profile = default_profile;
|
|
function set_default_profile(profile) {
|
|
const old_default = default_profile();
|
|
if (old_default && old_default != profile) {
|
|
old_default.id = guid();
|
|
}
|
|
profile.id = "default";
|
|
}
|
|
profiles_1.set_default_profile = set_default_profile;
|
|
function delete_profile(profile) {
|
|
available_profiles.remove(profile);
|
|
}
|
|
profiles_1.delete_profile = delete_profile;
|
|
})(profiles || (profiles = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["97f4f425246fb5a09df76962d3b4e6ded55a744c1a4572c69cacb84b09947703"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["97f4f425246fb5a09df76962d3b4e6ded55a744c1a4572c69cacb84b09947703"] = "97f4f425246fb5a09df76962d3b4e6ded55a744c1a4572c69cacb84b09947703";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "LU4TMdIh", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/profiles/identities/NameIdentity.ts (23,31)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../Identity.ts" />
|
|
var profiles;
|
|
(function (profiles) {
|
|
var identities;
|
|
(function (identities) {
|
|
class NameHandshakeHandler extends identities.AbstractHandshakeIdentityHandler {
|
|
constructor(connection, identity) {
|
|
super(connection);
|
|
this.identity = identity;
|
|
this.handler = new identities.HandshakeCommandHandler(connection, this);
|
|
this.handler["handshakeidentityproof"] = () => this.trigger_fail("server requested unexpected proof");
|
|
}
|
|
start_handshake() {
|
|
this.connection.command_handler_boss().register_handler(this.handler);
|
|
this.connection.send_command("handshakebegin", {
|
|
intention: 0,
|
|
authentication_method: this.identity.type(),
|
|
client_nickname: this.identity.name()
|
|
}).catch(error => {
|
|
console.error(_translations.LU4TMdIh || (_translations.LU4TMdIh = tr("Failed to initialize name based handshake. Error: %o")), error);
|
|
if (error instanceof CommandResult)
|
|
error = error.extra_message || error.message;
|
|
this.trigger_fail("failed to execute begin (" + error + ")");
|
|
}).then(() => this.trigger_success());
|
|
}
|
|
trigger_fail(message) {
|
|
this.connection.command_handler_boss().unregister_handler(this.handler);
|
|
super.trigger_fail(message);
|
|
}
|
|
trigger_success() {
|
|
this.connection.command_handler_boss().unregister_handler(this.handler);
|
|
super.trigger_success();
|
|
}
|
|
}
|
|
class NameIdentity {
|
|
constructor(name) {
|
|
this._name = name;
|
|
}
|
|
set_name(name) { this._name = name; }
|
|
name() {
|
|
return this._name;
|
|
}
|
|
uid() {
|
|
return btoa(this._name); //FIXME hash!
|
|
}
|
|
type() {
|
|
return identities.IdentitifyType.NICKNAME;
|
|
}
|
|
valid() {
|
|
return this._name != undefined && this._name.length >= 3;
|
|
}
|
|
decode(data) {
|
|
data = JSON.parse(data);
|
|
if (data.version !== 1)
|
|
throw "invalid version";
|
|
this._name = data["name"];
|
|
return;
|
|
}
|
|
encode() {
|
|
return JSON.stringify({
|
|
version: 1,
|
|
name: this._name
|
|
});
|
|
}
|
|
spawn_identity_handshake_handler(connection) {
|
|
return new NameHandshakeHandler(connection, this);
|
|
}
|
|
}
|
|
identities.NameIdentity = NameIdentity;
|
|
})(identities = profiles.identities || (profiles.identities = {}));
|
|
})(profiles || (profiles = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["b13c710ce5812e8eebe16c3f00ec0e6fc0c6afb86dde4b0672d57682d4d1615b"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["b13c710ce5812e8eebe16c3f00ec0e6fc0c6afb86dde4b0672d57682d4d1615b"] = "b13c710ce5812e8eebe16c3f00ec0e6fc0c6afb86dde4b0672d57682d4d1615b";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "gTP_s5rf", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/profiles/identities/TeaForumIdentity.ts (22,31)" }, { name: "rtlNOQM4", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/profiles/identities/TeaForumIdentity.ts (35,31)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../Identity.ts" />
|
|
var profiles;
|
|
(function (profiles) {
|
|
var identities;
|
|
(function (identities) {
|
|
class TeaForumHandshakeHandler extends identities.AbstractHandshakeIdentityHandler {
|
|
constructor(connection, identity) {
|
|
super(connection);
|
|
this.identity = identity;
|
|
this.handler = new identities.HandshakeCommandHandler(connection, this);
|
|
this.handler["handshakeidentityproof"] = this.handle_proof.bind(this);
|
|
}
|
|
start_handshake() {
|
|
this.connection.command_handler_boss().register_handler(this.handler);
|
|
this.connection.send_command("handshakebegin", {
|
|
intention: 0,
|
|
authentication_method: this.identity.type(),
|
|
data: this.identity.data_json()
|
|
}).catch(error => {
|
|
console.error(_translations.gTP_s5rf || (_translations.gTP_s5rf = tr("Failed to initialize TeaForum based handshake. Error: %o")), error);
|
|
if (error instanceof CommandResult)
|
|
error = error.extra_message || error.message;
|
|
this.trigger_fail("failed to execute begin (" + error + ")");
|
|
});
|
|
}
|
|
handle_proof(json) {
|
|
this.connection.send_command("handshakeindentityproof", {
|
|
proof: this.identity.data_sign()
|
|
}).catch(error => {
|
|
console.error(_translations.rtlNOQM4 || (_translations.rtlNOQM4 = tr("Failed to proof the identity. Error: %o")), error);
|
|
if (error instanceof CommandResult)
|
|
error = error.extra_message || error.message;
|
|
this.trigger_fail("failed to execute proof (" + error + ")");
|
|
}).then(() => this.trigger_success());
|
|
}
|
|
trigger_fail(message) {
|
|
this.connection.command_handler_boss().unregister_handler(this.handler);
|
|
super.trigger_fail(message);
|
|
}
|
|
trigger_success() {
|
|
this.connection.command_handler_boss().unregister_handler(this.handler);
|
|
super.trigger_success();
|
|
}
|
|
}
|
|
class TeaForumIdentity {
|
|
constructor(data, sign) {
|
|
this.identity_data_raw = data;
|
|
this.identity_data_sign = sign;
|
|
try {
|
|
this.identity_data = data ? JSON.parse(this.identity_data_raw) : undefined;
|
|
}
|
|
catch (error) { }
|
|
}
|
|
valid() {
|
|
return this.identity_data_raw.length > 0 && this.identity_data_raw.length > 0 && this.identity_data_sign.length > 0;
|
|
}
|
|
data_json() { return this.identity_data_raw; }
|
|
data_sign() { return this.identity_data_sign; }
|
|
name() { return this.identity_data["user_name"]; }
|
|
uid() { return "TeaForo#" + this.identity_data["user_id"]; }
|
|
type() { return identities.IdentitifyType.TEAFORO; }
|
|
forum_user_id() { return this.identity_data["user_id"]; }
|
|
forum_user_group() { return this.identity_data["user_group_id"]; }
|
|
is_stuff() { return this.identity_data["is_staff"]; }
|
|
is_premium() { return this.identity_data["user_groups"].indexOf(5) != -1; }
|
|
data_age() { return new Date(this.identity_data["data_age"]); }
|
|
/*
|
|
$user_data["user_id"] = $user->user_id;
|
|
$user_data["user_name"] = $user->username;
|
|
$user_data["user_group"] = $user->user_group_id;
|
|
$user_data["user_groups"] = $user->secondary_group_ids;
|
|
|
|
$user_data["trophy_points"] = $user->trophy_points;
|
|
$user_data["register_date"] = $user->register_date;
|
|
$user_data["is_staff"] = $user->is_staff;
|
|
$user_data["is_admin"] = $user->is_admin;
|
|
$user_data["is_super_admin"] = $user->is_super_admin;
|
|
$user_data["is_banned"] = $user->is_banned;
|
|
|
|
$user_data["data_age"] = milliseconds();
|
|
*/
|
|
decode(data) {
|
|
data = JSON.parse(data);
|
|
if (data.version !== 1)
|
|
throw "invalid version";
|
|
this.identity_data_raw = data["identity_data"];
|
|
this.identity_data_sign = data["identity_sign"];
|
|
this.identity_data = JSON.parse(this.identity_data);
|
|
return;
|
|
}
|
|
encode() {
|
|
return JSON.stringify({
|
|
version: 1,
|
|
identity_data: this.identity_data_raw,
|
|
identity_sign: this.identity_data_sign
|
|
});
|
|
}
|
|
spawn_identity_handshake_handler(connection) {
|
|
return new TeaForumHandshakeHandler(connection, this);
|
|
}
|
|
}
|
|
identities.TeaForumIdentity = TeaForumIdentity;
|
|
let static_identity;
|
|
function set_static_identity(identity) {
|
|
static_identity = identity;
|
|
}
|
|
identities.set_static_identity = set_static_identity;
|
|
function setup_forum() {
|
|
const user_data = settings.static("forum_user_data");
|
|
const user_sign = settings.static("forum_user_sign");
|
|
if (user_data && user_sign)
|
|
static_identity = new TeaForumIdentity(user_data, user_sign);
|
|
}
|
|
identities.setup_forum = setup_forum;
|
|
function valid_static_forum_identity() {
|
|
return static_identity && static_identity.valid();
|
|
}
|
|
identities.valid_static_forum_identity = valid_static_forum_identity;
|
|
function static_forum_identity() {
|
|
return static_identity;
|
|
}
|
|
identities.static_forum_identity = static_forum_identity;
|
|
})(identities = profiles.identities || (profiles.identities = {}));
|
|
})(profiles || (profiles = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["2ebc31136bb5cb9c9590586fa5a6c05556711699d9fb197a19f3a560ce22cbca"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["2ebc31136bb5cb9c9590586fa5a6c05556711699d9fb197a19f3a560ce22cbca"] = "2ebc31136bb5cb9c9590586fa5a6c05556711699d9fb197a19f3a560ce22cbca";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "UShtyyBP", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/profiles/identities/TeamSpeakIdentity.ts (217,31)" }, { name: "MexYNNj3", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/profiles/identities/TeamSpeakIdentity.ts (233,35)" }, { name: "dzrFDiun", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/profiles/identities/TeamSpeakIdentity.ts (415,31)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../Identity.ts" />
|
|
var profiles;
|
|
(function (profiles) {
|
|
var identities;
|
|
(function (identities) {
|
|
let CryptoHelper;
|
|
(function (CryptoHelper) {
|
|
function export_ecc_key(crypto_key, public_key) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
/*
|
|
Tomcrypt public key export:
|
|
if (type == PK_PRIVATE) {
|
|
flags[0] = 1;
|
|
err = der_encode_sequence_multi(out, outlen,
|
|
LTC_ASN1_BIT_STRING, 1UL, flags,
|
|
LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
|
|
LTC_ASN1_INTEGER, 1UL, key->pubkey.x,
|
|
LTC_ASN1_INTEGER, 1UL, key->pubkey.y,
|
|
LTC_ASN1_INTEGER, 1UL, key->k,
|
|
LTC_ASN1_EOL, 0UL, NULL);
|
|
} else {
|
|
flags[0] = 0;
|
|
err = der_encode_sequence_multi(out, outlen,
|
|
LTC_ASN1_BIT_STRING, 1UL, flags,
|
|
LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
|
|
LTC_ASN1_INTEGER, 1UL, key->pubkey.x,
|
|
LTC_ASN1_INTEGER, 1UL, key->pubkey.y,
|
|
LTC_ASN1_EOL, 0UL, NULL);
|
|
}
|
|
|
|
*/
|
|
const key_data = yield crypto.subtle.exportKey("jwk", crypto_key);
|
|
let index = 0;
|
|
const length = public_key ? 79 : 114; /* max lengths! Depends on the padding could be less */
|
|
const buffer = new Uint8Array(length); /* fixed ASN1 length */
|
|
{ /* the initial sequence */
|
|
buffer[index++] = 0x30; /* type */
|
|
buffer[index++] = 0x00; /* we will set the sequence length later */
|
|
}
|
|
{ /* the flags bit string */
|
|
buffer[index++] = 0x03; /* type */
|
|
buffer[index++] = 0x02; /* length */
|
|
buffer[index++] = 0x07; /* data */
|
|
buffer[index++] = public_key ? 0x00 : 0x80; /* flag 1 or 0 (1 = private key)*/
|
|
}
|
|
{ /* key size (const 32 for P-256) */
|
|
buffer[index++] = 0x02; /* type */
|
|
buffer[index++] = 0x01; /* length */
|
|
buffer[index++] = 0x20;
|
|
}
|
|
try { /* Public kex X */
|
|
buffer[index++] = 0x02; /* type */
|
|
buffer[index++] = 0x20; /* length */
|
|
const raw = atob(Base64DecodeUrl(key_data.x, false));
|
|
if (raw.charCodeAt(0) > 0x7F) {
|
|
buffer[index - 1] += 1;
|
|
buffer[index++] = 0;
|
|
}
|
|
for (let i = 0; i < 32; i++)
|
|
buffer[index++] = raw.charCodeAt(i);
|
|
}
|
|
catch (error) {
|
|
if (error instanceof DOMException)
|
|
throw "failed to parse x coordinate (invalid base64)";
|
|
throw error;
|
|
}
|
|
try { /* Public kex Y */
|
|
buffer[index++] = 0x02; /* type */
|
|
buffer[index++] = 0x20; /* length */
|
|
const raw = atob(Base64DecodeUrl(key_data.y, false));
|
|
if (raw.charCodeAt(0) > 0x7F) {
|
|
buffer[index - 1] += 1;
|
|
buffer[index++] = 0;
|
|
}
|
|
for (let i = 0; i < 32; i++)
|
|
buffer[index++] = raw.charCodeAt(i);
|
|
}
|
|
catch (error) {
|
|
if (error instanceof DOMException)
|
|
throw "failed to parse y coordinate (invalid base64)";
|
|
throw error;
|
|
}
|
|
if (!public_key) {
|
|
try { /* Public kex K */
|
|
buffer[index++] = 0x02; /* type */
|
|
buffer[index++] = 0x20; /* length */
|
|
const raw = atob(Base64DecodeUrl(key_data.d, false));
|
|
if (raw.charCodeAt(0) > 0x7F) {
|
|
buffer[index - 1] += 1;
|
|
buffer[index++] = 0;
|
|
}
|
|
for (let i = 0; i < 32; i++)
|
|
buffer[index++] = raw.charCodeAt(i);
|
|
}
|
|
catch (error) {
|
|
if (error instanceof DOMException)
|
|
throw "failed to parse y coordinate (invalid base64)";
|
|
throw error;
|
|
}
|
|
}
|
|
buffer[1] = index - 2; /* set the final sequence length */
|
|
return base64ArrayBuffer(buffer.buffer.slice(0, index));
|
|
});
|
|
}
|
|
CryptoHelper.export_ecc_key = export_ecc_key;
|
|
const crypt_key = "b9dfaa7bee6ac57ac7b65f1094a1c155e747327bc2fe5d51c512023fe54a280201004e90ad1daaae1075d53b7d571c30e063b5a62a4a017bb394833aa0983e6e";
|
|
function c_strlen(buffer, offset) {
|
|
let index = 0;
|
|
while (index + offset < buffer.length && buffer[index + offset] != 0)
|
|
index++;
|
|
return index;
|
|
}
|
|
function decrypt_ts_identity(buffer) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
/* buffer could contains a zero! */
|
|
const hash = new Uint8Array(yield sha.sha1(buffer.buffer.slice(20, 20 + c_strlen(buffer, 20))));
|
|
for (let i = 0; i < 20; i++)
|
|
buffer[i] ^= hash[i];
|
|
const length = Math.min(buffer.length, 100);
|
|
for (let i = 0; i < length; i++)
|
|
buffer[i] ^= crypt_key.charCodeAt(i);
|
|
return ab2str(buffer);
|
|
});
|
|
}
|
|
CryptoHelper.decrypt_ts_identity = decrypt_ts_identity;
|
|
function encrypt_ts_identity(buffer) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const length = Math.min(buffer.length, 100);
|
|
for (let i = 0; i < length; i++)
|
|
buffer[i] ^= crypt_key.charCodeAt(i);
|
|
const hash = new Uint8Array(yield sha.sha1(buffer.buffer.slice(20, 20 + c_strlen(buffer, 20))));
|
|
for (let i = 0; i < 20; i++)
|
|
buffer[i] ^= hash[i];
|
|
return base64ArrayBuffer(buffer);
|
|
});
|
|
}
|
|
CryptoHelper.encrypt_ts_identity = encrypt_ts_identity;
|
|
/**
|
|
* @param buffer base64 encoded ASN.1 string
|
|
*/
|
|
function decode_tomcrypt_key(buffer) {
|
|
let decoded;
|
|
try {
|
|
decoded = asn1.decode(atob(buffer));
|
|
}
|
|
catch (error) {
|
|
if (error instanceof DOMException)
|
|
throw "failed to parse key buffer (invalid base64)";
|
|
throw error;
|
|
}
|
|
let { x, y, k } = {
|
|
x: decoded.children[2].content(Infinity, asn1.TagType.VisibleString),
|
|
y: decoded.children[3].content(Infinity, asn1.TagType.VisibleString),
|
|
k: decoded.children[4].content(Infinity, asn1.TagType.VisibleString)
|
|
};
|
|
if (x.length > 32) {
|
|
if (x.charCodeAt(0) != 0)
|
|
throw "Invalid X coordinate! (Too long)";
|
|
x = x.substr(1);
|
|
}
|
|
if (y.length > 32) {
|
|
if (y.charCodeAt(0) != 0)
|
|
throw "Invalid Y coordinate! (Too long)";
|
|
y = y.substr(1);
|
|
}
|
|
if (k.length > 32) {
|
|
if (k.charCodeAt(0) != 0)
|
|
throw "Invalid private coordinate! (Too long)";
|
|
k = k.substr(1);
|
|
}
|
|
/*
|
|
console.log("Key x: %s (%d)", btoa(x), x.length);
|
|
console.log("Key y: %s (%d)", btoa(y), y.length);
|
|
console.log("Key k: %s (%d)", btoa(k), k.length);
|
|
*/
|
|
return {
|
|
crv: "P-256",
|
|
d: Base64EncodeUrl(btoa(k)),
|
|
x: Base64EncodeUrl(btoa(x)),
|
|
y: Base64EncodeUrl(btoa(y)),
|
|
ext: true,
|
|
key_ops: ["deriveKey", "sign"],
|
|
kty: "EC",
|
|
};
|
|
}
|
|
CryptoHelper.decode_tomcrypt_key = decode_tomcrypt_key;
|
|
})(CryptoHelper = identities.CryptoHelper || (identities.CryptoHelper = {}));
|
|
class TeaSpeakHandshakeHandler extends identities.AbstractHandshakeIdentityHandler {
|
|
constructor(connection, identity) {
|
|
super(connection);
|
|
this.identity = identity;
|
|
this.handler = new identities.HandshakeCommandHandler(connection, this);
|
|
this.handler["handshakeidentityproof"] = this.handle_proof.bind(this);
|
|
}
|
|
start_handshake() {
|
|
this.connection.command_handler_boss().register_handler(this.handler);
|
|
this.connection.send_command("handshakebegin", {
|
|
intention: 0,
|
|
authentication_method: this.identity.type(),
|
|
publicKey: this.identity.public_key
|
|
}).catch(error => {
|
|
console.error(_translations.UShtyyBP || (_translations.UShtyyBP = tr("Failed to initialize TeamSpeak based handshake. Error: %o")), error);
|
|
if (error instanceof CommandResult)
|
|
error = error.extra_message || error.message;
|
|
this.trigger_fail("failed to execute begin (" + error + ")");
|
|
});
|
|
}
|
|
handle_proof(json) {
|
|
if (!json[0]["digest"]) {
|
|
this.trigger_fail("server too old");
|
|
return;
|
|
}
|
|
this.identity.sign_message(json[0]["message"], json[0]["digest"]).then(proof => {
|
|
this.connection.send_command("handshakeindentityproof", { proof: proof }).catch(error => {
|
|
console.error(_translations.MexYNNj3 || (_translations.MexYNNj3 = tr("Failed to proof the identity. Error: %o")), error);
|
|
if (error instanceof CommandResult)
|
|
error = error.extra_message || error.message;
|
|
this.trigger_fail("failed to execute proof (" + error + ")");
|
|
}).then(() => this.trigger_success());
|
|
}).catch(error => {
|
|
this.trigger_fail("failed to sign message");
|
|
});
|
|
}
|
|
trigger_fail(message) {
|
|
this.connection.command_handler_boss().unregister_handler(this.handler);
|
|
super.trigger_fail(message);
|
|
}
|
|
trigger_success() {
|
|
this.connection.command_handler_boss().unregister_handler(this.handler);
|
|
super.trigger_success();
|
|
}
|
|
}
|
|
class IdentityPOWWorker {
|
|
initialize(key) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
this._worker = new Worker(settings.static("worker_directory", "js/workers/") + "WorkerPOW.js");
|
|
/* initialize */
|
|
yield new Promise((resolve, reject) => {
|
|
const timeout_id = setTimeout(() => reject("timeout"), 1000);
|
|
this._worker.onmessage = event => {
|
|
clearTimeout(timeout_id);
|
|
if (!event.data) {
|
|
reject("invalid data");
|
|
return;
|
|
}
|
|
if (!event.data.success) {
|
|
reject("initialize failed (" + event.data.success + " | " + (event.data.message || "unknown eroror") + ")");
|
|
return;
|
|
}
|
|
this._worker.onmessage = event => this.handle_message(event.data);
|
|
resolve();
|
|
};
|
|
this._worker.onerror = event => {
|
|
console.error("POW Worker error %o", event);
|
|
clearTimeout(timeout_id);
|
|
reject("Failed to load worker (" + event.message + ")");
|
|
};
|
|
});
|
|
/* set data */
|
|
yield new Promise((resolve, reject) => {
|
|
this._worker.postMessage({
|
|
type: "set_data",
|
|
private_key: key,
|
|
code: "set_data"
|
|
});
|
|
const timeout_id = setTimeout(() => reject("timeout (data)"), 1000);
|
|
this._worker.onmessage = event => {
|
|
clearTimeout(timeout_id);
|
|
if (!event.data) {
|
|
reject("invalid data");
|
|
return;
|
|
}
|
|
if (!event.data.success) {
|
|
reject("initialize of data failed (" + event.data.success + " | " + (event.data.message || "unknown eroror") + ")");
|
|
return;
|
|
}
|
|
this._worker.onmessage = event => this.handle_message(event.data);
|
|
resolve();
|
|
};
|
|
});
|
|
});
|
|
}
|
|
mine(hash, iterations, target, timeout) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
this._current_hash = hash;
|
|
if (target < this._best_level)
|
|
return true;
|
|
return yield new Promise((resolve, reject) => {
|
|
this._worker.postMessage({
|
|
type: "mine",
|
|
hash: this._current_hash,
|
|
iterations: iterations,
|
|
target: target,
|
|
code: "mine"
|
|
});
|
|
const timeout_id = setTimeout(() => reject("timeout (mine)"), timeout || 5000);
|
|
this._worker.onmessage = event => {
|
|
this._worker.onmessage = event => this.handle_message(event.data);
|
|
clearTimeout(timeout_id);
|
|
if (!event.data) {
|
|
reject("invalid data");
|
|
return;
|
|
}
|
|
if (!event.data.success) {
|
|
reject("mining failed (" + event.data.success + " | " + (event.data.message || "unknown eroror") + ")");
|
|
return;
|
|
}
|
|
if (event.data.result) {
|
|
this._best_level = event.data.level;
|
|
this._current_hash = event.data.hash;
|
|
resolve(true);
|
|
}
|
|
else {
|
|
resolve(false); /* no result */
|
|
}
|
|
};
|
|
});
|
|
});
|
|
}
|
|
current_hash() {
|
|
return this._current_hash;
|
|
}
|
|
current_level() {
|
|
return this._best_level;
|
|
}
|
|
finalize(timeout) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
try {
|
|
yield new Promise((resolve, reject) => {
|
|
this._worker.postMessage({
|
|
type: "finalize",
|
|
code: "finalize"
|
|
});
|
|
const timeout_id = setTimeout(() => reject("timeout"), timeout || 250);
|
|
this._worker.onmessage = event => {
|
|
this._worker.onmessage = event => this.handle_message(event.data);
|
|
clearTimeout(timeout_id);
|
|
if (!event.data) {
|
|
reject("invalid data");
|
|
return;
|
|
}
|
|
if (!event.data.success) {
|
|
reject("failed to finalize (" + event.data.success + " | " + (event.data.message || "unknown eroror") + ")");
|
|
return;
|
|
}
|
|
resolve();
|
|
};
|
|
});
|
|
}
|
|
catch (error) {
|
|
console.warn("Failed to finalize POW worker! (%o)", error);
|
|
}
|
|
this._worker.terminate();
|
|
this._worker = undefined;
|
|
});
|
|
}
|
|
handle_message(message) {
|
|
console.log("Received message: %o", message);
|
|
}
|
|
}
|
|
class TeaSpeakIdentity {
|
|
constructor(private_key, hash, name, initialize) {
|
|
this.private_key = private_key;
|
|
this.hash_number = hash || "0";
|
|
this._name = name;
|
|
if (this.private_key && (typeof (initialize) === "undefined" || initialize)) {
|
|
this.initialize().catch(error => {
|
|
console.error("Failed to initialize TeaSpeakIdentity (%s)", error);
|
|
this._initialized = false;
|
|
});
|
|
}
|
|
}
|
|
static generate_new() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
let key;
|
|
try {
|
|
key = yield crypto.subtle.generateKey({ name: 'ECDH', namedCurve: 'P-256' }, true, ["deriveKey"]);
|
|
}
|
|
catch (e) {
|
|
console.error(_translations.dzrFDiun || (_translations.dzrFDiun = tr("Could not generate a new key: %o")), e);
|
|
throw "Failed to generate keypair";
|
|
}
|
|
const private_key = yield CryptoHelper.export_ecc_key(key.privateKey, false);
|
|
const identity = new TeaSpeakIdentity(private_key, "0", undefined, false);
|
|
yield identity.initialize();
|
|
return identity;
|
|
});
|
|
}
|
|
static import_ts(ts_string, ini) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const parse_string = string => {
|
|
/* parsing without INI structure */
|
|
const V_index = string.indexOf('V');
|
|
if (V_index == -1)
|
|
throw "invalid input (missing V)";
|
|
return {
|
|
hash: string.substr(0, V_index),
|
|
data: string.substr(V_index + 1),
|
|
name: "TeaSpeak user"
|
|
};
|
|
};
|
|
const { hash, data, name } = (!ini ? () => parse_string(ts_string) : () => {
|
|
/* parsing with INI structure */
|
|
let identity, name;
|
|
for (const line of ts_string.split("\n")) {
|
|
if (line.startsWith("identity="))
|
|
identity = line.substr(9);
|
|
else if (line.startsWith("nickname="))
|
|
name = line.substr(9);
|
|
}
|
|
if (!identity)
|
|
throw "missing identity keyword";
|
|
if (identity[0] == "\"" && identity[identity.length - 1] == "\"")
|
|
identity = identity.substr(1, identity.length - 2);
|
|
const result = parse_string(identity);
|
|
result.name = name || result.name;
|
|
return result;
|
|
})();
|
|
if (!ts_string.match(/[0-9]+/g))
|
|
throw "invalid hash!";
|
|
const key64 = yield CryptoHelper.decrypt_ts_identity(new Uint8Array(arrayBufferBase64(data)));
|
|
const identity = new TeaSpeakIdentity(key64, hash, name, false);
|
|
yield identity.initialize();
|
|
return identity;
|
|
});
|
|
}
|
|
name() {
|
|
return this._name;
|
|
}
|
|
uid() {
|
|
return this._unique_id;
|
|
}
|
|
type() {
|
|
return identities.IdentitifyType.TEAMSPEAK;
|
|
}
|
|
valid() {
|
|
return this._initialized && !!this._crypto_key && !!this._crypto_key_sign;
|
|
}
|
|
decode(data) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
const json = JSON.parse(data);
|
|
if (!json)
|
|
throw "invalid json";
|
|
if (json.version == 2) {
|
|
this.private_key = json.key;
|
|
this.hash_number = json.hash;
|
|
this._name = json.name;
|
|
}
|
|
else if (json.version == 1) {
|
|
const key = json.key;
|
|
this._name = json.name;
|
|
const clone = yield TeaSpeakIdentity.import_ts(key, false);
|
|
this.private_key = clone.private_key;
|
|
this.hash_number = clone.hash_number;
|
|
}
|
|
else
|
|
throw "invalid version";
|
|
yield this.initialize();
|
|
});
|
|
}
|
|
encode() {
|
|
return JSON.stringify({
|
|
key: this.private_key,
|
|
hash: this.hash_number,
|
|
name: this._name,
|
|
version: 2
|
|
});
|
|
}
|
|
level() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
if (!this._initialized || !this.public_key)
|
|
throw "not initialized";
|
|
const hash = new Uint8Array(yield sha.sha1(this.public_key + this.hash_number));
|
|
let level = 0;
|
|
while (level < hash.byteLength && hash[level] == 0)
|
|
level++;
|
|
if (level >= hash.byteLength) {
|
|
level = 256;
|
|
}
|
|
else {
|
|
let byte = hash[level];
|
|
level <<= 3;
|
|
while ((byte & 0x1) == 0) {
|
|
level++;
|
|
byte >>= 1;
|
|
}
|
|
}
|
|
return level;
|
|
});
|
|
}
|
|
/**
|
|
* @param {string} a
|
|
* @param {string} b
|
|
* @description b must be smaller (in bytes) then a
|
|
*/
|
|
string_add(a, b) {
|
|
const char_result = [];
|
|
const char_a = [...a].reverse().map(e => e.charCodeAt(0));
|
|
const char_b = [...b].reverse().map(e => e.charCodeAt(0));
|
|
let carry = false;
|
|
while (char_b.length > 0) {
|
|
let result = char_b.pop_front() + char_a.pop_front() + (carry ? 1 : 0) - 48;
|
|
if ((carry = result > 57))
|
|
result -= 10;
|
|
char_result.push(result);
|
|
}
|
|
while (char_a.length > 0) {
|
|
let result = char_a.pop_front() + (carry ? 1 : 0);
|
|
if ((carry = result > 57))
|
|
result -= 10;
|
|
char_result.push(result);
|
|
}
|
|
if (carry)
|
|
char_result.push(49);
|
|
return String.fromCharCode.apply(null, char_result.reverse());
|
|
}
|
|
improve_level_for(time, threads) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
let active = true;
|
|
setTimeout(() => active = false, time);
|
|
return yield this.improve_level(-1, threads, () => active);
|
|
});
|
|
}
|
|
improve_level(target, threads, active_callback, callback_level, callback_status) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
if (!this._initialized || !this.public_key)
|
|
throw "not initialized";
|
|
if (target == -1) /* get the highest level possible */
|
|
target = 0;
|
|
else if (target <= (yield this.level()))
|
|
return true;
|
|
const workers = [];
|
|
const iterations = 100000;
|
|
let current_hash;
|
|
const next_hash = () => {
|
|
if (!current_hash)
|
|
return (current_hash = this.hash_number);
|
|
if (current_hash.length < iterations.toString().length) {
|
|
current_hash = this.string_add(iterations.toString(), current_hash);
|
|
}
|
|
else {
|
|
current_hash = this.string_add(current_hash, iterations.toString());
|
|
}
|
|
return current_hash;
|
|
};
|
|
{ /* init */
|
|
const initialize_promise = [];
|
|
for (let index = 0; index < threads; index++) {
|
|
const worker = new IdentityPOWWorker();
|
|
workers.push(worker);
|
|
initialize_promise.push(worker.initialize(this.public_key));
|
|
}
|
|
try {
|
|
yield Promise.all(initialize_promise);
|
|
}
|
|
catch (error) {
|
|
console.error(error);
|
|
throw "failed to initialize";
|
|
}
|
|
}
|
|
let result = false;
|
|
let best_level = 0;
|
|
let target_level = target > 0 ? target : (yield this.level()) + 1;
|
|
const worker_promise = [];
|
|
const hash_timestamps = [];
|
|
let last_hashrate_update = 0;
|
|
const update_hashrate = () => {
|
|
if (!callback_status)
|
|
return;
|
|
const now = Date.now();
|
|
hash_timestamps.push(now);
|
|
if (last_hashrate_update + 1000 < now) {
|
|
last_hashrate_update = now;
|
|
const timeout = now - 10 * 1000; /* 10s */
|
|
const rounds = hash_timestamps.filter(e => e > timeout);
|
|
callback_status(Math.ceil((rounds.length * iterations) / Math.ceil((now - rounds[0]) / 1000)));
|
|
}
|
|
};
|
|
try {
|
|
result = yield new Promise((resolve, reject) => {
|
|
let active = true;
|
|
const exit = () => {
|
|
const timeout = setTimeout(() => resolve(true), 1000);
|
|
Promise.all(worker_promise).then(result => {
|
|
clearTimeout(timeout);
|
|
resolve(true);
|
|
}).catch(error => resolve(true));
|
|
active = false;
|
|
};
|
|
for (const worker of workers) {
|
|
const worker_mine = () => {
|
|
if (!active)
|
|
return;
|
|
const promise = worker.mine(next_hash(), iterations, target_level);
|
|
const p = promise.then(result => {
|
|
update_hashrate();
|
|
worker_promise.remove(p);
|
|
if (result.valueOf()) {
|
|
if (worker.current_level() > best_level) {
|
|
this.hash_number = worker.current_hash();
|
|
console.log("Found new best at %s (%d). Old was %d", this.hash_number, worker.current_level(), best_level);
|
|
best_level = worker.current_level();
|
|
if (callback_level)
|
|
callback_level(best_level);
|
|
}
|
|
if (active) {
|
|
if (target > 0)
|
|
exit();
|
|
else
|
|
target_level = best_level + 1;
|
|
}
|
|
}
|
|
if (active && (active = active_callback()))
|
|
setTimeout(() => worker_mine(), 0);
|
|
else {
|
|
exit();
|
|
}
|
|
return Promise.resolve();
|
|
}).catch(error => {
|
|
worker_promise.remove(p);
|
|
console.warn("POW worker error %o", error);
|
|
reject(error);
|
|
return Promise.resolve();
|
|
});
|
|
worker_promise.push(p);
|
|
};
|
|
worker_mine();
|
|
}
|
|
});
|
|
}
|
|
catch (error) {
|
|
//error already printed before reject had been called
|
|
}
|
|
{ /* shutdown */
|
|
const finalize_promise = [];
|
|
for (const worker of workers)
|
|
finalize_promise.push(worker.finalize(250));
|
|
try {
|
|
yield Promise.all(finalize_promise);
|
|
}
|
|
catch (error) {
|
|
console.error(error);
|
|
throw "failed to finalize";
|
|
}
|
|
}
|
|
return result;
|
|
});
|
|
}
|
|
initialize() {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
if (!this.private_key)
|
|
throw "Invalid private key";
|
|
let jwk;
|
|
try {
|
|
jwk = yield CryptoHelper.decode_tomcrypt_key(this.private_key);
|
|
if (!jwk)
|
|
throw "result undefined";
|
|
}
|
|
catch (error) {
|
|
throw "failed to parse key (" + error + ")";
|
|
}
|
|
try {
|
|
this._crypto_key_sign = yield crypto.subtle.importKey("jwk", jwk, { name: 'ECDSA', namedCurve: 'P-256' }, false, ["sign"]);
|
|
}
|
|
catch (error) {
|
|
console.error(error);
|
|
throw "failed to create crypto sign key";
|
|
}
|
|
try {
|
|
this._crypto_key = yield crypto.subtle.importKey("jwk", jwk, { name: 'ECDH', namedCurve: 'P-256' }, true, ["deriveKey"]);
|
|
}
|
|
catch (error) {
|
|
console.error(error);
|
|
throw "failed to create crypto key";
|
|
}
|
|
try {
|
|
this.public_key = yield CryptoHelper.export_ecc_key(this._crypto_key, true);
|
|
this._unique_id = base64ArrayBuffer(yield sha.sha1(this.public_key));
|
|
}
|
|
catch (error) {
|
|
console.error(error);
|
|
throw "failed to calculate unique id";
|
|
}
|
|
this._initialized = true;
|
|
//const public_key = await profiles.identities.CryptoHelper.export_ecc_key(key, true);
|
|
});
|
|
}
|
|
export_ts(ini) {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
if (!this.private_key)
|
|
throw "Invalid private key";
|
|
const identity = this.hash_number + "V" + (yield CryptoHelper.encrypt_ts_identity(new Uint8Array(str2ab8(this.private_key))));
|
|
if (!ini)
|
|
return identity;
|
|
return "[Identity]\n" +
|
|
"id=TeaWeb-Exported\n" +
|
|
"identity=\"" + identity + "\"\n" +
|
|
"nickname=\"" + this.name() + "\"\n" +
|
|
"phonetic_nickname=";
|
|
});
|
|
}
|
|
sign_message(message, hash = "SHA-256") {
|
|
return __awaiter(this, void 0, void 0, function* () {
|
|
/* bring this to libtomcrypt format */
|
|
const sign_buffer = yield crypto.subtle.sign({
|
|
name: "ECDSA",
|
|
hash: hash
|
|
}, this._crypto_key_sign, str2ab8(message));
|
|
const sign = new Uint8Array(sign_buffer);
|
|
/* first 32 r bits | last 32 s bits */
|
|
const buffer = new Uint8Array(72);
|
|
let index = 0;
|
|
{ /* the initial sequence */
|
|
buffer[index++] = 0x30; /* type */
|
|
buffer[index++] = 0x00; /* we will set the sequence length later */
|
|
}
|
|
{ /* integer r */
|
|
buffer[index++] = 0x02; /* type */
|
|
buffer[index++] = 0x20; /* length */
|
|
if (sign[0] > 0x7F) {
|
|
buffer[index - 1] += 1;
|
|
buffer[index++] = 0;
|
|
}
|
|
for (let i = 0; i < 32; i++)
|
|
buffer[index++] = sign[i];
|
|
}
|
|
{ /* integer s */
|
|
buffer[index++] = 0x02; /* type */
|
|
buffer[index++] = 0x20; /* length */
|
|
if (sign[32] > 0x7F) {
|
|
buffer[index - 1] += 1;
|
|
buffer[index++] = 0;
|
|
}
|
|
for (let i = 0; i < 32; i++)
|
|
buffer[index++] = sign[32 + i];
|
|
}
|
|
buffer[1] = index - 2;
|
|
return base64ArrayBuffer(buffer.subarray(0, index));
|
|
});
|
|
}
|
|
spawn_identity_handshake_handler(connection) {
|
|
return new TeaSpeakHandshakeHandler(connection, this);
|
|
}
|
|
}
|
|
identities.TeaSpeakIdentity = TeaSpeakIdentity;
|
|
})(identities = profiles.identities || (profiles.identities = {}));
|
|
})(profiles || (profiles = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["446c209ef81f7b7224d75fc18d74014a5fa733e34fd263d33518be90ac3515b7"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["446c209ef81f7b7224d75fc18d74014a5fa733e34fd263d33518be90ac3515b7"] = "446c209ef81f7b7224d75fc18d74014a5fa733e34fd263d33518be90ac3515b7";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "SHOob1ET", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/sound/Sounds.ts (231,26)" }, { name: "qc1lS3zj", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/sound/Sounds.ts (244,26)" }, { name: "NYKnfWD9", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/sound/Sounds.ts (249,21)" }, { name: "TedPjWue", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/sound/Sounds.ts (257,33)" }, { name: "MLBuwnWd", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/sound/Sounds.ts (261,29)" }, { name: "nZCjUk0f", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/sound/Sounds.ts (287,37)" }, { name: "gELGE4Pb", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/sound/Sounds.ts (289,41)" }, { name: "PgjiBh_8", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/sound/Sounds.ts (293,43)" }, { name: "qC2EsMD0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/sound/Sounds.ts (313,39)" }, { name: "PejUdLLE", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/sound/Sounds.ts (320,35)" }, { name: "m7VfH0cA", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/sound/Sounds.ts (329,25)" }, { name: "_RK0Gxtx", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/sound/Sounds.ts (336,34)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var Sound;
|
|
(function (Sound) {
|
|
Sound["SOUND_TEST"] = "sound.test";
|
|
Sound["SOUND_EGG"] = "sound.egg";
|
|
Sound["AWAY_ACTIVATED"] = "away_activated";
|
|
Sound["AWAY_DEACTIVATED"] = "away_deactivated";
|
|
Sound["CONNECTION_CONNECTED"] = "connection.connected";
|
|
Sound["CONNECTION_DISCONNECTED"] = "connection.disconnected";
|
|
Sound["CONNECTION_BANNED"] = "connection.banned";
|
|
Sound["CONNECTION_DISCONNECTED_TIMEOUT"] = "connection.disconnected.timeout";
|
|
Sound["CONNECTION_REFUSED"] = "connection.refused";
|
|
Sound["SERVER_EDITED"] = "server.edited";
|
|
Sound["SERVER_EDITED_SELF"] = "server.edited.self";
|
|
Sound["SERVER_KICKED"] = "server.kicked";
|
|
Sound["CHANNEL_CREATED"] = "channel.created";
|
|
Sound["CHANNEL_MOVED"] = "channel.moved";
|
|
Sound["CHANNEL_EDITED"] = "channel.edited";
|
|
Sound["CHANNEL_EDITED_SELF"] = "channel.edited.self";
|
|
Sound["CHANNEL_DELETED"] = "channel.deleted";
|
|
Sound["CHANNEL_JOINED"] = "channel.joined";
|
|
Sound["CHANNEL_KICKED"] = "channel.kicked";
|
|
Sound["USER_MOVED"] = "user.moved";
|
|
Sound["USER_MOVED_SELF"] = "user.moved.self";
|
|
Sound["USER_POKED_SELF"] = "user.poked.self";
|
|
Sound["USER_BANNED"] = "user.banned";
|
|
Sound["USER_ENTERED"] = "user.joined";
|
|
Sound["USER_ENTERED_MOVED"] = "user.joined.moved";
|
|
Sound["USER_ENTERED_KICKED"] = "user.joined.kicked";
|
|
Sound["USER_ENTERED_CONNECT"] = "user.joined.connect";
|
|
Sound["USER_LEFT"] = "user.left";
|
|
Sound["USER_LEFT_MOVED"] = "user.left.moved";
|
|
Sound["USER_LEFT_KICKED_CHANNEL"] = "user.left.kicked.server";
|
|
Sound["USER_LEFT_KICKED_SERVER"] = "user.left.kicked.channel";
|
|
Sound["USER_LEFT_DISCONNECT"] = "user.left.disconnect";
|
|
Sound["USER_LEFT_BANNED"] = "user.left.banned";
|
|
Sound["ERROR_INSUFFICIENT_PERMISSIONS"] = "error.insufficient_permissions";
|
|
Sound["MESSAGE_SEND"] = "message.send";
|
|
Sound["MESSAGE_RECEIVED"] = "message.received";
|
|
Sound["GROUP_SERVER_ASSIGNED"] = "group.server.assigned";
|
|
Sound["GROUP_SERVER_REVOKED"] = "group.server.revoked";
|
|
Sound["GROUP_CHANNEL_CHANGED"] = "group.channel.changed";
|
|
Sound["GROUP_SERVER_ASSIGNED_SELF"] = "group.server.assigned.self";
|
|
Sound["GROUP_SERVER_REVOKED_SELF"] = "group.server.revoked.self";
|
|
Sound["GROUP_CHANNEL_CHANGED_SELF"] = "group.channel.changed.self";
|
|
})(Sound || (Sound = {}));
|
|
var sound;
|
|
(function (sound_1) {
|
|
let warned = false;
|
|
let speech_mapping = {};
|
|
let volume_require_save = false;
|
|
let speech_volume = {};
|
|
let master_volume;
|
|
let overlap_sounds;
|
|
let ignore_muted;
|
|
let master_mixed;
|
|
function register_sound(key, file) {
|
|
speech_mapping[key] = { key: key, filename: file };
|
|
}
|
|
function get_sound_volume(sound, default_volume) {
|
|
let result = speech_volume[sound];
|
|
if (typeof (result) === "undefined") {
|
|
if (typeof (default_volume) !== "undefined")
|
|
result = default_volume;
|
|
else
|
|
result = 1;
|
|
}
|
|
return result;
|
|
}
|
|
sound_1.get_sound_volume = get_sound_volume;
|
|
function set_sound_volume(sound, volume) {
|
|
volume_require_save = volume_require_save || speech_volume[sound] != volume;
|
|
speech_volume[sound] = volume == 1 ? undefined : volume;
|
|
}
|
|
sound_1.set_sound_volume = set_sound_volume;
|
|
function get_master_volume() {
|
|
return master_volume;
|
|
}
|
|
sound_1.get_master_volume = get_master_volume;
|
|
function set_master_volume(volume) {
|
|
volume_require_save = volume_require_save || master_volume != volume;
|
|
master_volume = volume;
|
|
if (master_mixed.gain.setValueAtTime)
|
|
master_mixed.gain.setValueAtTime(volume, 0);
|
|
else
|
|
master_mixed.gain.value = volume;
|
|
}
|
|
sound_1.set_master_volume = set_master_volume;
|
|
function overlap_activated() {
|
|
return overlap_sounds;
|
|
}
|
|
sound_1.overlap_activated = overlap_activated;
|
|
function set_overlap_activated(flag) {
|
|
volume_require_save = volume_require_save || overlap_sounds != flag;
|
|
overlap_sounds = flag;
|
|
}
|
|
sound_1.set_overlap_activated = set_overlap_activated;
|
|
function ignore_output_muted() {
|
|
return ignore_muted;
|
|
}
|
|
sound_1.ignore_output_muted = ignore_output_muted;
|
|
function set_ignore_output_muted(flag) {
|
|
volume_require_save = volume_require_save || ignore_muted != flag;
|
|
ignore_muted = flag;
|
|
}
|
|
sound_1.set_ignore_output_muted = set_ignore_output_muted;
|
|
function reinitialisize_audio() {
|
|
const context = audio.player.context();
|
|
const destination = audio.player.destination();
|
|
if (master_mixed)
|
|
master_mixed.disconnect();
|
|
master_mixed = context.createGain();
|
|
if (master_mixed.gain.setValueAtTime)
|
|
master_mixed.gain.setValueAtTime(master_volume, 0);
|
|
else
|
|
master_mixed.gain.value = master_volume;
|
|
master_mixed.connect(destination);
|
|
}
|
|
sound_1.reinitialisize_audio = reinitialisize_audio;
|
|
function save() {
|
|
if (volume_require_save) {
|
|
volume_require_save = false;
|
|
const data = {};
|
|
data.version = 1;
|
|
for (const sound in Sound) {
|
|
if (typeof (speech_volume[sound]) !== "undefined")
|
|
data[sound] = speech_volume[sound];
|
|
}
|
|
data.master = master_volume;
|
|
data.overlap = overlap_sounds;
|
|
data.ignore_muted = ignore_muted;
|
|
settings.changeGlobal("sound_volume", JSON.stringify(data));
|
|
console.error(data);
|
|
}
|
|
}
|
|
sound_1.save = save;
|
|
function initialize() {
|
|
$.ajaxSetup({
|
|
beforeSend: function (jqXHR, settings) {
|
|
if (settings.dataType === 'binary') {
|
|
settings.xhr().responseType = 'arraybuffer';
|
|
settings.processData = false;
|
|
}
|
|
}
|
|
});
|
|
/* volumes */
|
|
{
|
|
const data = JSON.parse(settings.static_global("sound_volume", "{}"));
|
|
for (const sound in Sound) {
|
|
if (typeof (data[sound]) !== "undefined")
|
|
speech_volume[sound] = data[sound];
|
|
}
|
|
console.error(data);
|
|
master_volume = data.master || 1;
|
|
overlap_sounds = data.overlap || true;
|
|
ignore_muted = data.ignore_muted || true;
|
|
}
|
|
register_sound("message.received", "effects/message_received.wav");
|
|
register_sound("message.send", "effects/message_send.wav");
|
|
audio.player.on_ready(reinitialisize_audio);
|
|
return new Promise(resolve => {
|
|
$.ajax({
|
|
url: "audio/speech/mapping.json",
|
|
success: response => {
|
|
if (typeof (response) === "string")
|
|
response = JSON.parse(response);
|
|
for (const entry of response)
|
|
register_sound(entry.key, "speech/" + entry.file);
|
|
resolve();
|
|
},
|
|
error: () => {
|
|
console.log("error!");
|
|
console.dir(...arguments);
|
|
},
|
|
timeout: 5000,
|
|
async: true,
|
|
type: 'GET'
|
|
});
|
|
});
|
|
}
|
|
sound_1.initialize = initialize;
|
|
function play(sound, options) {
|
|
if (!options) {
|
|
options = {};
|
|
}
|
|
const file = speech_mapping[sound];
|
|
if (!file) {
|
|
console.warn(_translations.SHOob1ET || (_translations.SHOob1ET = tr("Missing sound %o")), sound);
|
|
return;
|
|
}
|
|
if (file.not_supported) {
|
|
if (!file.not_supported_timeout || Date.now() < file.not_supported_timeout) //Test if the not supported isn't may timeouted
|
|
return;
|
|
file.not_supported = false;
|
|
file.not_supported_timeout = undefined;
|
|
}
|
|
const path = "audio/" + file.filename;
|
|
const context = audio.player.context();
|
|
if (!context) {
|
|
console.warn(_translations.qc1lS3zj || (_translations.qc1lS3zj = tr("Tried to replay a sound without an audio context (Sound: %o). Dropping playback")), sound);
|
|
return;
|
|
}
|
|
const volume = get_sound_volume(sound, options.default_volume);
|
|
console.log(_translations.NYKnfWD9 || (_translations.NYKnfWD9 = tr("Replaying sound %s (Sound volume: %o | Master volume %o)")), sound, volume, master_volume);
|
|
if (volume == 0)
|
|
return;
|
|
if (master_volume == 0)
|
|
return;
|
|
if (!options.ignore_muted && !ignore_muted && globalClient.controlBar.muteOutput)
|
|
return;
|
|
if (context.decodeAudioData) {
|
|
if (file.cached) {
|
|
if (!options.ignore_overlap && file.replaying && !overlap_sounds) {
|
|
console.log(_translations.TedPjWue || (_translations.TedPjWue = tr("Dropping requested playback for sound %s because it would overlap.")), sound);
|
|
return;
|
|
}
|
|
console.log(_translations.MLBuwnWd || (_translations.MLBuwnWd = tr("Using cached buffer: %o")), file.cached);
|
|
const player = context.createBufferSource();
|
|
player.buffer = file.cached;
|
|
player.start(0);
|
|
file.replaying = true;
|
|
player.onended = event => {
|
|
file.replaying = false;
|
|
};
|
|
if (volume != 1 && context.createGain) {
|
|
const gain = context.createGain();
|
|
if (gain.gain.setValueAtTime)
|
|
gain.gain.setValueAtTime(volume, 0);
|
|
else
|
|
gain.gain.value = volume;
|
|
player.connect(gain);
|
|
gain.connect(master_mixed);
|
|
}
|
|
else {
|
|
player.connect(master_mixed);
|
|
}
|
|
}
|
|
else {
|
|
const decode_data = buffer => {
|
|
console.log(buffer);
|
|
try {
|
|
console.log(_translations.nZCjUk0f || (_translations.nZCjUk0f = tr("Decoding data")));
|
|
context.decodeAudioData(buffer, result => {
|
|
console.log(_translations.gELGE4Pb || (_translations.gELGE4Pb = tr("Got decoded data")));
|
|
file.cached = result;
|
|
play(sound, options);
|
|
}, error => {
|
|
console.error(_translations.PgjiBh_8 || (_translations.PgjiBh_8 = tr("Failed to decode audio data for %o")), sound);
|
|
console.error(error);
|
|
file.not_supported = true;
|
|
file.not_supported_timeout = Date.now() + 1000 * 60 * 60; //Try in 2min again!
|
|
});
|
|
}
|
|
catch (error) {
|
|
console.error(error);
|
|
file.not_supported = true;
|
|
file.not_supported_timeout = Date.now() + 1000 * 60 * 60; //Try in 2min again!
|
|
}
|
|
};
|
|
const xhr = new XMLHttpRequest();
|
|
xhr.open('GET', path, true);
|
|
xhr.responseType = 'arraybuffer';
|
|
xhr.onload = function (e) {
|
|
if (this.status == 200) {
|
|
decode_data(this.response);
|
|
}
|
|
else {
|
|
console.error(_translations.qC2EsMD0 || (_translations.qC2EsMD0 = tr("Failed to load audio file. (Response code %o)")), this.status);
|
|
file.not_supported = true;
|
|
file.not_supported_timeout = Date.now() + 1000 * 60 * 60; //Try in 2min again!
|
|
}
|
|
};
|
|
xhr.onerror = error => {
|
|
console.error(_translations.PejUdLLE || (_translations.PejUdLLE = tr("Failed to load audio file ")), sound);
|
|
console.error(error);
|
|
file.not_supported = true;
|
|
file.not_supported_timeout = Date.now() + 1000 * 60 * 60; //Try in 2min again!
|
|
};
|
|
xhr.send();
|
|
}
|
|
}
|
|
else {
|
|
console.log(_translations.m7VfH0cA || (_translations.m7VfH0cA = tr("Replaying %s")), path);
|
|
if (file.node) {
|
|
file.node.currentTime = 0;
|
|
file.node.play();
|
|
}
|
|
else {
|
|
if (!warned) {
|
|
warned = true;
|
|
console.warn(_translations._RK0Gxtx || (_translations._RK0Gxtx = tr("Your browser does not support decodeAudioData! Using a node to playback! This bypasses the audio output and volume regulation!")));
|
|
}
|
|
const container = $("#sounds");
|
|
const node = $.spawn("audio").attr("src", path);
|
|
node.appendTo(container);
|
|
file.node = node[0];
|
|
file.node.play();
|
|
}
|
|
}
|
|
}
|
|
sound_1.play = play;
|
|
})(sound || (sound = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["3faa3b45f66fbf63bdd5516c889adf8619e6831641d9f1f7994437998b6910d7"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["3faa3b45f66fbf63bdd5516c889adf8619e6831641d9f1f7994437998b6910d7"] = "3faa3b45f66fbf63bdd5516c889adf8619e6831641d9f1f7994437998b6910d7";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
if (!$.fn.dividerfy) {
|
|
$.fn.dividerfy = function () {
|
|
this.find(".container-seperator").each(function () {
|
|
if (!this.previousElementSibling)
|
|
return;
|
|
if (!this.nextElementSibling)
|
|
return;
|
|
const element = $(this);
|
|
const parent_element = $(this.parentElement);
|
|
const previous_element = $(this.previousElementSibling);
|
|
const next_element = $(this.nextElementSibling);
|
|
const seperator_id = element.attr("seperator-id");
|
|
const vertical = element.hasClass("vertical");
|
|
const apply_view = (property, previous, next) => {
|
|
previous_element.css(property, "calc(" + previous + "% - " + (vertical ? element.width() : element.height()) + "px)");
|
|
next_element.css(property, "calc(" + next + "% - " + (vertical ? element.width() : element.height()) + "px)");
|
|
};
|
|
const listener_move = (event) => {
|
|
const parent_offset = parent_element.offset();
|
|
const min = vertical ? parent_offset.left : parent_offset.top;
|
|
const max = vertical ? parent_offset.left + parent_element.width() : parent_offset.top + parent_element.height();
|
|
const current = event instanceof MouseEvent ?
|
|
(vertical ? event.pageX : event.pageY) :
|
|
(vertical ? event.touches[event.touches.length - 1].clientX : event.touches[event.touches.length - 1].clientY);
|
|
/*
|
|
const previous_offset = previous_element.offset();
|
|
const next_offset = next_element.offset();
|
|
|
|
const min = vertical ? Math.min(previous_offset.left, next_offset.left) : Math.min(previous_offset.top, next_offset.top);
|
|
const max = vertical ?
|
|
Math.max(previous_offset.left + previous_element.width(), next_offset.left + next_element.width()) :
|
|
Math.max(previous_offset.top + previous_element.height(), next_offset.top + next_element.height());
|
|
*/
|
|
let previous = 0;
|
|
let next = 0;
|
|
if (current < min) {
|
|
previous = 0;
|
|
next = 1;
|
|
}
|
|
else if (current < max) {
|
|
const x_offset = current - min;
|
|
const x_offset_max = max - min;
|
|
previous = x_offset / x_offset_max;
|
|
next = 1 - previous;
|
|
}
|
|
else {
|
|
previous = 1;
|
|
next = 0;
|
|
}
|
|
const property = vertical ? "width" : "height";
|
|
const previous_p = Math.ceil(previous * 100);
|
|
const next_p = Math.ceil(next * 100);
|
|
apply_view(property, previous_p, next_p);
|
|
if (seperator_id)
|
|
settings.changeGlobal("seperator-settings-" + seperator_id, JSON.stringify({
|
|
previous: previous_p,
|
|
next: next_p,
|
|
property: property
|
|
}));
|
|
};
|
|
const listener_up = (event) => {
|
|
document.removeEventListener('mousemove', listener_move);
|
|
document.removeEventListener('touchmove', listener_move);
|
|
document.removeEventListener('mouseup', listener_up);
|
|
document.removeEventListener('touchend', listener_up);
|
|
document.removeEventListener('touchcancel', listener_up);
|
|
$(document.documentElement).css("user-select", "");
|
|
element.removeClass("seperator-selected");
|
|
};
|
|
element.on('mousedown', () => {
|
|
document.addEventListener('mousemove', listener_move);
|
|
document.addEventListener('touchmove', listener_move);
|
|
document.addEventListener('mouseup', listener_up);
|
|
document.addEventListener('touchend', listener_up);
|
|
document.addEventListener('touchcancel', listener_up);
|
|
$(document.documentElement).css("user-select", "none");
|
|
element.addClass("seperator-selected");
|
|
});
|
|
element.on('touchstart', () => {
|
|
element.trigger('mousedown');
|
|
});
|
|
if (seperator_id) {
|
|
try {
|
|
const config = JSON.parse(settings.global("seperator-settings-" + seperator_id));
|
|
if (config) {
|
|
console.log("Apply previous changed: %o", config);
|
|
apply_view(config.property, config.previous, config.next);
|
|
}
|
|
}
|
|
catch (e) {
|
|
if (!(e instanceof SyntaxError))
|
|
console.error(e);
|
|
}
|
|
}
|
|
});
|
|
return this;
|
|
};
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["975d14defd03581dc3938c23723a34d79728dafafa0e7060c8e6a3266031b34c"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["975d14defd03581dc3938c23723a34d79728dafafa0e7060c8e6a3266031b34c"] = "975d14defd03581dc3938c23723a34d79728dafafa0e7060c8e6a3266031b34c";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
var htmltags;
|
|
(function (htmltags) {
|
|
let mouse_coordinates = { x: 0, y: 0 };
|
|
function initialize() {
|
|
document.addEventListener('mousemove', event => {
|
|
mouse_coordinates.x = event.pageX;
|
|
mouse_coordinates.y = event.pageY;
|
|
});
|
|
}
|
|
initialize();
|
|
/* required for the bbcodes */
|
|
function generate_client_open(properties) {
|
|
let result = "";
|
|
/* build the opening tag: <div ...> */
|
|
result = result + "<div class='htmltag-client' ";
|
|
if (properties.client_avatar_id)
|
|
result = result + "client-id='" + properties.client_avatar_id + "' ";
|
|
if (properties.client_unique_id && properties.client_unique_id != "unknown")
|
|
result = result + "client-unique-id='" + encodeURIComponent(properties.client_unique_id) + "' ";
|
|
if (properties.client_name)
|
|
result = result + "client-name='" + encodeURIComponent(properties.client_name) + "' ";
|
|
/* add the click handler */
|
|
result += "oncontextmenu='return htmltags.callbacks.callback_context_client($(this));'";
|
|
result = result + ">";
|
|
return result;
|
|
}
|
|
function generate_client(properties) {
|
|
let result = generate_client_open(properties);
|
|
/* content */
|
|
{
|
|
if (properties.add_braces)
|
|
result = result + "\"";
|
|
result = result + MessageHelper.htmlEscape(properties.client_name || "undefined").join(" ");
|
|
if (properties.add_braces)
|
|
result = result + "\"";
|
|
}
|
|
/* close tag */
|
|
{
|
|
result += "</div>";
|
|
}
|
|
return result;
|
|
}
|
|
htmltags.generate_client = generate_client;
|
|
/* required for the bbcodes */
|
|
function generate_channel_open(properties) {
|
|
let result = "";
|
|
/* build the opening tag: <div ...> */
|
|
result = result + "<div class='htmltag-channel' ";
|
|
if (properties.channel_id)
|
|
result = result + "channel-id='" + properties.channel_id + "' ";
|
|
if (properties.channel_name)
|
|
result = result + "channel-name='" + encodeURIComponent(properties.channel_name) + "' ";
|
|
/* add the click handler */
|
|
result += "oncontextmenu='return htmltags.callbacks.callback_context_channel($(this));'";
|
|
result = result + ">";
|
|
return result;
|
|
}
|
|
function generate_channel(properties) {
|
|
let result = generate_channel_open(properties);
|
|
/* content */
|
|
{
|
|
if (properties.add_braces)
|
|
result = result + "\"";
|
|
result = result + MessageHelper.htmlEscape(properties.channel_display_name || properties.channel_name || "undefined").join(" ");
|
|
if (properties.add_braces)
|
|
result = result + "\"";
|
|
}
|
|
/* close tag */
|
|
{
|
|
result += "</div>";
|
|
}
|
|
return result;
|
|
}
|
|
htmltags.generate_channel = generate_channel;
|
|
let callbacks;
|
|
(function (callbacks) {
|
|
function callback_context_client(element) {
|
|
const client_id = parseInt(element.attr("client-id") || "0");
|
|
const client_unique_id = decodeURIComponent(element.attr("client-unique-id") || "");
|
|
/* we ignore the name, we cant find clients by name because the name is too volatile*/
|
|
let client;
|
|
if (globalClient && globalClient.channelTree) {
|
|
if (!client && client_id) {
|
|
client = globalClient.channelTree.findClient(client_id);
|
|
if (client && (client_unique_id && client.properties.client_unique_identifier != client_unique_id)) {
|
|
client = undefined; /* client id dosn't match anymore, lets search for the unique id */
|
|
}
|
|
}
|
|
if (!client && client_unique_id)
|
|
client = globalClient.channelTree.find_client_by_unique_id(client_unique_id);
|
|
}
|
|
if (!client) {
|
|
/* we may should open a "offline" menu? */
|
|
log.debug(LogCategory.GENERAL, "Failed to resolve client from html tag. Client id: %o, Client unique id: %o, Client name: %o", client_id, client_unique_id, decodeURIComponent(element.attr("client-name")));
|
|
return false;
|
|
}
|
|
client.showContextMenu(mouse_coordinates.x, mouse_coordinates.y);
|
|
return false;
|
|
}
|
|
callbacks.callback_context_client = callback_context_client;
|
|
function callback_context_channel(element) {
|
|
const channel_id = parseInt(element.attr("channel-id") || "0");
|
|
let channel;
|
|
if (globalClient && globalClient.channelTree) {
|
|
channel = globalClient.channelTree.findChannel(channel_id);
|
|
}
|
|
if (!channel)
|
|
return false;
|
|
channel.showContextMenu(mouse_coordinates.x, mouse_coordinates.y);
|
|
return false;
|
|
}
|
|
callbacks.callback_context_channel = callback_context_channel;
|
|
})(callbacks = htmltags.callbacks || (htmltags.callbacks = {}));
|
|
let bbcodes;
|
|
(function (bbcodes) {
|
|
/* the = because we sometimes get that */
|
|
//const url_client_regex = /(?:=)?client:\/\/(?<client_id>[0-9]+)\/(?<client_unique_id>[a-zA-Z0-9+=#]+)~(?<client_name>(?:[^%]|%[0-9A-Fa-f]{2})+)$/g;
|
|
const url_client_regex = /(?:=)?client:\/\/([0-9]+)\/([a-zA-Z0-9+=/#]+)~((?:[^%]|%[0-9A-Fa-f]{2})+)$/g; /* IDK which browsers already support group naming */
|
|
const url_channel_regex = /(?:=)?channel:\/\/([0-9]+)~((?:[^%]|%[0-9A-Fa-f]{2})+)$/g;
|
|
function initialize() {
|
|
const origin_url = XBBCODE.tags()["url"];
|
|
XBBCODE.addTags({
|
|
function: {
|
|
openTag: (params, content) => {
|
|
if (params) {
|
|
if (params.match(url_channel_regex)) {
|
|
const groups = url_channel_regex.exec(params);
|
|
return generate_channel_open({
|
|
add_braces: false,
|
|
channel_id: parseInt(groups[1]),
|
|
channel_name: decodeURIComponent(groups[2])
|
|
});
|
|
}
|
|
else if (params.match(url_client_regex)) {
|
|
const groups = url_client_regex.exec(params);
|
|
return generate_client_open({
|
|
add_braces: false,
|
|
client_avatar_id: parseInt(groups[1]),
|
|
client_unique_id: groups[2],
|
|
client_name: decodeURIComponent(groups[3])
|
|
});
|
|
}
|
|
}
|
|
return origin_url.openTag(params, content);
|
|
},
|
|
closeTag: (params, content) => {
|
|
if (params) {
|
|
if (params.match(url_client_regex))
|
|
return "</div>";
|
|
if (params.match(url_channel_regex))
|
|
return "</div>";
|
|
}
|
|
return origin_url.closeTag(params, content);
|
|
}
|
|
},
|
|
tag: "url"
|
|
});
|
|
/*
|
|
"img": {
|
|
openTag: function(params,content) {
|
|
let myUrl;
|
|
|
|
if (!params) {
|
|
myUrl = content.replace(/<.*?>/g,"");
|
|
} else {
|
|
myUrl = params.substr(1);
|
|
}
|
|
|
|
urlPattern.lastIndex = 0;
|
|
if ( !urlPattern.test( myUrl ) ) {
|
|
myUrl = "#";
|
|
}
|
|
|
|
return '<a href="' + myUrl + '" target="_blank">';
|
|
},
|
|
closeTag: function(params,content) {
|
|
return '</a>';
|
|
}
|
|
},
|
|
*/
|
|
}
|
|
initialize();
|
|
})(bbcodes || (bbcodes = {}));
|
|
})(htmltags || (htmltags = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["181f59474ad585434f2f8cd33a37ee29d4292be2ee59cc5b1bde6d8417448949"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["181f59474ad585434f2f8cd33a37ee29d4292be2ee59cc5b1bde6d8417448949"] = "181f59474ad585434f2f8cd33a37ee29d4292be2ee59cc5b1bde6d8417448949";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../utils/modal.ts" />
|
|
var Modals;
|
|
(function (Modals) {
|
|
function createServerModal(server, callback) {
|
|
let properties = {}; //The changes properties
|
|
const modal_template = $("#tmpl_server_edit").renderTag(server.properties);
|
|
const modal = modal_template.modalize((header, body, footer) => {
|
|
return {
|
|
body: body.tabify()
|
|
};
|
|
});
|
|
server_applyGeneralListener(properties, modal.htmlTag.find(".properties_general"), modal.htmlTag.find(".button_ok"));
|
|
server_applyTransferListener(properties, server, modal.htmlTag.find('.properties_transfer'));
|
|
server_applyHostListener(server, properties, server.properties, modal.htmlTag.find(".properties_host"), modal.htmlTag.find(".button_ok"));
|
|
server_applyMessages(properties, server, modal.htmlTag.find(".properties_messages"));
|
|
server_applyFlood(properties, server, modal.htmlTag.find(".properties_flood"));
|
|
server_applySecurity(properties, server, modal.htmlTag.find(".properties_security"));
|
|
server_applyMisc(properties, server, modal.htmlTag.find(".properties_misc"));
|
|
modal.htmlTag.find(".button_ok").click(() => {
|
|
modal.close();
|
|
callback(properties); //First may create the channel
|
|
});
|
|
modal.htmlTag.find(".button_cancel").click(() => {
|
|
modal.close();
|
|
callback();
|
|
});
|
|
modal.open();
|
|
}
|
|
Modals.createServerModal = createServerModal;
|
|
function server_applyGeneralListener(properties, tag, button) {
|
|
let updateButton = () => {
|
|
if (tag.find(".input_error").length == 0)
|
|
button.removeAttr("disabled");
|
|
else
|
|
button.attr("disabled", "true");
|
|
};
|
|
tag.find(".virtualserver_name").change(function () {
|
|
properties.virtualserver_name = this.value;
|
|
$(this).removeClass("input_error");
|
|
if (this.value.length < 1 || this.value.length > 70)
|
|
$(this).addClass("input_error");
|
|
updateButton();
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_NAME).granted(1));
|
|
tag.find(".virtualserver_name_phonetic").change(function () {
|
|
properties.virtualserver_name_phonetic = this.value;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_NAME).granted(1));
|
|
tag.find(".virtualserver_password").change(function () {
|
|
properties.virtualserver_flag_password = this.value.length != 0;
|
|
if (properties.virtualserver_flag_password)
|
|
helpers.hashPassword(this.value).then(pass => properties.virtualserver_password = pass);
|
|
$(this).removeClass("input_error");
|
|
if (!properties.virtualserver_flag_password)
|
|
if (globalClient.permissions.neededPermission(PermissionType.B_CHANNEL_CREATE_MODIFY_WITH_FORCE_PASSWORD).granted(1))
|
|
$(this).addClass("input_error");
|
|
updateButton();
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_PASSWORD).granted(1));
|
|
tag.find(".virtualserver_maxclients").change(function () {
|
|
properties.virtualserver_maxclients = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_MAXCLIENTS).granted(1));
|
|
tag.find(".virtualserver_reserved_slots").change(function () {
|
|
properties.virtualserver_reserved_slots = this.valueAsNumber;
|
|
$(this).removeClass("input_error");
|
|
if (this.valueAsNumber > properties.virtualserver_maxclients)
|
|
$(this).addClass("input_error");
|
|
updateButton();
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_RESERVED_SLOTS).granted(1));
|
|
tag.find(".virtualserver_welcomemessage").change(function () {
|
|
properties.virtualserver_welcomemessage = this.value;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_WELCOMEMESSAGE).granted(1));
|
|
}
|
|
function server_applyHostListener(server, properties, original_properties, tag, button) {
|
|
tag.find(".virtualserver_host").change(function () {
|
|
properties.virtualserver_host = this.value;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_HOST).granted(1));
|
|
tag.find(".virtualserver_port").change(function () {
|
|
properties.virtualserver_port = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_PORT).granted(1));
|
|
tag.find(".virtualserver_hostmessage").change(function () {
|
|
properties.virtualserver_hostmessage = this.value;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_HOSTMESSAGE).granted(1));
|
|
tag.find(".virtualserver_hostmessage_mode").change(function () {
|
|
properties.virtualserver_hostmessage_mode = this.selectedIndex;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_HOSTMESSAGE).granted(1))
|
|
.find("option").eq(original_properties.virtualserver_hostmessage_mode).prop('selected', true);
|
|
tag.find(".virtualserver_hostbanner_url").change(function () {
|
|
properties.virtualserver_hostbanner_url = this.value;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_HOSTBANNER).granted(1));
|
|
tag.find(".virtualserver_hostbanner_gfx_url").change(function () {
|
|
properties.virtualserver_hostbanner_gfx_url = this.value;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_HOSTBANNER).granted(1));
|
|
tag.find(".virtualserver_hostbanner_gfx_interval").change(function () {
|
|
properties.virtualserver_hostbanner_gfx_interval = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_HOSTBANNER).granted(1));
|
|
tag.find(".virtualserver_hostbanner_mode").change(function () {
|
|
properties.virtualserver_hostbanner_mode = this.selectedIndex;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_HOSTMESSAGE).granted(1))
|
|
.find("option").eq(original_properties.virtualserver_hostbanner_mode).prop('selected', true);
|
|
tag.find(".virtualserver_hostbutton_tooltip").change(function () {
|
|
properties.virtualserver_hostbutton_tooltip = this.value;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_HOSTBUTTON).granted(1));
|
|
tag.find(".virtualserver_hostbutton_url").change(function () {
|
|
properties.virtualserver_hostbutton_url = this.value;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_HOSTBUTTON).granted(1));
|
|
tag.find(".virtualserver_hostbutton_gfx_url").change(function () {
|
|
properties.virtualserver_hostbutton_gfx_url = this.value;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_HOSTBUTTON).granted(1));
|
|
server.updateProperties().then(() => {
|
|
tag.find(".virtualserver_host").val(server.properties.virtualserver_host);
|
|
tag.find(".virtualserver_port").val(server.properties.virtualserver_port);
|
|
});
|
|
}
|
|
function server_applyMessages(properties, server, tag) {
|
|
server.updateProperties().then(() => {
|
|
tag.find(".virtualserver_default_client_description").val(server.properties.virtualserver_default_client_description);
|
|
tag.find(".virtualserver_default_channel_description").val(server.properties.virtualserver_default_channel_description);
|
|
tag.find(".virtualserver_default_channel_topic").val(server.properties.virtualserver_default_channel_topic);
|
|
});
|
|
tag.find(".virtualserver_default_client_description").change(function () {
|
|
properties.virtualserver_default_client_description = this.value;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_DEFAULT_MESSAGES).granted(1));
|
|
tag.find(".virtualserver_default_channel_description").change(function () {
|
|
properties.virtualserver_default_channel_description = this.value;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_DEFAULT_MESSAGES).granted(1));
|
|
tag.find(".virtualserver_default_channel_topic").change(function () {
|
|
properties.virtualserver_default_channel_topic = this.value;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_DEFAULT_MESSAGES).granted(1));
|
|
}
|
|
function server_applyFlood(properties, server, tag) {
|
|
server.updateProperties().then(() => {
|
|
tag.find(".virtualserver_antiflood_points_tick_reduce").val(server.properties.virtualserver_antiflood_points_tick_reduce);
|
|
tag.find(".virtualserver_antiflood_points_needed_command_block").val(server.properties.virtualserver_antiflood_points_needed_command_block);
|
|
tag.find(".virtualserver_antiflood_points_needed_ip_block").val(server.properties.virtualserver_antiflood_points_needed_ip_block);
|
|
});
|
|
tag.find(".virtualserver_antiflood_points_tick_reduce").change(function () {
|
|
properties.virtualserver_antiflood_points_tick_reduce = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_ANTIFLOOD).granted(1));
|
|
tag.find(".virtualserver_antiflood_points_needed_command_block").change(function () {
|
|
properties.virtualserver_antiflood_points_needed_command_block = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_ANTIFLOOD).granted(1));
|
|
tag.find(".virtualserver_antiflood_points_needed_ip_block").change(function () {
|
|
properties.virtualserver_antiflood_points_needed_ip_block = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_ANTIFLOOD).granted(1));
|
|
}
|
|
function server_applySecurity(properties, server, tag) {
|
|
server.updateProperties().then(() => {
|
|
tag.find(".virtualserver_needed_identity_security_level").val(server.properties.virtualserver_needed_identity_security_level);
|
|
});
|
|
tag.find(".virtualserver_needed_identity_security_level").change(function () {
|
|
properties.virtualserver_needed_identity_security_level = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_NEEDED_IDENTITY_SECURITY_LEVEL).granted(1));
|
|
tag.find(".virtualserver_codec_encryption_mode").change(function () {
|
|
properties.virtualserver_codec_encryption_mode = this.selectedIndex;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_ANTIFLOOD).granted(1))
|
|
.find("option").eq(server.properties.virtualserver_codec_encryption_mode).prop('selected', true);
|
|
}
|
|
function server_applyMisc(properties, server, tag) {
|
|
{ //TODO notify on tmp channeladmin group and vice versa
|
|
{
|
|
let groups_tag = tag.find(".default_server_group");
|
|
groups_tag.change(function () {
|
|
properties.virtualserver_default_server_group = parseInt($(this.item(this.selectedIndex)).attr("group-id"));
|
|
});
|
|
for (let group of server.channelTree.client.groups.serverGroups.sort(GroupManager.sorter())) {
|
|
if (group.type != 2)
|
|
continue;
|
|
let group_tag = $.spawn("option").text(group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]").attr("group-id", group.id);
|
|
if (group.id == server.properties.virtualserver_default_server_group)
|
|
group_tag.prop("selected", true);
|
|
group_tag.appendTo(groups_tag);
|
|
}
|
|
}
|
|
{
|
|
let groups_tag = tag.find(".default_music_group");
|
|
groups_tag.change(function () {
|
|
properties.virtualserver_default_music_group = parseInt($(this.item(this.selectedIndex)).attr("group-id"));
|
|
});
|
|
for (let group of server.channelTree.client.groups.serverGroups.sort(GroupManager.sorter())) {
|
|
if (group.type != 2)
|
|
continue;
|
|
let group_tag = $.spawn("option").text(group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]").attr("group-id", group.id);
|
|
if (group.id == server.properties.virtualserver_default_music_group)
|
|
group_tag.prop("selected", true);
|
|
group_tag.appendTo(groups_tag);
|
|
}
|
|
}
|
|
{
|
|
let groups_tag = tag.find(".default_channel_group");
|
|
groups_tag.change(function () {
|
|
properties.virtualserver_default_channel_group = parseInt($(this.item(this.selectedIndex)).attr("group-id"));
|
|
});
|
|
for (let group of server.channelTree.client.groups.channelGroups.sort(GroupManager.sorter())) {
|
|
if (group.type != 2)
|
|
continue;
|
|
let group_tag = $.spawn("option").text(group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]").attr("group-id", group.id);
|
|
if (group.id == server.properties.virtualserver_default_channel_group)
|
|
group_tag.prop("selected", true);
|
|
group_tag.appendTo(groups_tag);
|
|
}
|
|
}
|
|
{
|
|
let groups_tag = tag.find(".default_channel_admin_group");
|
|
groups_tag.change(function () {
|
|
properties.virtualserver_default_channel_admin_group = parseInt($(this.item(this.selectedIndex)).attr("group-id"));
|
|
});
|
|
for (let group of server.channelTree.client.groups.channelGroups.sort(GroupManager.sorter())) {
|
|
if (group.type != 2)
|
|
continue;
|
|
let group_tag = $.spawn("option").text(group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]").attr("group-id", group.id);
|
|
if (group.id == server.properties.virtualserver_default_channel_admin_group)
|
|
group_tag.prop("selected", true);
|
|
group_tag.appendTo(groups_tag);
|
|
}
|
|
}
|
|
}
|
|
server.updateProperties().then(() => {
|
|
//virtualserver_antiflood_points_needed_ip_block
|
|
//virtualserver_antiflood_points_needed_command_block
|
|
//virtualserver_antiflood_points_tick_reduce
|
|
//virtualserver_complain_autoban_count
|
|
//virtualserver_complain_autoban_time
|
|
//virtualserver_complain_remove_time
|
|
tag.find(".virtualserver_antiflood_points_needed_ip_block").val(server.properties.virtualserver_antiflood_points_needed_ip_block);
|
|
tag.find(".virtualserver_antiflood_points_needed_command_block").val(server.properties.virtualserver_antiflood_points_needed_command_block);
|
|
tag.find(".virtualserver_antiflood_points_tick_reduce").val(server.properties.virtualserver_antiflood_points_tick_reduce);
|
|
tag.find(".virtualserver_complain_autoban_count").val(server.properties.virtualserver_complain_autoban_count);
|
|
tag.find(".virtualserver_complain_autoban_time").val(server.properties.virtualserver_complain_autoban_time);
|
|
tag.find(".virtualserver_complain_remove_time").val(server.properties.virtualserver_complain_remove_time);
|
|
tag.find(".virtualserver_weblist_enabled").prop("checked", server.properties.virtualserver_weblist_enabled);
|
|
});
|
|
tag.find(".virtualserver_antiflood_points_needed_ip_block").change(function () {
|
|
properties.virtualserver_antiflood_points_needed_ip_block = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_ANTIFLOOD).granted(1));
|
|
tag.find(".virtualserver_antiflood_points_needed_command_block").change(function () {
|
|
properties.virtualserver_antiflood_points_needed_command_block = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_ANTIFLOOD).granted(1));
|
|
tag.find(".virtualserver_antiflood_points_tick_reduce").change(function () {
|
|
properties.virtualserver_antiflood_points_tick_reduce = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_ANTIFLOOD).granted(1));
|
|
tag.find(".virtualserver_complain_autoban_count").change(function () {
|
|
properties.virtualserver_complain_autoban_count = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_COMPLAIN).granted(1));
|
|
tag.find(".virtualserver_complain_autoban_time").change(function () {
|
|
properties.virtualserver_complain_autoban_time = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_COMPLAIN).granted(1));
|
|
tag.find(".virtualserver_complain_remove_time").change(function () {
|
|
properties.virtualserver_complain_remove_time = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_COMPLAIN).granted(1));
|
|
tag.find(".virtualserver_weblist_enabled").change(function () {
|
|
properties.virtualserver_weblist_enabled = $(this).prop("checked");
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_WEBLIST).granted(1));
|
|
}
|
|
function server_applyTransferListener(properties, server, tag) {
|
|
server.updateProperties().then(() => {
|
|
//virtualserver_max_upload_total_bandwidth
|
|
//virtualserver_upload_quota
|
|
//virtualserver_max_download_total_bandwidth
|
|
//virtualserver_download_quota
|
|
tag.find(".virtualserver_max_upload_total_bandwidth").val(server.properties.virtualserver_max_upload_total_bandwidth);
|
|
tag.find(".virtualserver_upload_quota").val(server.properties.virtualserver_upload_quota);
|
|
tag.find(".virtualserver_max_download_total_bandwidth").val(server.properties.virtualserver_max_download_total_bandwidth);
|
|
tag.find(".virtualserver_download_quota").val(server.properties.virtualserver_download_quota);
|
|
});
|
|
tag.find(".virtualserver_max_upload_total_bandwidth").change(function () {
|
|
properties.virtualserver_max_upload_total_bandwidth = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_FT_SETTINGS).granted(1));
|
|
tag.find(".virtualserver_max_download_total_bandwidth").change(function () {
|
|
properties.virtualserver_max_download_total_bandwidth = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_FT_SETTINGS).granted(1));
|
|
tag.find(".virtualserver_upload_quota").change(function () {
|
|
properties.virtualserver_upload_quota = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_FT_QUOTAS).granted(1));
|
|
tag.find(".virtualserver_download_quota").change(function () {
|
|
properties.virtualserver_download_quota = this.valueAsNumber;
|
|
}).prop("disabled", !globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_MODIFY_FT_QUOTAS).granted(1));
|
|
}
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["bd101f06474d59265da4974b252292ddfa87f6897614905cd9c1a1ab78ae064b"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["bd101f06474d59265da4974b252292ddfa87f6897614905cd9c1a1ab78ae064b"] = "bd101f06474d59265da4974b252292ddfa87f6897614905cd9c1a1ab78ae064b";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "TyOggpDv", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/server.ts (141,23)" }, { name: "Yo2SjrmS", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/server.ts (144,54)" }, { name: "yOT7HTle", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/server.ts (145,37)" }, { name: "Nuoj6H9J", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/server.ts (155,23)" }, { name: "tgZqV628", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/server.ts (162,37)" }, { name: "CVdq81pa", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/server.ts (162,61)" }, { name: "RygJF9MZ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/server.ts (162,102)" }, { name: "Zt0rvG9D", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/server.ts (170,70)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="channel.ts" />
|
|
/// <reference path="modal/ModalServerEdit.ts" />
|
|
class ServerProperties {
|
|
constructor() {
|
|
this.virtualserver_host = "";
|
|
this.virtualserver_port = 0;
|
|
this.virtualserver_name = "";
|
|
this.virtualserver_name_phonetic = "";
|
|
this.virtualserver_icon_id = 0;
|
|
this.virtualserver_version = "unknown";
|
|
this.virtualserver_platform = "unknown";
|
|
this.virtualserver_unique_identifier = "";
|
|
this.virtualserver_clientsonline = 0;
|
|
this.virtualserver_queryclientsonline = 0;
|
|
this.virtualserver_channelsonline = 0;
|
|
this.virtualserver_uptime = 0;
|
|
this.virtualserver_maxclients = 0;
|
|
this.virtualserver_reserved_slots = 0;
|
|
this.virtualserver_password = "";
|
|
this.virtualserver_flag_password = false;
|
|
this.virtualserver_welcomemessage = "";
|
|
this.virtualserver_hostmessage = "";
|
|
this.virtualserver_hostmessage_mode = 0;
|
|
this.virtualserver_hostbanner_url = "";
|
|
this.virtualserver_hostbanner_gfx_url = "";
|
|
this.virtualserver_hostbanner_gfx_interval = 0;
|
|
this.virtualserver_hostbanner_mode = 0;
|
|
this.virtualserver_hostbutton_tooltip = "";
|
|
this.virtualserver_hostbutton_url = "";
|
|
this.virtualserver_hostbutton_gfx_url = "";
|
|
this.virtualserver_codec_encryption_mode = 0;
|
|
this.virtualserver_default_music_group = 0;
|
|
this.virtualserver_default_server_group = 0;
|
|
this.virtualserver_default_channel_group = 0;
|
|
this.virtualserver_default_channel_admin_group = 0;
|
|
//Special requested properties
|
|
this.virtualserver_default_client_description = "";
|
|
this.virtualserver_default_channel_description = "";
|
|
this.virtualserver_default_channel_topic = "";
|
|
this.virtualserver_antiflood_points_tick_reduce = 0;
|
|
this.virtualserver_antiflood_points_needed_command_block = 0;
|
|
this.virtualserver_antiflood_points_needed_ip_block = 0;
|
|
this.virtualserver_complain_autoban_count = 0;
|
|
this.virtualserver_complain_autoban_time = 0;
|
|
this.virtualserver_complain_remove_time = 0;
|
|
this.virtualserver_needed_identity_security_level = 8;
|
|
this.virtualserver_weblist_enabled = false;
|
|
this.virtualserver_min_clients_in_channel_before_forced_silence = 0;
|
|
this.virtualserver_max_upload_total_bandwidth = 0;
|
|
this.virtualserver_upload_quota = 0;
|
|
this.virtualserver_max_download_total_bandwidth = 0;
|
|
this.virtualserver_download_quota = 0;
|
|
}
|
|
}
|
|
class ServerEntry {
|
|
constructor(tree, name, address) {
|
|
this.info_request_promise = undefined;
|
|
this.info_request_promise_resolve = undefined;
|
|
this.info_request_promise_reject = undefined;
|
|
this.lastInfoRequest = 0;
|
|
this.nextInfoRequest = 0;
|
|
this.properties = new ServerProperties();
|
|
this.channelTree = tree;
|
|
this.remote_address = address;
|
|
this.properties.virtualserver_name = name;
|
|
}
|
|
get htmlTag() {
|
|
if (this._htmlTag)
|
|
return this._htmlTag;
|
|
let tag = $.spawn("div").addClass("tree-entry server");
|
|
tag.append($.spawn("div")
|
|
.addClass("server_type icon client-server_green"));
|
|
tag.append($.spawn("div")
|
|
.addClass("name")
|
|
.text(this.properties.virtualserver_name));
|
|
tag.append($.spawn("div")
|
|
.addClass("icon_property icon_empty"));
|
|
return this._htmlTag = tag;
|
|
}
|
|
initializeListener() {
|
|
this._htmlTag.click(() => {
|
|
this.channelTree.onSelect(this);
|
|
});
|
|
if (!settings.static(Settings.KEY_DISABLE_CONTEXT_MENU, false)) {
|
|
this.htmlTag.on("contextmenu", (event) => {
|
|
event.preventDefault();
|
|
if ($.isArray(this.channelTree.currently_selected)) { //Multiselect
|
|
(this.channelTree.currently_selected_context_callback || ((_) => null))(event);
|
|
return;
|
|
}
|
|
this.channelTree.onSelect(this, true);
|
|
this.spawnContextMenu(event.pageX, event.pageY, () => { this.channelTree.onSelect(undefined, true); });
|
|
});
|
|
}
|
|
}
|
|
spawnContextMenu(x, y, on_close = () => { }) {
|
|
spawn_context_menu(x, y, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-virtualserver_edit",
|
|
name: _translations.TyOggpDv || (_translations.TyOggpDv = tr("Edit")),
|
|
callback: () => {
|
|
Modals.createServerModal(this, properties => {
|
|
log.info(LogCategory.SERVER, _translations.Yo2SjrmS || (_translations.Yo2SjrmS = tr("Changing server properties %o")), properties);
|
|
console.log(_translations.yOT7HTle || (_translations.yOT7HTle = tr("Changed properties: %o")), properties);
|
|
if (properties)
|
|
this.channelTree.client.serverConnection.send_command("serveredit", properties).then(() => {
|
|
sound.play(Sound.SERVER_EDITED_SELF);
|
|
});
|
|
});
|
|
}
|
|
}, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "client-invite_buddy",
|
|
name: _translations.Nuoj6H9J || (_translations.Nuoj6H9J = tr("Invite buddy")),
|
|
callback: () => {
|
|
const address = this.channelTree.client.serverConnection._remote_address.host + ":" + this.channelTree.client.serverConnection._remote_address.port;
|
|
const parameter = "connect_default=1&connect_address=" + encodeURIComponent(address);
|
|
const url = document.location.origin + document.location.pathname + "?" + parameter;
|
|
copy_to_clipboard(url);
|
|
createInfoModal(_translations.tgZqV628 || (_translations.tgZqV628 = tr("Buddy invite URL")), (_translations.CVdq81pa || (_translations.CVdq81pa = tr("Your buddy invite URL:<br>"))) + url + (_translations.RygJF9MZ || (_translations.RygJF9MZ = tr("<bt>This has been copied to your clipboard.")))).open();
|
|
}
|
|
}, MenuEntry.CLOSE(on_close));
|
|
}
|
|
updateVariables(is_self_notify, ...variables) {
|
|
let group = log.group(log.LogType.DEBUG, LogCategory.SERVER, _translations.Zt0rvG9D || (_translations.Zt0rvG9D = tr("Update properties (%i)")), variables.length);
|
|
let update_bannner = false;
|
|
for (let variable of variables) {
|
|
JSON.map_field_to(this.properties, variable.value, variable.key);
|
|
//TODO tr
|
|
group.log("Updating server " + this.properties.virtualserver_name + ". Key " + variable.key + " Value: '" + variable.value + "' (" + typeof (this.properties[variable.key]) + ")");
|
|
if (variable.key == "virtualserver_name") {
|
|
this.htmlTag.find(".name").text(variable.value);
|
|
}
|
|
else if (variable.key == "virtualserver_icon_id") {
|
|
if (this.channelTree.client.fileManager && this.channelTree.client.fileManager.icons)
|
|
this.htmlTag.find(".icon_property").replaceWith(this.channelTree.client.fileManager.icons.generateTag(this.properties.virtualserver_icon_id).addClass("icon_property"));
|
|
}
|
|
else if (variable.key.indexOf('hostbanner') != -1) {
|
|
update_bannner = true;
|
|
}
|
|
}
|
|
if (update_bannner)
|
|
this.channelTree.client.selectInfo.update_banner();
|
|
group.end();
|
|
if (is_self_notify && this.info_request_promise_resolve) {
|
|
this.info_request_promise_resolve();
|
|
this.info_request_promise = undefined;
|
|
this.info_request_promise_reject = undefined;
|
|
this.info_request_promise_resolve = undefined;
|
|
}
|
|
}
|
|
updateProperties() {
|
|
if (this.info_request_promise && Date.now() - this.lastInfoRequest < 1000)
|
|
return this.info_request_promise;
|
|
this.lastInfoRequest = Date.now();
|
|
this.nextInfoRequest = this.lastInfoRequest + 10 * 1000;
|
|
this.channelTree.client.serverConnection.send_command("servergetvariables").catch(error => {
|
|
this.info_request_promise_reject(error);
|
|
this.info_request_promise = undefined;
|
|
this.info_request_promise_reject = undefined;
|
|
this.info_request_promise_resolve = undefined;
|
|
});
|
|
return this.info_request_promise = new Promise((resolve, reject) => {
|
|
this.info_request_promise_reject = reject;
|
|
this.info_request_promise_resolve = resolve;
|
|
});
|
|
}
|
|
shouldUpdateProperties() {
|
|
return this.nextInfoRequest < Date.now();
|
|
}
|
|
calculateUptime() {
|
|
if (this.properties.virtualserver_uptime == 0 || this.lastInfoRequest == 0)
|
|
return this.properties.virtualserver_uptime;
|
|
return this.properties.virtualserver_uptime + (new Date().getTime() - this.lastInfoRequest) / 1000;
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["1742a73c5bf1b2d3a9d4798e06f4425c2e0934554d549e8bfb1e7e451a1c9718"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["1742a73c5bf1b2d3a9d4798e06f4425c2e0934554d549e8bfb1e7e451a1c9718"] = "1742a73c5bf1b2d3a9d4798e06f4425c2e0934554d549e8bfb1e7e451a1c9718";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "EGKSrXTJ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBookmarks.ts (42,21)" }, { name: "w0cXvTxP", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBookmarks.ts (92,37)" }, { name: "oZh862t4", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBookmarks.ts (143,36)" }, { name: "Fo8Cfk6b", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalBookmarks.ts (143,57)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../utils/modal.ts" />
|
|
/// <reference path="../../proto.ts" />
|
|
var Modals;
|
|
(function (Modals) {
|
|
function bookmark_tag(callback_select, bookmark) {
|
|
const tag = $("#tmpl_manage_bookmarks-list_entry").renderTag({
|
|
name: bookmark.display_name,
|
|
type: bookmark.type == bookmarks.BookmarkType.DIRECTORY ? "directory" : "bookmark"
|
|
});
|
|
tag.find(".name").on('click', () => {
|
|
callback_select(bookmark, tag);
|
|
tag.addClass("selected");
|
|
});
|
|
if (bookmark.type == bookmarks.BookmarkType.DIRECTORY) {
|
|
const casted = bookmark;
|
|
for (const member of casted.content)
|
|
tag.find("> .members").append(bookmark_tag(callback_select, member));
|
|
}
|
|
return tag;
|
|
}
|
|
function parent_tag(select_tag, prefix, bookmark) {
|
|
if (bookmark.type == bookmarks.BookmarkType.DIRECTORY) {
|
|
const casted = bookmark;
|
|
select_tag.append($.spawn("option")
|
|
.val(casted.unique_id)
|
|
.text(prefix + casted.display_name));
|
|
for (const member of casted.content)
|
|
parent_tag(select_tag, prefix + " ", member);
|
|
}
|
|
}
|
|
function spawnBookmarkModal() {
|
|
let modal;
|
|
modal = createModal({
|
|
header: _translations.EGKSrXTJ || (_translations.EGKSrXTJ = tr("Manage bookmarks")),
|
|
body: () => {
|
|
let template = $("#tmpl_manage_bookmarks").renderTag({});
|
|
template = $.spawn("div").append(template);
|
|
let selected_bookmark;
|
|
let update_name;
|
|
const update_bookmarks = () => {
|
|
template.find(".list").empty();
|
|
const callback_selected = (entry, tag) => {
|
|
template.find(".selected").removeClass("selected");
|
|
if (selected_bookmark == entry)
|
|
return;
|
|
selected_bookmark = entry;
|
|
update_name = () => tag.find("> .name").text(entry.display_name);
|
|
template.find(".bookmark-setting").hide();
|
|
template.find(".setting-bookmark-name").val(selected_bookmark.display_name);
|
|
if (selected_bookmark.type == bookmarks.BookmarkType.ENTRY) {
|
|
template.find(".bookmark-setting-bookmark").show();
|
|
const casted = selected_bookmark;
|
|
const profile = profiles.find_profile(casted.connect_profile) || profiles.default_profile();
|
|
template.find(".setting-bookmark-profile").val(profile.id);
|
|
template.find(".setting-server-host").val(casted.server_properties.server_address);
|
|
template.find(".setting-server-port").val(casted.server_properties.server_port);
|
|
template.find(".setting-server-password").val(casted.server_properties.server_password_hash || casted.server_properties.server_password);
|
|
template.find(".setting-username").val(casted.nickname);
|
|
template.find(".setting-channel").val(casted.default_channel);
|
|
template.find(".setting-channel-password").val(casted.default_channel_password_hash || casted.default_channel_password);
|
|
}
|
|
else {
|
|
template.find(".bookmark-setting-directory").show();
|
|
}
|
|
};
|
|
for (const bookmark of bookmarks.bookmarks().content) {
|
|
template.find(".list").append(bookmark_tag(callback_selected, bookmark));
|
|
}
|
|
console.log(template.find(".list").find(".bookmark, .directory"));
|
|
template.find(".list").find(".bookmark, .directory").eq(0).find("> .name").trigger('click');
|
|
};
|
|
{ //General buttons
|
|
template.find(".button-create").on('click', event => {
|
|
let create_modal;
|
|
create_modal = createModal({
|
|
header: _translations.w0cXvTxP || (_translations.w0cXvTxP = tr("Create a new entry")),
|
|
body: () => {
|
|
let template = $("#tmpl_manage_bookmarks-create").renderTag({});
|
|
template = $.spawn("div").append(template);
|
|
for (const bookmark of bookmarks.bookmarks().content)
|
|
parent_tag(template.find(".bookmark-parent"), "", bookmark);
|
|
if (selected_bookmark) {
|
|
const parent = selected_bookmark.type == bookmarks.BookmarkType.ENTRY ?
|
|
bookmarks.parent_bookmark(selected_bookmark) :
|
|
selected_bookmark;
|
|
if (parent)
|
|
template.find(".bookmark-parent").val(parent.unique_id);
|
|
}
|
|
template.find(".bookmark-name").on('change, keyup', event => {
|
|
template.find(".button-create").prop("disabled", event.target.value.length < 3);
|
|
});
|
|
template.find(".button-create").prop("disabled", true).on('click', event => {
|
|
const name = template.find(".bookmark-name").val();
|
|
const parent_uuid = template.find(".bookmark-parent").val();
|
|
const parent = bookmarks.find_bookmark(parent_uuid);
|
|
let bookmark;
|
|
if (template.find(".bookmark-type").val() == "directory") {
|
|
bookmark = bookmarks.create_bookmark_directory(parent || bookmarks.bookmarks(), name);
|
|
}
|
|
else {
|
|
bookmark = bookmarks.create_bookmark(name, parent || bookmarks.bookmarks(), {
|
|
server_port: 9987,
|
|
server_address: "ts.teaspeak.de"
|
|
}, "Another TeaSpeak user");
|
|
}
|
|
bookmarks.save_bookmark(bookmark);
|
|
create_modal.close();
|
|
update_bookmarks();
|
|
});
|
|
return template;
|
|
},
|
|
footer: 400
|
|
});
|
|
create_modal.open();
|
|
});
|
|
template.find(".button-delete").on('click', event => {
|
|
if (!selected_bookmark)
|
|
return;
|
|
Modals.spawnYesNo(_translations.oZh862t4 || (_translations.oZh862t4 = tr("Are you sure?")), _translations.Fo8Cfk6b || (_translations.Fo8Cfk6b = tr("Do you really want to delete this entry?")), result => {
|
|
if (result) {
|
|
bookmarks.delete_bookmark(selected_bookmark);
|
|
bookmarks.save_bookmark(selected_bookmark); /* save the deleted state */
|
|
update_bookmarks();
|
|
}
|
|
});
|
|
});
|
|
/* bookmark listener */
|
|
{
|
|
template.find(".setting-bookmark-profile").on('change', event => {
|
|
if (!selected_bookmark || selected_bookmark.type != bookmarks.BookmarkType.ENTRY)
|
|
return;
|
|
const casted = selected_bookmark;
|
|
const element = event.target;
|
|
casted.connect_profile = element.value;
|
|
bookmarks.save_bookmark(selected_bookmark);
|
|
});
|
|
template.find(".setting-server-host").on('change', event => {
|
|
if (!selected_bookmark || selected_bookmark.type != bookmarks.BookmarkType.ENTRY)
|
|
return;
|
|
const casted = selected_bookmark;
|
|
const element = event.target;
|
|
casted.server_properties.server_address = element.value;
|
|
bookmarks.save_bookmark(selected_bookmark);
|
|
});
|
|
template.find(".setting-server-port").on('change', event => {
|
|
if (!selected_bookmark || selected_bookmark.type != bookmarks.BookmarkType.ENTRY)
|
|
return;
|
|
const casted = selected_bookmark;
|
|
const element = event.target;
|
|
casted.server_properties.server_port = parseInt(element.value);
|
|
bookmarks.save_bookmark(selected_bookmark);
|
|
});
|
|
template.find(".setting-server-password").on('change', event => {
|
|
if (!selected_bookmark || selected_bookmark.type != bookmarks.BookmarkType.ENTRY)
|
|
return;
|
|
const casted = selected_bookmark;
|
|
const element = event.target;
|
|
casted.server_properties.server_password = element.value;
|
|
bookmarks.save_bookmark(selected_bookmark);
|
|
});
|
|
template.find(".setting-username").on('change', event => {
|
|
if (!selected_bookmark || selected_bookmark.type != bookmarks.BookmarkType.ENTRY)
|
|
return;
|
|
const casted = selected_bookmark;
|
|
const element = event.target;
|
|
casted.nickname = element.value;
|
|
bookmarks.save_bookmark(selected_bookmark);
|
|
});
|
|
template.find(".setting-channel").on('change', event => {
|
|
if (!selected_bookmark || selected_bookmark.type != bookmarks.BookmarkType.ENTRY)
|
|
return;
|
|
const casted = selected_bookmark;
|
|
const element = event.target;
|
|
casted.default_channel = element.value;
|
|
bookmarks.save_bookmark(selected_bookmark);
|
|
});
|
|
template.find(".setting-channel-password").on('change', event => {
|
|
if (!selected_bookmark || selected_bookmark.type != bookmarks.BookmarkType.ENTRY)
|
|
return;
|
|
const casted = selected_bookmark;
|
|
const element = event.target;
|
|
casted.default_channel_password = element.value;
|
|
bookmarks.save_bookmark(selected_bookmark);
|
|
});
|
|
}
|
|
/* listener for both */
|
|
{
|
|
template.find(".setting-bookmark-name").on('change', event => {
|
|
if (!selected_bookmark)
|
|
return;
|
|
const element = event.target;
|
|
if (element.value.length >= 3) {
|
|
selected_bookmark.display_name = element.value;
|
|
bookmarks.save_bookmark(selected_bookmark);
|
|
if (update_name)
|
|
update_name();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
/* connect profile initialisation */
|
|
{
|
|
const list = template.find(".setting-bookmark-profile");
|
|
for (const profile of profiles.profiles()) {
|
|
const tag = $.spawn("option").val(profile.id).text(profile.profile_name);
|
|
if (profile.id == "default")
|
|
tag.css("font-weight", "bold");
|
|
list.append(tag);
|
|
}
|
|
}
|
|
update_bookmarks();
|
|
template.find(".button-close").on('click', event => modal.close());
|
|
return template;
|
|
},
|
|
footer: undefined,
|
|
width: 750
|
|
});
|
|
modal.close_listener.push(() => globalClient.controlBar.update_bookmarks());
|
|
modal.open();
|
|
}
|
|
Modals.spawnBookmarkModal = spawnBookmarkModal;
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["9c4e0679ae90546e1212cf0fa94a8dc93cf5f5d6dd58dec3bdc2ea0354f64bc2"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["9c4e0679ae90546e1212cf0fa94a8dc93cf5f5d6dd58dec3bdc2ea0354f64bc2"] = "9c4e0679ae90546e1212cf0fa94a8dc93cf5f5d6dd58dec3bdc2ea0354f64bc2";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of []) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["5defa2b0b7870d87fbee02ddfa78bcf56652e21a055d43f1914c3ed58a071ce6"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["5defa2b0b7870d87fbee02ddfa78bcf56652e21a055d43f1914c3ed58a071ce6"] = "5defa2b0b7870d87fbee02ddfa78bcf56652e21a055d43f1914c3ed58a071ce6";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "Oww_8MhG", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (201,39)" }, { name: "pWwEnXuH", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (206,39)" }, { name: "d782WRD7", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (211,39)" }, { name: "jLPEqD7a", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (216,39)" }, { name: "u4Wrveax", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (379,51)" }, { name: "H8E3MA_M", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (386,51)" }, { name: "I3wO3RnF", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (417,51)" }, { name: "sVPIokB6", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (424,51)" }, { name: "YhHVnenK", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (433,47)" }, { name: "oz_lVTbr", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (439,47)" }, { name: "uhJ9MiVe", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (446,47)" }, { name: "NkqCLmwG", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (449,49)" }, { name: "MtZz4yIH", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (450,49)" }, { name: "srnRm9_W", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (457,47)" }, { name: "ZU4wsk2d", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (548,24)" }, { name: "n9Z50GLJ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (663,63)" }, { name: "mBkRBZS3", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (674,63)" }, { name: "UsIyoX72", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (689,63)" }, { name: "QlK0TuLh", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (706,63)" }, { name: "J_ce8JgI", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (819,63)" }, { name: "nCBesWoG", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (829,63)" }, { name: "nv19nyrb", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (843,63)" }, { name: "pzndfIuy", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (859,63)" }, { name: "ihkHEieL", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (954,63)" }, { name: "nhiCrQH9", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (965,63)" }, { name: "ImjQM5Jj", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (979,63)" }, { name: "smhZ_Q0H", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (996,63)" }, { name: "pdeF_A33", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (1056,63)" }, { name: "FnCGmVHb", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (1066,63)" }, { name: "b2qjExpf", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (1080,63)" }, { name: "Dr0kHgdQ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (1096,63)" }, { name: "buddzElO", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (1216,63)" }, { name: "EAsiW60n", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (1226,63)" }, { name: "FimEJKlf", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (1240,63)" }, { name: "m6BgWvPe", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPermissionEdit.ts (1256,63)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../utils/modal.ts" />
|
|
/// <reference path="../../proto.ts" />
|
|
/// <reference path="../../client.ts" />
|
|
var Modals;
|
|
(function (Modals) {
|
|
let PermissionEditorMode;
|
|
(function (PermissionEditorMode) {
|
|
PermissionEditorMode[PermissionEditorMode["VISIBLE"] = 0] = "VISIBLE";
|
|
PermissionEditorMode[PermissionEditorMode["NO_PERMISSION"] = 1] = "NO_PERMISSION";
|
|
PermissionEditorMode[PermissionEditorMode["UNSET"] = 2] = "UNSET";
|
|
})(PermissionEditorMode || (PermissionEditorMode = {}));
|
|
class PermissionEditor {
|
|
constructor(permissions) {
|
|
/* references within the container tag */
|
|
this.permission_value_map = {};
|
|
this.listener_change = () => Promise.resolve();
|
|
this.permissions = permissions;
|
|
}
|
|
build_tag() {
|
|
this.permission_map = {};
|
|
this.container = $("#tmpl_permission_editor").renderTag();
|
|
/* search for that as long we've not that much nodes */
|
|
this.mode_container_permissions = this.container.find(".container-mode-permissions");
|
|
this.mode_container_error_permission = this.container.find(".container-mode-no-permissions");
|
|
this.mode_container_unset = this.container.find(".container-mode-unset");
|
|
this.set_mode(PermissionEditorMode.UNSET);
|
|
/* the filter */
|
|
{
|
|
const tag_filter_input = this.container.find(".filter-input");
|
|
const tag_filter_granted = this.container.find(".filter-granted");
|
|
tag_filter_granted.on('change', event => tag_filter_input.trigger('change'));
|
|
tag_filter_input.on('keyup change', event => {
|
|
let filter_mask = tag_filter_input.val();
|
|
let req_granted = tag_filter_granted.prop("checked");
|
|
/* we've to disable this function because its sometimes laggy */
|
|
const org_fn = $.fn.dropdown && $.fn.dropdown.Constructor ? $.fn.dropdown.Constructor._clearMenus : undefined;
|
|
if (org_fn)
|
|
$.fn.dropdown.Constructor._clearMenus = () => { };
|
|
/* update each permission */
|
|
{
|
|
const start = Date.now();
|
|
for (const permission_id of Object.keys(this.permission_map)) {
|
|
const permission = this.permission_map[permission_id];
|
|
let shown = filter_mask.length == 0 || permission.filter.indexOf(filter_mask) != -1;
|
|
if (shown && req_granted) {
|
|
const value = this.permission_value_map[permission_id];
|
|
shown = value && (value.hasValue() || value.hasGrant());
|
|
}
|
|
permission.tag.attr("match", shown ? 1 : 0);
|
|
/* this is faster then .hide() or .show() */
|
|
if (shown)
|
|
permission.tag.css('display', 'flex');
|
|
else
|
|
permission.tag.css('display', 'none');
|
|
}
|
|
const end = Date.now();
|
|
console.error("Filter update required %oms", end - start);
|
|
}
|
|
/* update group visibility (hide empty groups) */
|
|
{
|
|
const start = Date.now();
|
|
this.container.find(".group").each((idx, _entry) => {
|
|
let entry = $(_entry);
|
|
let target = entry.find(".entry:not(.group)[match=\"1\"]").length > 0;
|
|
/* this is faster then .hide() or .show() */
|
|
if (target)
|
|
entry.css('display', 'flex');
|
|
else
|
|
entry.css('display', 'none');
|
|
});
|
|
const end = Date.now();
|
|
console.error("Group update required %oms", end - start);
|
|
}
|
|
if (org_fn)
|
|
$.fn.dropdown.Constructor._clearMenus = org_fn;
|
|
});
|
|
}
|
|
/* update button */
|
|
{
|
|
this.container.find(".button-update").on('click', this.trigger_update.bind(this));
|
|
}
|
|
/* global context menu listener */
|
|
{
|
|
this.container.on('contextmenu', event => {
|
|
if (event.isDefaultPrevented())
|
|
return;
|
|
event.preventDefault();
|
|
/* TODO allow collapse and expend all */
|
|
});
|
|
}
|
|
/* actual permissions */
|
|
{
|
|
const tag_entries = this.container.find(".entries");
|
|
const template_entry = $("#tmpl_permission_entry");
|
|
const build_group = (group) => {
|
|
const tag_group = template_entry.renderTag({
|
|
type: "group",
|
|
name: group.group.name
|
|
});
|
|
const tag_group_entries = tag_group.find(".group-entries");
|
|
const update_collapse_status = (status, recursive) => {
|
|
const tag = recursive ? this.container.find(".entry.group") : tag_group;
|
|
/* this is faster then .hide() or .show() */
|
|
if (status) {
|
|
tag.find("> .group-entries").css('display', 'block');
|
|
}
|
|
else {
|
|
tag.find("> .group-entries").css('display', 'none');
|
|
}
|
|
tag.find("> .title .arrow").toggleClass("down", status).toggleClass("right", !status);
|
|
};
|
|
/* register collapse and context listener */
|
|
{
|
|
const tag_arrow = tag_group.find(".arrow");
|
|
tag_arrow.on('click', event => {
|
|
if (event.isDefaultPrevented())
|
|
return;
|
|
event.preventDefault();
|
|
update_collapse_status(tag_arrow.hasClass("right"), false);
|
|
});
|
|
const tag_title = tag_group.find(".title");
|
|
tag_title.on('contextmenu', event => {
|
|
if (event.isDefaultPrevented())
|
|
return;
|
|
event.preventDefault();
|
|
spawn_context_menu(event.pageX, event.pageY, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "",
|
|
name: _translations.Oww_8MhG || (_translations.Oww_8MhG = tr("Expend group")),
|
|
callback: () => update_collapse_status(true, false)
|
|
}, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "",
|
|
name: _translations.pWwEnXuH || (_translations.pWwEnXuH = tr("Expend all")),
|
|
callback: () => update_collapse_status(true, true)
|
|
}, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "",
|
|
name: _translations.d782WRD7 || (_translations.d782WRD7 = tr("Collapse group")),
|
|
callback: () => update_collapse_status(false, false)
|
|
}, {
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "",
|
|
name: _translations.jLPEqD7a || (_translations.jLPEqD7a = tr("Collapse all")),
|
|
callback: () => update_collapse_status(false, true)
|
|
});
|
|
});
|
|
}
|
|
/* build the permissions */
|
|
{
|
|
for (const permission of group.permissions) {
|
|
const tag_permission = template_entry.renderTag({
|
|
type: "permission",
|
|
permission_name: permission.name,
|
|
permission_id: permission.id,
|
|
permission_description: permission.description,
|
|
});
|
|
const tag_value = tag_permission.find(".column-value input");
|
|
const tag_granted = tag_permission.find(".column-granted input");
|
|
const tag_flag_skip = tag_permission.find(".column-skip input");
|
|
const tag_flag_negate = tag_permission.find(".column-negate input");
|
|
/* double click listener */
|
|
{
|
|
tag_permission.on('dblclick', event => {
|
|
if (event.isDefaultPrevented())
|
|
return;
|
|
event.preventDefault();
|
|
if (tag_permission.hasClass("value-unset")) {
|
|
tag_flag_skip.prop("checked", false);
|
|
tag_flag_negate.prop("checked", false);
|
|
tag_permission.removeClass("value-unset");
|
|
if (permission.name.startsWith("b_")) {
|
|
tag_permission.find(".column-value input")
|
|
.prop("checked", true)
|
|
.trigger('change');
|
|
}
|
|
else {
|
|
/* TODO auto value */
|
|
tag_value.val('').focus();
|
|
}
|
|
}
|
|
else if (!permission.name.startsWith("b_")) {
|
|
tag_value.focus();
|
|
}
|
|
});
|
|
tag_permission.find(".column-granted").on('dblclick', event => {
|
|
if (event.isDefaultPrevented())
|
|
return;
|
|
event.preventDefault();
|
|
if (tag_permission.hasClass("grant-unset")) {
|
|
tag_permission.removeClass("grant-unset");
|
|
tag_granted.focus();
|
|
}
|
|
});
|
|
}
|
|
/* focus out listener */
|
|
{
|
|
tag_granted.on('focusout', event => {
|
|
try {
|
|
const value = tag_granted.val();
|
|
if (isNaN(parseInt(value)))
|
|
throw "";
|
|
}
|
|
catch (_) {
|
|
tag_granted.val("");
|
|
tag_permission.addClass("grant-unset");
|
|
const element = this.permission_value_map[permission.id];
|
|
if (element && element.hasGrant()) {
|
|
this.listener_change(permission, {
|
|
remove: true,
|
|
granted: -2
|
|
}).then(() => {
|
|
element.granted_value = undefined;
|
|
}).catch(() => {
|
|
tag_granted.val(element.granted_value);
|
|
});
|
|
}
|
|
}
|
|
});
|
|
tag_value.on('focusout', event => {
|
|
try {
|
|
if (isNaN(parseInt(tag_value.val())))
|
|
throw "";
|
|
}
|
|
catch (_) {
|
|
const element = this.permission_value_map[permission.id];
|
|
if (element && element.hasValue()) {
|
|
tag_value.val(element.value);
|
|
}
|
|
else {
|
|
tag_value.val("");
|
|
tag_permission.addClass("value-unset");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
/* change listener */
|
|
{
|
|
tag_flag_negate.on('change', () => tag_value.trigger('change'));
|
|
tag_flag_skip.on('change', () => tag_value.trigger('change'));
|
|
tag_granted.on('change', event => {
|
|
const value = parseInt(tag_granted.val());
|
|
if (isNaN(value))
|
|
return;
|
|
this.listener_change(permission, {
|
|
remove: false,
|
|
granted: value,
|
|
}).then(() => {
|
|
const element = this.permission_value_map[permission.id] || (this.permission_value_map[permission.id] = new PermissionValue(permission));
|
|
element.granted_value = value;
|
|
}).catch(() => {
|
|
const element = this.permission_value_map[permission.id];
|
|
tag_granted.val(element && element.hasGrant() ? element.granted_value : "");
|
|
tag_permission.toggleClass("grant-unset", !element || !element.hasGrant());
|
|
});
|
|
});
|
|
tag_value.on('change', event => {
|
|
const value = permission.is_boolean() ? tag_value.prop("checked") ? 1 : 0 : parseInt(tag_value.val());
|
|
if (isNaN(value))
|
|
return;
|
|
const flag_negate = tag_flag_negate.prop("checked");
|
|
const flag_skip = tag_flag_skip.prop("checked");
|
|
this.listener_change(permission, {
|
|
remove: false,
|
|
value: value,
|
|
flag_negate: flag_negate,
|
|
flag_skip: flag_skip
|
|
}).then(() => {
|
|
const element = this.permission_value_map[permission.id] || (this.permission_value_map[permission.id] = new PermissionValue(permission));
|
|
element.value = value;
|
|
element.flag_skip = flag_skip;
|
|
element.flag_negate = flag_negate;
|
|
}).catch(error => {
|
|
const element = this.permission_value_map[permission.id];
|
|
/* reset or set the fields */
|
|
if (permission.is_boolean())
|
|
tag_value.prop('checked', element && element.hasValue() && element.value > 0);
|
|
else
|
|
tag_value.val(element && element.hasValue() ? element.value : "");
|
|
tag_flag_negate.prop("checked", element && element.flag_negate);
|
|
tag_flag_skip.prop("checked", element && element.flag_skip);
|
|
tag_permission.toggleClass("value-unset", !element || !element.hasValue());
|
|
});
|
|
});
|
|
}
|
|
/* context menu */
|
|
{
|
|
tag_permission.on('contextmenu', event => {
|
|
if (event.isDefaultPrevented())
|
|
return;
|
|
event.preventDefault();
|
|
let entries = [];
|
|
if (tag_permission.hasClass("value-unset")) {
|
|
entries.push({
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "",
|
|
name: _translations.u4Wrveax || (_translations.u4Wrveax = tr("Add permission")),
|
|
callback: () => tag_permission.trigger('dblclick')
|
|
});
|
|
}
|
|
else {
|
|
entries.push({
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "",
|
|
name: _translations.H8E3MA_M || (_translations.H8E3MA_M = tr("Remove permission")),
|
|
callback: () => {
|
|
this.listener_change(permission, {
|
|
remove: true,
|
|
value: -2
|
|
}).then(() => {
|
|
const element = this.permission_value_map[permission.id];
|
|
if (!element)
|
|
return; /* This should never happen, if so how are we displaying this permission?! */
|
|
element.value = undefined;
|
|
element.flag_negate = false;
|
|
element.flag_skip = false;
|
|
tag_permission.toggleClass("value-unset", true);
|
|
}).catch(() => {
|
|
const element = this.permission_value_map[permission.id];
|
|
/* reset or set the fields */
|
|
tag_value.val(element && element.hasValue() ? element.value : "");
|
|
tag_flag_negate.prop("checked", element && element.flag_negate);
|
|
tag_flag_skip.prop("checked", element && element.flag_skip);
|
|
tag_permission.toggleClass("value-unset", !element || !element.hasValue());
|
|
});
|
|
}
|
|
});
|
|
}
|
|
if (tag_permission.hasClass("grant-unset")) {
|
|
entries.push({
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "",
|
|
name: _translations.I3wO3RnF || (_translations.I3wO3RnF = tr("Add grant permission")),
|
|
callback: () => tag_permission.find(".column-granted").trigger('dblclick')
|
|
});
|
|
}
|
|
else {
|
|
entries.push({
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "",
|
|
name: _translations.sVPIokB6 || (_translations.sVPIokB6 = tr("Remove grant permission")),
|
|
callback: () => tag_granted.val('').trigger('focusout') /* empty values are handled within focus out */
|
|
});
|
|
}
|
|
entries.push(MenuEntry.HR());
|
|
entries.push({
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "",
|
|
name: _translations.YhHVnenK || (_translations.YhHVnenK = tr("Expend all")),
|
|
callback: () => update_collapse_status(true, true)
|
|
});
|
|
entries.push({
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "",
|
|
name: _translations.oz_lVTbr || (_translations.oz_lVTbr = tr("Collapse all")),
|
|
callback: () => update_collapse_status(false, true)
|
|
});
|
|
entries.push(MenuEntry.HR());
|
|
entries.push({
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "",
|
|
name: _translations.uhJ9MiVe || (_translations.uhJ9MiVe = tr("Show permission description")),
|
|
callback: () => {
|
|
createInfoModal(_translations.NkqCLmwG || (_translations.NkqCLmwG = tr("Permission description")), (_translations.MtZz4yIH || (_translations.MtZz4yIH = tr("Permission description for permission "))) + permission.name + ": <br>" + permission.description).open();
|
|
}
|
|
});
|
|
entries.push({
|
|
type: MenuEntryType.ENTRY,
|
|
icon: "",
|
|
name: _translations.srnRm9_W || (_translations.srnRm9_W = tr("Copy permission name")),
|
|
callback: () => {
|
|
copy_to_clipboard(permission.name);
|
|
}
|
|
});
|
|
spawn_context_menu(event.pageX, event.pageY, ...entries);
|
|
});
|
|
}
|
|
this.permission_map[permission.id] = {
|
|
tag: tag_permission,
|
|
id: permission.id,
|
|
filter: permission.name,
|
|
tag_flag_negate: tag_flag_negate,
|
|
tag_flag_skip: tag_flag_skip,
|
|
tag_grant: tag_granted,
|
|
tag_value: tag_value,
|
|
is_bool: permission.is_boolean()
|
|
};
|
|
tag_group_entries.append(tag_permission);
|
|
}
|
|
}
|
|
/* append the subgroups */
|
|
for (const child of group.children) {
|
|
tag_group_entries.append(build_group(child));
|
|
}
|
|
return tag_group;
|
|
};
|
|
/* build the groups */
|
|
for (const group of this.permissions)
|
|
tag_entries.append(build_group(group));
|
|
}
|
|
}
|
|
set_permissions(permissions) {
|
|
permissions = permissions || [];
|
|
this.permission_value_map = {};
|
|
for (const permission of permissions)
|
|
this.permission_value_map[permission.type.id] = permission;
|
|
for (const permission_id of Object.keys(this.permission_map)) {
|
|
const permission = this.permission_map[permission_id];
|
|
const value = this.permission_value_map[permission_id];
|
|
permission.tag
|
|
.toggleClass("value-unset", !value || !value.hasValue())
|
|
.toggleClass("grant-unset", !value || !value.hasGrant());
|
|
if (value && value.hasValue()) {
|
|
if (value.type.is_boolean())
|
|
permission.tag_value.prop("checked", value.value);
|
|
else
|
|
permission.tag_value.val(value.value);
|
|
permission.tag_flag_skip.prop("checked", value.flag_skip);
|
|
permission.tag_flag_negate.prop("checked", value.flag_negate);
|
|
}
|
|
if (value && value.hasGrant()) {
|
|
permission.tag_grant.val(value.granted_value);
|
|
}
|
|
}
|
|
}
|
|
set_listener(listener) {
|
|
this.listener_change = listener || (() => Promise.resolve());
|
|
}
|
|
set_listener_update(listener) {
|
|
this.listener_update = listener;
|
|
}
|
|
trigger_update() {
|
|
if (this.listener_update)
|
|
this.listener_update();
|
|
}
|
|
set_mode(mode) {
|
|
this.mode_container_permissions.css('display', mode == PermissionEditorMode.VISIBLE ? 'flex' : 'none');
|
|
this.mode_container_error_permission.css('display', mode == PermissionEditorMode.NO_PERMISSION ? 'flex' : 'none');
|
|
this.mode_container_unset.css('display', mode == PermissionEditorMode.UNSET ? 'block' : 'none');
|
|
}
|
|
}
|
|
function spawnPermissionEdit() {
|
|
const connectModal = createModal({
|
|
header: function () {
|
|
return _translations.ZU4wsk2d || (_translations.ZU4wsk2d = tr("Server Permissions"));
|
|
},
|
|
body: function () {
|
|
let properties = {};
|
|
let tag = $("#tmpl_server_permissions").renderTag(properties);
|
|
const pe = new PermissionEditor(globalClient.permissions.groupedPermissions());
|
|
pe.build_tag();
|
|
/* initialisation */
|
|
{
|
|
const pe_server = tag.find("permission-editor.group-server");
|
|
pe_server.append(pe.container); /* fuck off workaround to initialize form listener */
|
|
}
|
|
apply_server_groups(pe, tag.find(".tab-group-server"));
|
|
apply_channel_groups(pe, tag.find(".tab-group-channel"));
|
|
apply_channel_permission(pe, tag.find(".tab-channel"));
|
|
apply_client_permission(pe, tag.find(".tab-client"));
|
|
apply_client_channel_permission(pe, tag.find(".tab-client-channel"));
|
|
return tag.tabify(false);
|
|
},
|
|
footer: undefined,
|
|
width: "90%",
|
|
height: "80%",
|
|
trigger_tab: false,
|
|
full_size: true
|
|
});
|
|
const tag = connectModal.htmlTag;
|
|
tag.find(".btn_close").on('click', () => {
|
|
connectModal.close();
|
|
});
|
|
return connectModal;
|
|
}
|
|
Modals.spawnPermissionEdit = spawnPermissionEdit;
|
|
function build_channel_tree(channel_list, select_callback) {
|
|
const root = globalClient.channelTree.get_first_channel();
|
|
if (!root)
|
|
return;
|
|
const build_channel = (channel) => {
|
|
let tag = $.spawn("div").addClass("channel").attr("channel-id", channel.channelId);
|
|
globalClient.fileManager.icons.generateTag(channel.properties.channel_icon_id).appendTo(tag);
|
|
{
|
|
let name = $.spawn("a").text(channel.channelName() + " (" + channel.channelId + ")").addClass("name");
|
|
//if(globalClient.channelTree.server.properties. == group.id)
|
|
// name.addClass("default");
|
|
name.appendTo(tag);
|
|
}
|
|
tag.on('click', event => {
|
|
channel_list.find(".selected").removeClass("selected");
|
|
tag.addClass("selected");
|
|
select_callback(channel);
|
|
});
|
|
return tag;
|
|
};
|
|
const build_channels = (root) => {
|
|
build_channel(root).appendTo(channel_list);
|
|
for (const child of root.children())
|
|
build_channels(child);
|
|
while (root.channel_next) {
|
|
root = root.channel_next;
|
|
build_channel(root).appendTo(channel_list);
|
|
}
|
|
};
|
|
build_channels(root);
|
|
setTimeout(() => channel_list.find('.channel').first().trigger('click'), 0);
|
|
}
|
|
function apply_client_channel_permission(editor, tab_tag) {
|
|
let current_cldbid = 0;
|
|
let current_channel;
|
|
/* the editor */
|
|
{
|
|
const pe_client = tab_tag.find("permission-editor.client-channel");
|
|
tab_tag.on('show', event => {
|
|
console.error("Channel tab show");
|
|
pe_client.append(editor.container);
|
|
if (globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_CLIENT_PERMISSION_LIST).granted(1)) {
|
|
if (current_cldbid && current_channel)
|
|
editor.set_mode(PermissionEditorMode.VISIBLE);
|
|
else
|
|
editor.set_mode(PermissionEditorMode.UNSET);
|
|
}
|
|
else {
|
|
editor.set_mode(PermissionEditorMode.NO_PERMISSION);
|
|
return;
|
|
}
|
|
editor.set_listener_update(() => {
|
|
if (!current_cldbid || !current_channel)
|
|
return;
|
|
globalClient.permissions.requestClientChannelPermissions(current_cldbid, current_channel.channelId).then(result => {
|
|
editor.set_permissions(result);
|
|
editor.set_mode(PermissionEditorMode.VISIBLE);
|
|
}).catch(error => {
|
|
console.log(error); //TODO handling?
|
|
});
|
|
});
|
|
editor.set_listener((permission, value) => {
|
|
if (!current_cldbid)
|
|
return Promise.reject("unset client");
|
|
if (!current_channel)
|
|
return Promise.reject("unset channel");
|
|
if (value.remove) {
|
|
/* remove the permission */
|
|
if (typeof (value.value) !== "undefined") {
|
|
log.info(LogCategory.PERMISSIONS, _translations.n9Z50GLJ || (_translations.n9Z50GLJ = tr("Removing client channel permission %s. permission.id: %o")), permission.name, permission.id);
|
|
return globalClient.serverConnection.send_command("channelclientdelperm", {
|
|
cldbid: current_cldbid,
|
|
cid: current_channel.channelId,
|
|
permid: permission.id,
|
|
});
|
|
}
|
|
else {
|
|
log.info(LogCategory.PERMISSIONS, _translations.mBkRBZS3 || (_translations.mBkRBZS3 = tr("Removing client channel grant permission %s. permission.id: %o")), permission.name, permission.id_grant(), value.granted);
|
|
return globalClient.serverConnection.send_command("channelclientdelperm", {
|
|
cldbid: current_cldbid,
|
|
cid: current_channel.channelId,
|
|
permid: permission.id_grant(),
|
|
});
|
|
}
|
|
}
|
|
else {
|
|
/* add the permission */
|
|
if (typeof (value.value) !== "undefined") {
|
|
log.info(LogCategory.PERMISSIONS, _translations.UsIyoX72 || (_translations.UsIyoX72 = tr("Adding or updating client channel permission %s. permission.{id: %o, value: %o, flag_skip: %o, flag_negate: %o}")), permission.name, permission.id, value.value, value.flag_skip, value.flag_negate);
|
|
return globalClient.serverConnection.send_command("channelclientaddperm", {
|
|
cldbid: current_cldbid,
|
|
cid: current_channel.channelId,
|
|
permid: permission.id,
|
|
permvalue: value.value,
|
|
permskip: value.flag_skip,
|
|
permnegate: value.flag_negate
|
|
});
|
|
}
|
|
else {
|
|
log.info(LogCategory.PERMISSIONS, _translations.QlK0TuLh || (_translations.QlK0TuLh = tr("Adding or updating client channel grant permission %s. permission.{id: %o, value: %o}")), permission.name, permission.id_grant(), value.granted);
|
|
return globalClient.serverConnection.send_command("channelclientaddperm", {
|
|
cldbid: current_cldbid,
|
|
cid: current_channel.channelId,
|
|
permid: permission.id_grant(),
|
|
permvalue: value.granted,
|
|
permskip: false,
|
|
permnegate: false
|
|
});
|
|
}
|
|
}
|
|
});
|
|
/* FIXME: Use cached permissions */
|
|
editor.trigger_update();
|
|
});
|
|
}
|
|
build_channel_tree(tab_tag.find(".list-channel .entries"), channel => {
|
|
if (current_channel == channel)
|
|
return;
|
|
current_channel = channel;
|
|
/* TODO: Test for visibility */
|
|
editor.trigger_update();
|
|
});
|
|
{
|
|
const tag_select_uid = tab_tag.find(".client-select input");
|
|
const tag_select_error = tab_tag.find(".client-select .invalid-feedback");
|
|
const tag_client_name = tab_tag.find(".client-name");
|
|
const tag_client_uid = tab_tag.find(".client-uid");
|
|
const tag_client_dbid = tab_tag.find(".client-dbid");
|
|
const resolve_client = () => {
|
|
let client_uid = tag_select_uid.val();
|
|
globalClient.serverConnection.command_helper.info_from_uid(client_uid).then(result => {
|
|
if (!result || result.length == 0)
|
|
return Promise.reject("invalid data");
|
|
tag_select_uid.attr('pattern', null).removeClass('is-invalid');
|
|
tag_client_name.val(result[0].client_nickname);
|
|
tag_client_uid.val(result[0].client_unique_id);
|
|
tag_client_dbid.val(result[0].client_database_id);
|
|
current_cldbid = result[0].client_database_id;
|
|
editor.trigger_update();
|
|
}).catch(error => {
|
|
console.log(error);
|
|
if (error instanceof CommandResult) {
|
|
if (error.id == ErrorID.EMPTY_RESULT)
|
|
error = "unknown client";
|
|
else
|
|
error = error.extra_message || error.message;
|
|
}
|
|
tag_client_name.val("");
|
|
tag_client_uid.val("");
|
|
tag_client_dbid.val("");
|
|
tag_select_error.text(error);
|
|
tag_select_uid.attr('pattern', '^[a]{1000}$').addClass('is-invalid');
|
|
editor.set_mode(PermissionEditorMode.UNSET);
|
|
});
|
|
};
|
|
tab_tag.find(".client-select-uid").on('change', event => resolve_client());
|
|
}
|
|
}
|
|
function apply_client_permission(editor, tab_tag) {
|
|
let current_cldbid = 0;
|
|
/* the editor */
|
|
{
|
|
const pe_client = tab_tag.find("permission-editor.client");
|
|
tab_tag.on('show', event => {
|
|
console.error("Channel tab show");
|
|
pe_client.append(editor.container);
|
|
if (globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_CLIENT_PERMISSION_LIST).granted(1)) {
|
|
if (current_cldbid)
|
|
editor.set_mode(PermissionEditorMode.VISIBLE);
|
|
else
|
|
editor.set_mode(PermissionEditorMode.UNSET);
|
|
}
|
|
else {
|
|
editor.set_mode(PermissionEditorMode.NO_PERMISSION);
|
|
return;
|
|
}
|
|
editor.set_listener_update(() => {
|
|
if (!current_cldbid)
|
|
return;
|
|
globalClient.permissions.requestClientPermissions(current_cldbid).then(result => {
|
|
editor.set_permissions(result);
|
|
editor.set_mode(PermissionEditorMode.VISIBLE);
|
|
}).catch(error => {
|
|
console.log(error); //TODO handling?
|
|
});
|
|
});
|
|
editor.set_listener((permission, value) => {
|
|
if (!current_cldbid)
|
|
return Promise.reject("unset client");
|
|
if (value.remove) {
|
|
/* remove the permission */
|
|
if (typeof (value.value) !== "undefined") {
|
|
log.info(LogCategory.PERMISSIONS, _translations.J_ce8JgI || (_translations.J_ce8JgI = tr("Removing client permission %s. permission.id: %o")), permission.name, permission.id);
|
|
return globalClient.serverConnection.send_command("clientaddperm", {
|
|
cldbid: current_cldbid,
|
|
permid: permission.id,
|
|
});
|
|
}
|
|
else {
|
|
log.info(LogCategory.PERMISSIONS, _translations.nCBesWoG || (_translations.nCBesWoG = tr("Removing client grant permission %s. permission.id: %o")), permission.name, permission.id_grant(), value.granted);
|
|
return globalClient.serverConnection.send_command("clientaddperm", {
|
|
cldbid: current_cldbid,
|
|
permid: permission.id_grant(),
|
|
});
|
|
}
|
|
}
|
|
else {
|
|
/* add the permission */
|
|
if (typeof (value.value) !== "undefined") {
|
|
log.info(LogCategory.PERMISSIONS, _translations.nv19nyrb || (_translations.nv19nyrb = tr("Adding or updating client permission %s. permission.{id: %o, value: %o, flag_skip: %o, flag_negate: %o}")), permission.name, permission.id, value.value, value.flag_skip, value.flag_negate);
|
|
return globalClient.serverConnection.send_command("clientaddperm", {
|
|
cldbid: current_cldbid,
|
|
permid: permission.id,
|
|
permvalue: value.value,
|
|
permskip: value.flag_skip,
|
|
permnegate: value.flag_negate
|
|
});
|
|
}
|
|
else {
|
|
log.info(LogCategory.PERMISSIONS, _translations.pzndfIuy || (_translations.pzndfIuy = tr("Adding or updating client grant permission %s. permission.{id: %o, value: %o}")), permission.name, permission.id_grant(), value.granted);
|
|
return globalClient.serverConnection.send_command("clientaddperm", {
|
|
cldbid: current_cldbid,
|
|
permid: permission.id_grant(),
|
|
permvalue: value.granted,
|
|
permskip: false,
|
|
permnegate: false
|
|
});
|
|
}
|
|
}
|
|
});
|
|
/* FIXME: Use cached permissions */
|
|
editor.trigger_update();
|
|
});
|
|
}
|
|
const tag_select_uid = tab_tag.find(".client-select input");
|
|
const tag_select_error = tab_tag.find(".client-select .invalid-feedback");
|
|
const tag_client_name = tab_tag.find(".client-name");
|
|
const tag_client_uid = tab_tag.find(".client-uid");
|
|
const tag_client_dbid = tab_tag.find(".client-dbid");
|
|
const resolve_client = () => {
|
|
let client_uid = tag_select_uid.val();
|
|
globalClient.serverConnection.command_helper.info_from_uid(client_uid).then(result => {
|
|
if (!result || result.length == 0)
|
|
return Promise.reject("invalid data");
|
|
tag_select_uid.attr('pattern', null).removeClass('is-invalid');
|
|
tag_client_name.val(result[0].client_nickname);
|
|
tag_client_uid.val(result[0].client_unique_id);
|
|
tag_client_dbid.val(result[0].client_database_id);
|
|
current_cldbid = result[0].client_database_id;
|
|
editor.trigger_update();
|
|
}).catch(error => {
|
|
console.log(error);
|
|
if (error instanceof CommandResult) {
|
|
if (error.id == ErrorID.EMPTY_RESULT)
|
|
error = "unknown client";
|
|
else
|
|
error = error.extra_message || error.message;
|
|
}
|
|
tag_client_name.val("");
|
|
tag_client_uid.val("");
|
|
tag_client_dbid.val("");
|
|
tag_select_error.text(error);
|
|
tag_select_uid.attr('pattern', '^[a]{1000}$').addClass('is-invalid');
|
|
editor.set_mode(PermissionEditorMode.UNSET);
|
|
});
|
|
};
|
|
tab_tag.find(".client-select-uid").on('change', event => resolve_client());
|
|
}
|
|
function apply_channel_permission(editor, tab_tag) {
|
|
let current_channel;
|
|
/* the editor */
|
|
{
|
|
const pe_channel = tab_tag.find("permission-editor.channel");
|
|
tab_tag.on('show', event => {
|
|
console.error("Channel tab show");
|
|
pe_channel.append(editor.container);
|
|
if (globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_CHANNEL_PERMISSION_LIST).granted(1))
|
|
editor.set_mode(PermissionEditorMode.VISIBLE);
|
|
else {
|
|
editor.set_mode(PermissionEditorMode.NO_PERMISSION);
|
|
return;
|
|
}
|
|
editor.set_listener_update(() => {
|
|
if (!current_channel)
|
|
return;
|
|
globalClient.permissions.requestChannelPermissions(current_channel.channelId).then(result => editor.set_permissions(result)).catch(error => {
|
|
console.log(error); //TODO handling?
|
|
});
|
|
});
|
|
editor.set_listener((permission, value) => {
|
|
if (!current_channel)
|
|
return Promise.reject("unset channel");
|
|
if (value.remove) {
|
|
/* remove the permission */
|
|
if (typeof (value.value) !== "undefined") {
|
|
log.info(LogCategory.PERMISSIONS, _translations.ihkHEieL || (_translations.ihkHEieL = tr("Removing channel permission %s. permission.id: %o")), permission.name, permission.id);
|
|
return globalClient.serverConnection.send_command("channeldelperm", {
|
|
cid: current_channel.channelId,
|
|
permid: permission.id,
|
|
});
|
|
}
|
|
else {
|
|
/* TODO Remove this because its totally useless. Remove this from the UI as well */
|
|
log.info(LogCategory.PERMISSIONS, _translations.nhiCrQH9 || (_translations.nhiCrQH9 = tr("Removing channel grant permission %s. permission.id: %o")), permission.name, permission.id_grant(), value.granted);
|
|
return globalClient.serverConnection.send_command("channeldelperm", {
|
|
cid: current_channel.channelId,
|
|
permid: permission.id_grant(),
|
|
});
|
|
}
|
|
}
|
|
else {
|
|
/* add the permission */
|
|
if (typeof (value.value) !== "undefined") {
|
|
log.info(LogCategory.PERMISSIONS, _translations.ImjQM5Jj || (_translations.ImjQM5Jj = tr("Adding or updating channel permission %s. permission.{id: %o, value: %o, flag_skip: %o, flag_negate: %o}")), permission.name, permission.id, value.value, value.flag_skip, value.flag_negate);
|
|
return globalClient.serverConnection.send_command("channeladdperm", {
|
|
cid: current_channel.channelId,
|
|
permid: permission.id,
|
|
permvalue: value.value,
|
|
permskip: value.flag_skip,
|
|
permnegate: value.flag_negate
|
|
});
|
|
}
|
|
else {
|
|
/* TODO Remove this because its totally useless. Remove this from the UI as well */
|
|
log.info(LogCategory.PERMISSIONS, _translations.smhZ_Q0H || (_translations.smhZ_Q0H = tr("Adding or updating channel grant permission %s. permission.{id: %o, value: %o}")), permission.name, permission.id_grant(), value.granted);
|
|
return globalClient.serverConnection.send_command("channeladdperm", {
|
|
cid: current_channel.channelId,
|
|
permid: permission.id_grant(),
|
|
permvalue: value.granted,
|
|
permskip: false,
|
|
permnegate: false
|
|
});
|
|
}
|
|
}
|
|
});
|
|
/* FIXME: Use cached permissions */
|
|
editor.trigger_update();
|
|
});
|
|
}
|
|
let channel_list = tab_tag.find(".list-channel .entries");
|
|
build_channel_tree(channel_list, channel => {
|
|
current_channel = channel;
|
|
editor.trigger_update();
|
|
});
|
|
}
|
|
function apply_channel_groups(editor, tab_tag) {
|
|
let current_group;
|
|
/* the editor */
|
|
{
|
|
const pe_server = tab_tag.find("permission-editor.group-channel");
|
|
tab_tag.on('show', event => {
|
|
console.error("Channel group tab show");
|
|
pe_server.append(editor.container);
|
|
if (globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_CHANNELGROUP_PERMISSION_LIST).granted(1))
|
|
editor.set_mode(PermissionEditorMode.VISIBLE);
|
|
else {
|
|
editor.set_mode(PermissionEditorMode.NO_PERMISSION);
|
|
return;
|
|
}
|
|
editor.set_listener_update(() => {
|
|
if (!current_group)
|
|
return;
|
|
globalClient.groups.request_permissions(current_group).then(result => editor.set_permissions(result)).catch(error => {
|
|
console.log(error); //TODO handling?
|
|
});
|
|
});
|
|
editor.set_listener((permission, value) => {
|
|
if (!current_group)
|
|
return Promise.reject("unset channel group");
|
|
if (value.remove) {
|
|
/* remove the permission */
|
|
if (typeof (value.value) !== "undefined") {
|
|
log.info(LogCategory.PERMISSIONS, _translations.pdeF_A33 || (_translations.pdeF_A33 = tr("Removing channel group permission %s. permission.id: %o")), permission.name, permission.id);
|
|
return globalClient.serverConnection.send_command("channelgroupdelperm", {
|
|
cgid: current_group.id,
|
|
permid: permission.id,
|
|
});
|
|
}
|
|
else {
|
|
log.info(LogCategory.PERMISSIONS, _translations.FnCGmVHb || (_translations.FnCGmVHb = tr("Removing channel group grant permission %s. permission.id: %o")), permission.name, permission.id_grant(), value.granted);
|
|
return globalClient.serverConnection.send_command("channelgroupdelperm", {
|
|
cgid: current_group.id,
|
|
permid: permission.id_grant(),
|
|
});
|
|
}
|
|
}
|
|
else {
|
|
/* add the permission */
|
|
if (typeof (value.value) !== "undefined") {
|
|
log.info(LogCategory.PERMISSIONS, _translations.b2qjExpf || (_translations.b2qjExpf = tr("Adding or updating channel group permission %s. permission.{id: %o, value: %o, flag_skip: %o, flag_negate: %o}")), permission.name, permission.id, value.value, value.flag_skip, value.flag_negate);
|
|
return globalClient.serverConnection.send_command("channelgroupaddperm", {
|
|
cgid: current_group.id,
|
|
permid: permission.id,
|
|
permvalue: value.value,
|
|
permskip: value.flag_skip,
|
|
permnegate: value.flag_negate
|
|
});
|
|
}
|
|
else {
|
|
log.info(LogCategory.PERMISSIONS, _translations.Dr0kHgdQ || (_translations.Dr0kHgdQ = tr("Adding or updating channel group grant permission %s. permission.{id: %o, value: %o}")), permission.name, permission.id_grant(), value.granted);
|
|
return globalClient.serverConnection.send_command("channelgroupaddperm", {
|
|
cgid: current_group.id,
|
|
permid: permission.id_grant(),
|
|
permvalue: value.granted,
|
|
permskip: false,
|
|
permnegate: false
|
|
});
|
|
}
|
|
}
|
|
});
|
|
/* FIXME: Use cached permissions */
|
|
editor.trigger_update();
|
|
});
|
|
}
|
|
/* list all channel groups */
|
|
{
|
|
let group_list = tab_tag.find(".list-group-channel .entries");
|
|
for (let group of globalClient.groups.channelGroups.sort(GroupManager.sorter())) {
|
|
let tag = $.spawn("div").addClass("group").attr("group-id", group.id);
|
|
globalClient.fileManager.icons.generateTag(group.properties.iconid).appendTo(tag);
|
|
{
|
|
let name = $.spawn("a").text(group.name + " (" + group.id + ")").addClass("name");
|
|
if (group.properties.savedb)
|
|
name.addClass("savedb");
|
|
if (globalClient.channelTree.server.properties.virtualserver_default_channel_group == group.id)
|
|
name.addClass("default");
|
|
name.appendTo(tag);
|
|
}
|
|
tag.appendTo(group_list);
|
|
tag.on('click', event => {
|
|
current_group = group;
|
|
group_list.find(".selected").removeClass("selected");
|
|
tag.addClass("selected");
|
|
//TODO trigger only if the editor is in channel group mode!
|
|
editor.trigger_update();
|
|
});
|
|
}
|
|
/* because the server menu is the first which will be shown */
|
|
setTimeout(() => group_list.find('.group').first().trigger('click'), 0);
|
|
}
|
|
}
|
|
/*
|
|
b_virtualserver_servergroup_permission_list
|
|
b_virtualserver_channel_permission_list
|
|
b_virtualserver_client_permission_list
|
|
b_virtualserver_channelgroup_permission_list
|
|
b_virtualserver_channelclient_permission_list
|
|
b_virtualserver_playlist_permission_list
|
|
*/
|
|
function apply_server_groups(editor, tab_tag) {
|
|
let current_group;
|
|
/* list all groups */
|
|
{
|
|
let group_list = tab_tag.find(".list-group-server .entries");
|
|
for (let group of globalClient.groups.serverGroups.sort(GroupManager.sorter())) {
|
|
let tag = $.spawn("div").addClass("group").attr("group-id", group.id);
|
|
globalClient.fileManager.icons.generateTag(group.properties.iconid).appendTo(tag);
|
|
{
|
|
let name = $.spawn("a").text(group.name + " (" + group.id + ")").addClass("name");
|
|
if (group.properties.savedb)
|
|
name.addClass("savedb");
|
|
if (globalClient.channelTree.server.properties.virtualserver_default_server_group == group.id)
|
|
name.addClass("default");
|
|
name.appendTo(tag);
|
|
}
|
|
tag.appendTo(group_list);
|
|
tag.on('click', event => {
|
|
current_group = group;
|
|
group_list.find(".selected").removeClass("selected");
|
|
tag.addClass("selected");
|
|
editor.trigger_update();
|
|
});
|
|
}
|
|
/* because the server menu is the first which will be shown */
|
|
setTimeout(() => group_list.find('.group').first().trigger('click'), 0);
|
|
}
|
|
/* the editor */
|
|
{
|
|
const pe_server = tab_tag.find("permission-editor.group-server");
|
|
tab_tag.on('show', event => {
|
|
console.error("Server tab show");
|
|
pe_server.append(editor.container);
|
|
if (globalClient.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_SERVERGROUP_PERMISSION_LIST).granted(1))
|
|
editor.set_mode(PermissionEditorMode.VISIBLE);
|
|
else {
|
|
editor.set_mode(PermissionEditorMode.NO_PERMISSION);
|
|
return;
|
|
}
|
|
editor.set_listener_update(() => {
|
|
globalClient.groups.request_permissions(current_group).then(result => editor.set_permissions(result)).catch(error => {
|
|
console.log(error); //TODO handling?
|
|
});
|
|
});
|
|
editor.set_listener((permission, value) => {
|
|
if (!current_group)
|
|
return Promise.reject("unset server group");
|
|
if (value.remove) {
|
|
/* remove the permission */
|
|
if (typeof (value.value) !== "undefined") {
|
|
log.info(LogCategory.PERMISSIONS, _translations.buddzElO || (_translations.buddzElO = tr("Removing server group permission %s. permission.id: %o")), permission.name, permission.id);
|
|
return globalClient.serverConnection.send_command("servergroupdelperm", {
|
|
sgid: current_group.id,
|
|
permid: permission.id,
|
|
});
|
|
}
|
|
else {
|
|
log.info(LogCategory.PERMISSIONS, _translations.EAsiW60n || (_translations.EAsiW60n = tr("Removing server group grant permission %s. permission.id: %o")), permission.name, permission.id_grant(), value.granted);
|
|
return globalClient.serverConnection.send_command("servergroupdelperm", {
|
|
sgid: current_group.id,
|
|
permid: permission.id_grant(),
|
|
});
|
|
}
|
|
}
|
|
else {
|
|
/* add the permission */
|
|
if (typeof (value.value) !== "undefined") {
|
|
log.info(LogCategory.PERMISSIONS, _translations.FimEJKlf || (_translations.FimEJKlf = tr("Adding or updating server group permission %s. permission.{id: %o, value: %o, flag_skip: %o, flag_negate: %o}")), permission.name, permission.id, value.value, value.flag_skip, value.flag_negate);
|
|
return globalClient.serverConnection.send_command("servergroupaddperm", {
|
|
sgid: current_group.id,
|
|
permid: permission.id,
|
|
permvalue: value.value,
|
|
permskip: value.flag_skip,
|
|
permnegate: value.flag_negate
|
|
});
|
|
}
|
|
else {
|
|
log.info(LogCategory.PERMISSIONS, _translations.m6BgWvPe || (_translations.m6BgWvPe = tr("Adding or updating server group grant permission %s. permission.{id: %o, value: %o}")), permission.name, permission.id_grant(), value.granted);
|
|
return globalClient.serverConnection.send_command("servergroupaddperm", {
|
|
sgid: current_group.id,
|
|
permid: permission.id_grant(),
|
|
permvalue: value.granted,
|
|
permskip: false,
|
|
permnegate: false
|
|
});
|
|
}
|
|
}
|
|
});
|
|
editor.trigger_update();
|
|
});
|
|
}
|
|
}
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["e9fc308fbc7dd673ccc12df343a8fbe32f2790467fa2716feacf070b441aa9dd"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["e9fc308fbc7dd673ccc12df343a8fbe32f2790467fa2716feacf070b441aa9dd"] = "e9fc308fbc7dd673ccc12df343a8fbe32f2790467fa2716feacf070b441aa9dd";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "Vzv70U1I", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (10,21)" }, { name: "NQh5eGr5", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (43,21)" }, { name: "tmSzNTzy", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (83,21)" }, { name: "n7VcWm07", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (108,46)" }, { name: "a_TZcP0H", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (108,82)" }, { name: "NB7sciFG", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (130,46)" }, { name: "mnek9ENK", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (130,82)" }, { name: "m6AIHquf", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (137,36)" }, { name: "jEelVGXf", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (137,57)" }, { name: "eWqk1aTM", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (178,27)" }, { name: "zynyuRv_", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (207,50)" }, { name: "EaOaEwhp", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (207,80)" }, { name: "v6RuZ030", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (230,31)" }, { name: "I43FEeaW", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (248,38)" }, { name: "KwvQCSiF", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (248,65)" }, { name: "YI9EW4YZ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (352,30)" }, { name: "LuuiZhoN", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistEdit.ts (352,67)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../utils/modal.ts" />
|
|
/// <reference path="../../proto.ts" />
|
|
/// <reference path="../../client.ts" />
|
|
var Modals;
|
|
(function (Modals) {
|
|
function spawnPlaylistSongInfo(song) {
|
|
let modal;
|
|
modal = createModal({
|
|
header: _translations.Vzv70U1I || (_translations.Vzv70U1I = tr("Song info")),
|
|
body: () => {
|
|
try {
|
|
song.metadata = JSON.parse(song.song_metadata);
|
|
}
|
|
catch (e) { }
|
|
let template = $("#tmpl_playlist_edit-song_info").renderTag(song);
|
|
template = $.spawn("div").append(template);
|
|
const text_area = template.find(".property-metadata-raw textarea");
|
|
template.find(".toggle-metadata").on('click', event => {
|
|
if (text_area.is(":visible")) {
|
|
template.find(".toggle-metadata").text("show");
|
|
}
|
|
else {
|
|
template.find(".toggle-metadata").text("hide");
|
|
}
|
|
text_area.slideToggle({ duration: 250 });
|
|
});
|
|
text_area.hide();
|
|
return template;
|
|
},
|
|
footer: undefined,
|
|
width: 750
|
|
});
|
|
modal.open();
|
|
}
|
|
Modals.spawnPlaylistSongInfo = spawnPlaylistSongInfo;
|
|
function spawnSongAdd(playlist, callback_add) {
|
|
let modal;
|
|
modal = createModal({
|
|
header: _translations.NQh5eGr5 || (_translations.NQh5eGr5 = tr("Add a song")),
|
|
body: () => {
|
|
let template = $("#tmpl_playlist_edit-song_add").renderTag();
|
|
template = $.spawn("div").append(template);
|
|
const url = template.find(".property-url .value");
|
|
const url_loader = template.find(".property-loader .value");
|
|
const button_add = template.find(".container-buttons .button-add");
|
|
const button_cancel = template.find(".container-buttons .button-cancel");
|
|
url.on('change keyup', event => {
|
|
button_add.prop("disabled", url.val().toString().length == 0);
|
|
}).trigger('change');
|
|
button_cancel.on('click', event => modal.close());
|
|
button_add.on('click', event => {
|
|
callback_add(url.val(), url_loader.val());
|
|
modal.close();
|
|
});
|
|
return template;
|
|
},
|
|
footer: undefined,
|
|
width: 750
|
|
});
|
|
modal.open();
|
|
}
|
|
Modals.spawnSongAdd = spawnSongAdd;
|
|
function spawnPlaylistEdit(client, playlist) {
|
|
let modal;
|
|
let changed_properties = {};
|
|
let changed_permissions = {};
|
|
let callback_permission_update;
|
|
const update_save = () => {
|
|
const save_button = modal.htmlTag.find(".buttons .button-save");
|
|
save_button.prop("disabled", (Object.keys(changed_properties).length + Object.keys(changed_permissions).length) == 0);
|
|
};
|
|
modal = createModal({
|
|
header: _translations.tmSzNTzy || (_translations.tmSzNTzy = tr("Edit playlist")),
|
|
body: () => {
|
|
let template = $("#tmpl_playlist_edit").renderTag().tabify();
|
|
callback_permission_update = apply_permissions(template, client, playlist, (key, value) => {
|
|
console.log("Change permission %o => %o", key, value);
|
|
changed_permissions[key] = value;
|
|
update_save();
|
|
});
|
|
const callback_song_id = apply_songs(template, client, playlist);
|
|
apply_properties(template, client, playlist, (key, value) => {
|
|
console.log("Change property %o => %o", key, value);
|
|
changed_properties[key] = value;
|
|
update_save();
|
|
}, callback_song_id);
|
|
template.find(".buttons .button-save").on('click', event => {
|
|
if (Object.keys(changed_properties).length != 0) {
|
|
changed_properties["playlist_id"] = playlist.playlist_id;
|
|
client.serverConnection.send_command("playlistedit", changed_properties).then(() => {
|
|
changed_properties = {};
|
|
update_save();
|
|
}).catch(error => {
|
|
if (error instanceof CommandResult)
|
|
error = error.extra_message || error.message;
|
|
createErrorModal(_translations.n7VcWm07 || (_translations.n7VcWm07 = tr("Failed to change properties.")), (_translations.a_TZcP0H || (_translations.a_TZcP0H = tr("Failed to change playlist properties.<br>Error: "))) + error).open();
|
|
});
|
|
}
|
|
if (Object.keys(changed_permissions).length != 0) {
|
|
const array = [];
|
|
for (const permission_key of Object.keys(changed_permissions)) {
|
|
array.push({
|
|
permvalue: changed_permissions[permission_key],
|
|
permnegated: false,
|
|
permskip: false,
|
|
permsid: permission_key
|
|
});
|
|
}
|
|
array[0]["playlist_id"] = playlist.playlist_id;
|
|
client.serverConnection.send_command("playlistaddperm", array).then(() => {
|
|
changed_permissions = {};
|
|
update_save();
|
|
}).catch(error => {
|
|
if (error instanceof CommandResult)
|
|
error = error.extra_message || error.message;
|
|
createErrorModal(_translations.NB7sciFG || (_translations.NB7sciFG = tr("Failed to change permission.")), (_translations.mnek9ENK || (_translations.mnek9ENK = tr("Failed to change playlist permissions.<br>Error: "))) + error).open();
|
|
});
|
|
}
|
|
});
|
|
template.find(".buttons .button-close").on('click', event => {
|
|
if ((Object.keys(changed_properties).length + Object.keys(changed_permissions).length) != 0) {
|
|
Modals.spawnYesNo(_translations.m6AIHquf || (_translations.m6AIHquf = tr("Are you sure?")), _translations.jEelVGXf || (_translations.jEelVGXf = tr("Do you really want to discard all your changes?")), result => {
|
|
if (result)
|
|
modal.close();
|
|
});
|
|
return;
|
|
}
|
|
modal.close();
|
|
});
|
|
return template;
|
|
},
|
|
footer: undefined,
|
|
width: 750
|
|
});
|
|
update_save();
|
|
modal.open();
|
|
return modal;
|
|
}
|
|
Modals.spawnPlaylistEdit = spawnPlaylistEdit;
|
|
function apply_songs(tag, client, playlist) {
|
|
const owns_playlist = playlist.playlist_owner_dbid == client.getClient().properties.client_database_id;
|
|
const song_tag = tag.find(".container-songs");
|
|
let replaying_song_id = 0;
|
|
let selected_song;
|
|
const set_song_info = (text) => {
|
|
const tag = song_tag.find(".info-message");
|
|
if (text && text.length > 0) {
|
|
tag.text(text).show();
|
|
}
|
|
else
|
|
tag.hide();
|
|
};
|
|
const set_current_song = (id) => {
|
|
/* this method shall enforce an update */
|
|
replaying_song_id = id;
|
|
update_songs();
|
|
};
|
|
const update_songs = () => {
|
|
set_song_info(_translations.eWqk1aTM || (_translations.eWqk1aTM = tr("loading song list")));
|
|
client.serverConnection.command_helper.request_playlist_songs(playlist.playlist_id).then(result => {
|
|
const entries_tag = song_tag.find(".song-list-entries");
|
|
const entry_template = $("#tmpl_playlist_edit-song_entry");
|
|
entries_tag.empty();
|
|
for (const song of result) {
|
|
const rendered = entry_template.renderTag(song);
|
|
rendered.find(".button-info").on('click', event => {
|
|
spawnPlaylistSongInfo(song);
|
|
});
|
|
const button_delete = rendered.find(".button-delete");
|
|
if (!owns_playlist && !client.permissions.neededPermission(PermissionType.I_PLAYLIST_SONG_REMOVE_POWER).granted(playlist.needed_power_song_remove))
|
|
button_delete.detach();
|
|
else
|
|
button_delete.on('click', event => {
|
|
client.serverConnection.send_command("playlistsongremove", {
|
|
playlist_id: playlist.playlist_id,
|
|
song_id: song.song_id
|
|
}).then(() => {
|
|
rendered.slideToggle({ duration: 250, done(animation, jumpedToEnd) {
|
|
rendered.detach();
|
|
} });
|
|
rendered.hide(250);
|
|
}).catch(error => {
|
|
if (error instanceof CommandResult)
|
|
error = error.extra_message || error.message;
|
|
createErrorModal(_translations.zynyuRv_ || (_translations.zynyuRv_ = tr("Failed to remove song.")), (_translations.EaOaEwhp || (_translations.EaOaEwhp = tr("Failed to remove song/url from the playlist.<br>Error: "))) + error).open();
|
|
});
|
|
});
|
|
if (song.song_id == replaying_song_id)
|
|
rendered.addClass("playing");
|
|
rendered.on('click', event => {
|
|
selected_song = song;
|
|
entries_tag.find(".selected").removeClass("selected");
|
|
rendered.addClass("selected");
|
|
});
|
|
entries_tag.append(rendered);
|
|
}
|
|
const entry_container = song_tag.find(".song-list-entries-container");
|
|
if (entry_container.hasScrollBar())
|
|
entry_container.addClass("scrollbar");
|
|
set_song_info("displaying " + result.length + " songs");
|
|
}).catch(error => {
|
|
console.error(error);
|
|
set_song_info(_translations.v6RuZ030 || (_translations.v6RuZ030 = tr("failed to load song list")));
|
|
//TODO improve error handling!
|
|
});
|
|
};
|
|
song_tag.find(".button-refresh").on('click', event => update_songs());
|
|
song_tag.find(".button-song-add").on('click', event => {
|
|
spawnSongAdd(playlist, (url, loader) => {
|
|
//playlist_id invoker previous url
|
|
client.serverConnection.send_command("playlistsongadd", {
|
|
playlist_id: playlist.playlist_id,
|
|
invoker: loader,
|
|
url: url
|
|
}).then(() => {
|
|
update_songs();
|
|
}).catch(error => {
|
|
if (error instanceof CommandResult)
|
|
error = error.extra_message || error.message;
|
|
createErrorModal(_translations.I43FEeaW || (_translations.I43FEeaW = tr("Failed to add song.")), (_translations.KwvQCSiF || (_translations.KwvQCSiF = tr("Failed to add song/url to the playlist.<br>Error: "))) + error).open();
|
|
});
|
|
});
|
|
}).prop("disabled", !owns_playlist && !client.permissions.neededPermission(PermissionType.I_PLAYLIST_SONG_ADD_POWER).granted(playlist.needed_power_song_add));
|
|
/* setTimeout(update_songs, 100); */ /* We dont have to call that here because it will get called over set_current_song when we received the current song id */
|
|
return set_current_song;
|
|
}
|
|
function apply_permissions(tag, client, playlist, change_permission) {
|
|
const owns_playlist = playlist.playlist_owner_dbid == client.getClient().properties.client_database_id;
|
|
const permission_tag = tag.find(".container-permissions");
|
|
const nopermission_tag = tag.find(".container-no-permissions");
|
|
const update_permissions = () => {
|
|
if (!client.permissions.neededPermission(PermissionType.B_VIRTUALSERVER_PLAYLIST_PERMISSION_LIST).granted(1)) {
|
|
nopermission_tag.show();
|
|
permission_tag.hide();
|
|
}
|
|
else {
|
|
nopermission_tag.hide();
|
|
permission_tag.show();
|
|
permission_tag.find(".permission input").prop("disabled", true);
|
|
client.permissions.requestPlaylistPermissions(playlist.playlist_id).then(permissions => {
|
|
permission_tag.find(".permission input")
|
|
.val(0)
|
|
.prop("disabled", !owns_playlist && !client.permissions.neededPermission(PermissionType.I_PLAYLIST_PERMISSION_MODIFY_POWER).granted(playlist.needed_power_permission_modify));
|
|
for (const permission of permissions) {
|
|
const tag = permission_tag.find(".permission[permission='" + permission.type.name + "']");
|
|
if (permission.value != -2)
|
|
tag.find("input").val(permission.value);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
permission_tag.find(".permission").each((index, _element) => {
|
|
const element = $(_element);
|
|
element.find("input").on('change', event => {
|
|
console.log(element.find("input").val());
|
|
change_permission(element.attr("permission"), parseInt(element.find("input").val().toString()));
|
|
});
|
|
});
|
|
update_permissions();
|
|
return update_permissions;
|
|
}
|
|
function apply_properties(tag, client, playlist, change_property, callback_current_song) {
|
|
const owns_playlist = playlist.playlist_owner_dbid == client.getClient().properties.client_database_id;
|
|
client.serverConnection.command_helper.request_playlist_info(playlist.playlist_id).then(info => {
|
|
tag.find(".property-owner input")
|
|
.val(info.playlist_owner_name + " (" + info.playlist_owner_dbid + ")");
|
|
tag.find(".property-title input")
|
|
.val(info.playlist_title)
|
|
.prop("disabled", !owns_playlist && !client.permissions.neededPermission(PermissionType.I_PLAYLIST_MODIFY_POWER).granted(playlist.needed_power_modify))
|
|
.on('change', event => {
|
|
change_property("playlist_title", event.target.value);
|
|
});
|
|
tag.find(".property-description textarea")
|
|
.val(info.playlist_description)
|
|
.prop("disabled", !owns_playlist && !client.permissions.neededPermission(PermissionType.I_PLAYLIST_MODIFY_POWER).granted(playlist.needed_power_modify))
|
|
.on('change', event => {
|
|
change_property("playlist_description", event.target.value);
|
|
});
|
|
tag.find(".property-type select")
|
|
.val(info.playlist_type.toString())
|
|
.prop("disabled", !owns_playlist && !client.permissions.neededPermission(PermissionType.I_PLAYLIST_MODIFY_POWER).granted(playlist.needed_power_modify))
|
|
.on('change', event => {
|
|
change_property("playlist_description", event.target.selectedIndex.toString());
|
|
});
|
|
tag.find(".property-replay-mode select")
|
|
.val(info.playlist_replay_mode.toString())
|
|
.prop("disabled", !owns_playlist && !client.permissions.neededPermission(PermissionType.I_PLAYLIST_MODIFY_POWER).granted(playlist.needed_power_modify))
|
|
.on('change', event => {
|
|
change_property("playlist_replay_mode", event.target.selectedIndex.toString());
|
|
});
|
|
tag.find(".property-flag-delete-played input")
|
|
.prop("checked", info.playlist_flag_delete_played)
|
|
.prop("disabled", !owns_playlist && !client.permissions.neededPermission(PermissionType.I_PLAYLIST_MODIFY_POWER).granted(playlist.needed_power_modify))
|
|
.on('change', event => {
|
|
change_property("playlist_flag_delete_played", event.target.checked ? "1" : "0");
|
|
});
|
|
tag.find(".property-current-song input")
|
|
.val(info.playlist_current_song_id);
|
|
callback_current_song(info.playlist_current_song_id);
|
|
tag.find(".property-flag-finished input")
|
|
.prop("checked", info.playlist_flag_finished)
|
|
.prop("disabled", !owns_playlist && !client.permissions.neededPermission(PermissionType.I_PLAYLIST_MODIFY_POWER).granted(playlist.needed_power_modify))
|
|
.on('change', event => {
|
|
change_property("playlist_flag_finished", event.target.checked ? "1" : "0");
|
|
});
|
|
}).catch(error => {
|
|
if (error instanceof CommandResult)
|
|
error = error.extra_message || error.message;
|
|
createErrorModal(_translations.YI9EW4YZ || (_translations.YI9EW4YZ = tr("Failed to query playlist info")), (_translations.LuuiZhoN || (_translations.LuuiZhoN = tr("Failed to query playlist info.<br>Error:"))) + error).open();
|
|
});
|
|
}
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["410ea43c3dc2c1ee49cfbfb643a182f0e9981c36f14cd6a6a6e29f5ca30a135a"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["410ea43c3dc2c1ee49cfbfb643a182f0e9981c36f14cd6a6a6e29f5ca30a135a"] = "410ea43c3dc2c1ee49cfbfb643a182f0e9981c36f14cd6a6a6e29f5ca30a135a";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "nIUCwZBR", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistList.ts (81,21)" }, { name: "tdwJZI2z", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistList.ts (99,44)" }, { name: "CBw6VfB6", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistList.ts (99,79)" }, { name: "g2hAzei0", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistList.ts (120,42)" }, { name: "WrenQWBa", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistList.ts (120,75)" }, { name: "a7w2YrqD", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistList.ts (132,39)" }, { name: "T4u_R_ZA", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistList.ts (132,60)" }, { name: "BDEB3Orm", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistList.ts (135,49)" }, { name: "LYoSicUY", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistList.ts (135,84)" }, { name: "kAx45VX1", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistList.ts (143,50)" }, { name: "euCGSQsE", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPlaylistList.ts (143,83)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../utils/modal.ts" />
|
|
/// <reference path="../../proto.ts" />
|
|
/// <reference path="../../client.ts" />
|
|
var Modals;
|
|
(function (Modals) {
|
|
function spawnPlaylistManage(client) {
|
|
let modal;
|
|
let selected_playlist;
|
|
let available_playlists;
|
|
let highlight_own = settings.global("playlist-list-highlight-own", true);
|
|
const update_selected = () => {
|
|
const buttons = modal.htmlTag.find(".header .buttons");
|
|
buttons.find(".button-playlist-edit").prop("disabled", !selected_playlist);
|
|
buttons.find(".button-playlist-delete").prop("disabled", !selected_playlist || !( /* not owner or permission */client.permissions.neededPermission(PermissionType.I_PLAYLIST_DELETE_POWER).granted(selected_playlist.needed_power_delete) || /* client has permissions */
|
|
client.getClient().properties.client_database_id == selected_playlist.playlist_owner_dbid /* client is playlist owner */));
|
|
buttons.find(".button-playlist-create").prop("disabled", !client.permissions.neededPermission(PermissionType.B_PLAYLIST_CREATE).granted(1));
|
|
if (selected_playlist) {
|
|
buttons.find(".button-playlist-edit").prop("disabled", false);
|
|
}
|
|
};
|
|
const update_list = () => __awaiter(this, void 0, void 0, function* () {
|
|
const info_tag = modal.htmlTag.find(".footer .info a");
|
|
info_tag.text("loading...");
|
|
selected_playlist = undefined;
|
|
update_selected();
|
|
try {
|
|
available_playlists = yield client.serverConnection.command_helper.request_playlist_list();
|
|
}
|
|
catch (error) {
|
|
info_tag.text("failed to query playlist list.");
|
|
//FIXME error handling?
|
|
return;
|
|
}
|
|
const entries_tag = modal.htmlTag.find(".playlist-list-entries");
|
|
const entry_template = $("#tmpl_playlist_list-list_entry");
|
|
entries_tag.empty();
|
|
const owndbid = client.getClient().properties.client_database_id;
|
|
for (const query of available_playlists) {
|
|
const tag = entry_template.renderTag(query).on('click', event => {
|
|
entries_tag.find(".entry.selected").removeClass("selected");
|
|
$(event.target).parent(".entry").addClass("selected");
|
|
selected_playlist = query;
|
|
update_selected();
|
|
});
|
|
if (highlight_own && query.playlist_owner_dbid == owndbid)
|
|
tag.addClass("highlighted");
|
|
entries_tag.append(tag);
|
|
}
|
|
const entry_container = modal.htmlTag.find(".playlist-list-entries-container");
|
|
if (entry_container.hasScrollBar())
|
|
entry_container.addClass("scrollbar");
|
|
info_tag.text("Showing " + available_playlists.length + " entries");
|
|
update_selected();
|
|
});
|
|
modal = createModal({
|
|
header: _translations.nIUCwZBR || (_translations.nIUCwZBR = tr("Manage playlists")),
|
|
body: () => {
|
|
let template = $("#tmpl_playlist_list").renderTag();
|
|
/* first open the modal */
|
|
setTimeout(() => {
|
|
const entry_container = template.find(".playlist-list-entries-container");
|
|
if (entry_container.hasScrollBar())
|
|
entry_container.addClass("scrollbar");
|
|
}, 100);
|
|
template.find(".footer .buttons .button-refresh").on('click', update_list);
|
|
template.find(".button-playlist-create").on('click', event => {
|
|
const single_handler = {
|
|
function: command => {
|
|
const json = command.arguments;
|
|
update_list().then(() => {
|
|
Modals.spawnYesNo(_translations.tdwJZI2z || (_translations.tdwJZI2z = tr("Playlist created successful")), _translations.CBw6VfB6 || (_translations.CBw6VfB6 = tr("The playlist has been successfully created.<br>Should we open the editor?")), result => {
|
|
if (result) {
|
|
for (const playlist of available_playlists) {
|
|
if (playlist.playlist_id == json[0]["playlist_id"]) {
|
|
Modals.spawnPlaylistEdit(client, playlist).close_listener.push(update_list);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
return true;
|
|
},
|
|
command: "notifyplaylistcreated"
|
|
};
|
|
client.serverConnection.command_handler_boss().register_single_handler(single_handler);
|
|
client.serverConnection.send_command("playlistcreate").catch(error => {
|
|
client.serverConnection.command_handler_boss().remove_single_handler(single_handler);
|
|
if (error instanceof CommandResult)
|
|
error = error.extra_message || error.message;
|
|
createErrorModal(_translations.g2hAzei0 || (_translations.g2hAzei0 = tr("Unable to create playlist")), (_translations.WrenQWBa || (_translations.WrenQWBa = tr("Failed to create playlist<br>Message: "))) + error).open();
|
|
});
|
|
});
|
|
template.find(".button-playlist-edit").on('click', event => {
|
|
if (!selected_playlist)
|
|
return;
|
|
Modals.spawnPlaylistEdit(client, selected_playlist).close_listener.push(update_list);
|
|
});
|
|
template.find(".button-playlist-delete").on('click', () => {
|
|
if (!selected_playlist)
|
|
return;
|
|
Modals.spawnYesNo(_translations.a7w2YrqD || (_translations.a7w2YrqD = tr("Are you sure?")), _translations.T4u_R_ZA || (_translations.T4u_R_ZA = tr("Do you really want to delete this playlist?")), result => {
|
|
if (result) {
|
|
client.serverConnection.send_command("playlistdelete", { playlist_id: selected_playlist.playlist_id }).then(() => {
|
|
createInfoModal(_translations.BDEB3Orm || (_translations.BDEB3Orm = tr("Playlist deleted successful")), _translations.LYoSicUY || (_translations.LYoSicUY = tr("This playlist has been deleted successfully."))).open();
|
|
update_list();
|
|
}).catch(error => {
|
|
if (error instanceof CommandResult) {
|
|
/* TODO extra handling here */
|
|
//if(error.id == ErrorID.PLAYLIST_IS_IN_USE) { }
|
|
error = error.extra_message || error.message;
|
|
}
|
|
createErrorModal(_translations.kAx45VX1 || (_translations.kAx45VX1 = tr("Unable to delete playlist")), (_translations.euCGSQsE || (_translations.euCGSQsE = tr("Failed to delete playlist<br>Message: "))) + error).open();
|
|
});
|
|
}
|
|
});
|
|
});
|
|
template.find(".input-search").on('change keyup', () => {
|
|
const text = (template.find(".input-search").val() || "").toLowerCase();
|
|
if (text.length == 0) {
|
|
template.find(".playlist-list-entries .entry").show();
|
|
}
|
|
else {
|
|
template.find(".playlist-list-entries .entry").each((_, e) => {
|
|
const element = $(e);
|
|
if (element.text().toLowerCase().indexOf(text) == -1)
|
|
element.hide();
|
|
else
|
|
element.show();
|
|
});
|
|
}
|
|
});
|
|
template.find(".button-highlight-own").on('change', event => {
|
|
const flag = event.target.checked;
|
|
settings.changeGlobal("playlist-list-highlight-own", flag);
|
|
if (flag) {
|
|
const owndbid = client.getClient().properties.client_database_id;
|
|
template.find(".playlist-list-entries .entry").each((index, _element) => {
|
|
const element = $(_element);
|
|
if (parseInt(element.attr("playlist-owner-dbid")) == owndbid)
|
|
element.addClass("highlighted");
|
|
});
|
|
}
|
|
else {
|
|
template.find(".playlist-list-entries .highlighted").removeClass("highlighted");
|
|
}
|
|
}).prop("checked", highlight_own);
|
|
return template;
|
|
},
|
|
footer: undefined,
|
|
width: 750
|
|
});
|
|
update_list();
|
|
modal.open();
|
|
}
|
|
Modals.spawnPlaylistManage = spawnPlaylistManage;
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["d30dd7a3f50901e5febbc38e30fb6224f5e4ed888c0f4fa7bf99fe2aeb94db13"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["d30dd7a3f50901e5febbc38e30fb6224f5e4ed888c0f4fa7bf99fe2aeb94db13"] = "d30dd7a3f50901e5febbc38e30fb6224f5e4ed888c0f4fa7bf99fe2aeb94db13";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "okdb6XT1", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalPoke.ts (13,21)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../utils/modal.ts" />
|
|
/// <reference path="../../proto.ts" />
|
|
/// <reference path="../../client.ts" />
|
|
var Modals;
|
|
(function (Modals) {
|
|
function spawnPoke(invoker, message) {
|
|
let modal;
|
|
modal = createModal({
|
|
header: _translations.okdb6XT1 || (_translations.okdb6XT1 = tr("You have been poked!")),
|
|
body: () => {
|
|
let template = $("#tmpl_poke_popup").renderTag({
|
|
"invoker": ClientEntry.chatTag(invoker.id, invoker.name, invoker.unique_id, true),
|
|
"message": message
|
|
});
|
|
template = $.spawn("div").append(template);
|
|
template.find(".button-close").on('click', event => modal.close());
|
|
return template;
|
|
},
|
|
footer: undefined,
|
|
width: 750
|
|
});
|
|
modal.open();
|
|
}
|
|
Modals.spawnPoke = spawnPoke;
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["01ff91f95f4ae8eb6f70a7e16b455d57e8626e346ef7af1720c934bccbdb4948"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["01ff91f95f4ae8eb6f70a7e16b455d57e8626e346ef7af1720c934bccbdb4948"] = "01ff91f95f4ae8eb6f70a7e16b455d57e8626e346ef7af1720c934bccbdb4948";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "i0fIl3oL", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQuery.ts (9,21)" }, { name: "VWS3eA1A", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQuery.ts (18,42)" }, { name: "HfLP3u1c", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQuery.ts (18,66)" }, { name: "sUeYqhYy", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQuery.ts (45,42)" }, { name: "_NxrXhp1", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQuery.ts (45,74)" }, { name: "phsdCzyk", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQuery.ts (65,36)" }, { name: "H3PUMR9C", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQuery.ts (65,69)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../utils/modal.ts" />
|
|
/// <reference path="../../proto.ts" />
|
|
/// <reference path="../../client.ts" />
|
|
var Modals;
|
|
(function (Modals) {
|
|
function spawnQueryCreate(callback_created) {
|
|
let modal;
|
|
modal = createModal({
|
|
header: _translations.i0fIl3oL || (_translations.i0fIl3oL = tr("Create a server query login")),
|
|
body: () => {
|
|
let template = $("#tmpl_query_create").renderTag();
|
|
template = $.spawn("div").append(template);
|
|
template.find(".button-close").on('click', event => modal.close());
|
|
template.find(".button-create").on('click', event => {
|
|
const name = template.find(".input-name").val();
|
|
if (name.length < 3 || name.length > 64) {
|
|
createErrorModal(_translations.VWS3eA1A || (_translations.VWS3eA1A = tr("Invalid username")), _translations.HfLP3u1c || (_translations.HfLP3u1c = tr("Please enter a valid name!"))).open();
|
|
return;
|
|
}
|
|
//client_login_password
|
|
const single_handler = {
|
|
function: command => {
|
|
const json = command.arguments[0];
|
|
spawnQueryCreated({
|
|
username: name,
|
|
password: json.client_login_password
|
|
}, true);
|
|
if (callback_created)
|
|
callback_created(name, json.client_login_password);
|
|
return true;
|
|
}
|
|
};
|
|
globalClient.serverConnection.command_handler_boss().register_single_handler(single_handler);
|
|
globalClient.serverConnection.send_command("querycreate", {
|
|
client_login_name: name
|
|
}).catch(error => {
|
|
globalClient.serverConnection.command_handler_boss().remove_single_handler(single_handler);
|
|
if (error instanceof CommandResult)
|
|
error = error.extra_message || error.message;
|
|
createErrorModal(_translations.sUeYqhYy || (_translations.sUeYqhYy = tr("Unable to create account")), (_translations._NxrXhp1 || (_translations._NxrXhp1 = tr("Failed to create account<br>Message: "))) + error).open();
|
|
});
|
|
modal.close();
|
|
//TODO create account
|
|
});
|
|
return template;
|
|
},
|
|
footer: undefined,
|
|
width: 750
|
|
});
|
|
modal.open();
|
|
}
|
|
Modals.spawnQueryCreate = spawnQueryCreate;
|
|
function spawnQueryCreated(credentials, just_created) {
|
|
let modal;
|
|
modal = createModal({
|
|
header: just_created ? _translations.phsdCzyk || (_translations.phsdCzyk = tr("Server query credentials")) : _translations.H3PUMR9C || (_translations.H3PUMR9C = tr("New server query credentials")),
|
|
body: () => {
|
|
let template = $("#tmpl_query_created").renderTag(credentials);
|
|
template = $.spawn("div").append(template);
|
|
template.find(".button-close").on('click', event => modal.close());
|
|
template.find(".query_name").text(credentials.username);
|
|
template.find(".query_password").text(credentials.password);
|
|
template.find(".btn_copy_name").on('click', () => {
|
|
template.find(".query_name").select();
|
|
document.execCommand("copy");
|
|
});
|
|
template.find(".btn_copy_password").on('click', () => {
|
|
template.find(".query_password").select();
|
|
document.execCommand("copy");
|
|
});
|
|
return template;
|
|
},
|
|
footer: undefined,
|
|
width: 750
|
|
});
|
|
modal.open();
|
|
}
|
|
Modals.spawnQueryCreated = spawnQueryCreated;
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["3e1485745c7efc1d480698267e44a5aa2180cb996a613004e480ed3d2aed118a"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["3e1485745c7efc1d480698267e44a5aa2180cb996a613004e480ed3d2aed118a"] = "3e1485745c7efc1d480698267e44a5aa2180cb996a613004e480ed3d2aed118a";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "GmzgCKRw", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (55,21)" }, { name: "ULvkthEJ", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (74,38)" }, { name: "Flid_Dnh", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (74,65)" }, { name: "ZP4DmU5Y", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (82,50)" }, { name: "oPA981GT", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (82,82)" }, { name: "k_mQLmYi", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (84,49)" }, { name: "NCQMkX7N", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (84,85)" }, { name: "u8hcZjr9", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (93,38)" }, { name: "MKf0Oy9V", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (93,71)" }, { name: "fwE3FxKx", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (115,50)" }, { name: "JN32xB1a", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (115,83)" }, { name: "k6O9cTdo", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (123,39)" }, { name: "blDGb16q", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (123,60)" }, { name: "XwJxu075", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (130,50)" }, { name: "Ncf1HghS", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (130,82)" }, { name: "WuT4UVFU", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (132,49)" }, { name: "Wg3DKkcV", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/ui/modal/ModalQueryManage.ts (132,85)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
/// <reference path="../../utils/modal.ts" />
|
|
/// <reference path="../../proto.ts" />
|
|
/// <reference path="../../client.ts" />
|
|
var Modals;
|
|
(function (Modals) {
|
|
function spawnQueryManage(client) {
|
|
let modal;
|
|
let selected_query;
|
|
const update_selected = () => {
|
|
const buttons = modal.htmlTag.find(".header .buttons");
|
|
//TODO gray out if no permissions (Server needs to send that... :D)
|
|
buttons.find(".button-query-delete").prop("disabled", selected_query === undefined);
|
|
buttons.find(".button-query-rename").prop("disabled", selected_query === undefined);
|
|
buttons.find(".button-query-change-password").prop("disabled", selected_query === undefined);
|
|
};
|
|
const update_list = () => {
|
|
const info_tag = modal.htmlTag.find(".footer .info a");
|
|
info_tag.text("loading...");
|
|
client.serverConnection.command_helper.current_virtual_server_id().then(server_id => {
|
|
client.serverConnection.command_helper.request_query_list(server_id).then(result => {
|
|
selected_query = undefined;
|
|
const entries_tag = modal.htmlTag.find(".query-list-entries");
|
|
const entry_template = $("#tmpl_query_manager-list_entry");
|
|
entries_tag.empty();
|
|
for (const query of result.queries || []) {
|
|
entries_tag.append(entry_template.renderTag(query).on('click', event => {
|
|
entries_tag.find(".entry.selected").removeClass("selected");
|
|
$(event.target).parent(".entry").addClass("selected");
|
|
selected_query = query;
|
|
update_selected();
|
|
}));
|
|
}
|
|
const entry_container = modal.htmlTag.find(".query-list-entries-container");
|
|
if (entry_container.hasScrollBar())
|
|
entry_container.addClass("scrollbar");
|
|
if (!result || result.flag_all) {
|
|
info_tag.text("Showing all server queries");
|
|
}
|
|
else {
|
|
info_tag.text("Showing your server queries");
|
|
}
|
|
update_selected();
|
|
});
|
|
});
|
|
//TODO error handling
|
|
};
|
|
modal = createModal({
|
|
header: _translations.GmzgCKRw || (_translations.GmzgCKRw = tr("Manage query accounts")),
|
|
body: () => {
|
|
let template = $("#tmpl_query_manager").renderTag();
|
|
template = $.spawn("div").append(template);
|
|
/* first open the modal */
|
|
setTimeout(() => {
|
|
const entry_container = template.find(".query-list-entries-container");
|
|
if (entry_container.hasScrollBar())
|
|
entry_container.addClass("scrollbar");
|
|
}, 100);
|
|
template.find(".footer .buttons .button-refresh").on('click', update_list);
|
|
template.find(".button-query-create").on('click', () => {
|
|
Modals.spawnQueryCreate((user, pass) => update_list());
|
|
});
|
|
template.find(".button-query-rename").on('click', () => {
|
|
if (!selected_query)
|
|
return;
|
|
createInputModal(_translations.ULvkthEJ || (_translations.ULvkthEJ = tr("Change account name")), _translations.Flid_Dnh || (_translations.Flid_Dnh = tr("Enter the new name for the login:<br>")), text => text.length >= 3, result => {
|
|
if (result) {
|
|
client.serverConnection.send_command("queryrename", {
|
|
client_login_name: selected_query.username,
|
|
client_new_login_name: result
|
|
}).catch(error => {
|
|
if (error instanceof CommandResult)
|
|
error = error.extra_message || error.message;
|
|
createErrorModal(_translations.ZP4DmU5Y || (_translations.ZP4DmU5Y = tr("Unable to rename account")), (_translations.oPA981GT || (_translations.oPA981GT = tr("Failed to rename account<br>Message: "))) + error).open();
|
|
}).then(() => {
|
|
createInfoModal(_translations.k_mQLmYi || (_translations.k_mQLmYi = tr("Account successfully renamed")), _translations.NCQMkX7N || (_translations.NCQMkX7N = tr("The query account has been renamed!"))).open();
|
|
update_list();
|
|
});
|
|
}
|
|
}).open();
|
|
});
|
|
template.find(".button-query-change-password").on('click', () => {
|
|
if (!selected_query)
|
|
return;
|
|
createInputModal(_translations.u8hcZjr9 || (_translations.u8hcZjr9 = tr("Change account's password")), _translations.MKf0Oy9V || (_translations.MKf0Oy9V = tr("Enter a new password (leave blank for auto generation):<br>")), text => true, result => {
|
|
if (result !== false) {
|
|
const single_handler = {
|
|
command: "notifyquerypasswordchanges",
|
|
function: command => {
|
|
Modals.spawnQueryCreated({
|
|
username: command.arguments[0]["client_login_name"],
|
|
password: command.arguments[0]["client_login_password"]
|
|
}, false);
|
|
return true;
|
|
}
|
|
};
|
|
client.serverConnection.command_handler_boss().register_single_handler(single_handler);
|
|
client.serverConnection.send_command("querychangepassword", {
|
|
client_login_name: selected_query.username,
|
|
client_login_password: result
|
|
}).catch(error => {
|
|
client.serverConnection.command_handler_boss().remove_single_handler(single_handler);
|
|
if (error instanceof CommandResult)
|
|
error = error.extra_message || error.message;
|
|
createErrorModal(_translations.fwE3FxKx || (_translations.fwE3FxKx = tr("Unable to change password")), (_translations.JN32xB1a || (_translations.JN32xB1a = tr("Failed to change password<br>Message: "))) + error).open();
|
|
});
|
|
}
|
|
}).open();
|
|
});
|
|
template.find(".button-query-delete").on('click', () => {
|
|
if (!selected_query)
|
|
return;
|
|
Modals.spawnYesNo(_translations.k6O9cTdo || (_translations.k6O9cTdo = tr("Are you sure?")), _translations.blDGb16q || (_translations.blDGb16q = tr("Do you really want to delete this account?")), result => {
|
|
if (result) {
|
|
client.serverConnection.send_command("querydelete", {
|
|
client_login_name: selected_query.username
|
|
}).catch(error => {
|
|
if (error instanceof CommandResult)
|
|
error = error.extra_message || error.message;
|
|
createErrorModal(_translations.XwJxu075 || (_translations.XwJxu075 = tr("Unable to delete account")), (_translations.Ncf1HghS || (_translations.Ncf1HghS = tr("Failed to delete account<br>Message: "))) + error).open();
|
|
}).then(() => {
|
|
createInfoModal(_translations.WuT4UVFU || (_translations.WuT4UVFU = tr("Account successfully deleted")), _translations.Wg3DKkcV || (_translations.Wg3DKkcV = tr("The query account has been successfully deleted!"))).open();
|
|
update_list();
|
|
});
|
|
}
|
|
});
|
|
});
|
|
template.find(".input-search").on('change keyup', () => {
|
|
const text = (template.find(".input-search").val() || "").toLowerCase();
|
|
if (text.length == 0) {
|
|
template.find(".query-list-entries .entry").show();
|
|
}
|
|
else {
|
|
template.find(".query-list-entries .entry").each((_, e) => {
|
|
const element = $(e);
|
|
if (element.text().toLowerCase().indexOf(text) == -1)
|
|
element.hide();
|
|
else
|
|
element.show();
|
|
});
|
|
}
|
|
});
|
|
return template;
|
|
},
|
|
footer: undefined,
|
|
width: 750
|
|
});
|
|
update_list();
|
|
modal.open();
|
|
}
|
|
Modals.spawnQueryManage = spawnQueryManage;
|
|
})(Modals || (Modals = {}));
|
|
typeof _translations !== "undefined" || (_translations = {});
|
|
_translations["declared"] = _translations["declared"] || (_translations["declared"] = {});
|
|
_translations["declared_files"] = _translations["declared_files"] || (_translations["declared_files"] = {});
|
|
unique_translation_check: {
|
|
if (_translations["declared_files"]["72abf2a1657d8a2c16b9bc58f4676dd9d92f3a5b082d8bbefa32c7f07d9c8121"] !== undefined) {
|
|
console.warn("This file has already been loaded!\nAre you executing scripts twice?");
|
|
break unique_translation_check;
|
|
}
|
|
else
|
|
_translations["declared_files"]["72abf2a1657d8a2c16b9bc58f4676dd9d92f3a5b082d8bbefa32c7f07d9c8121"] = "72abf2a1657d8a2c16b9bc58f4676dd9d92f3a5b082d8bbefa32c7f07d9c8121";
|
|
/*Auto generated helper for testing if the translation keys are unique*/
|
|
for (var { name: _i, path: _a } of [{ name: "xWglwJfu", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/AudioResampler.ts (7,82)" }, { name: "gYuR48US", path: "/home/wolverindev/TeaSpeak/TeaSpeak/Web-Client/shared/js/voice/AudioResampler.ts (12,26)" }]) {
|
|
if (_translations["declared"][_i] !== undefined)
|
|
throw "Translation with generated name \"" + _i + "\" already exists!\nIt has been already defined here: " + _translations["declared"][_i] + "\nAttempted to redefine here: " + _a + "\nRegenerate and/or fix your program!";
|
|
else
|
|
_translations["declared"][_i] = _a;
|
|
}
|
|
}
|
|
class AudioResampler {
|
|
constructor(targetSampleRate) {
|
|
this.targetSampleRate = targetSampleRate;
|
|
if (this.targetSampleRate < 3000 || this.targetSampleRate > 384000)
|
|
throw _translations.xWglwJfu || (_translations.xWglwJfu = tr("The target sample rate is outside the range [3000, 384000]."));
|
|
}
|
|
resample(buffer) {
|
|
if (!buffer) {
|
|
console.warn(_translations.gYuR48US || (_translations.gYuR48US = tr("Received empty buffer as input! Returning empty output!")));
|
|
return Promise.resolve(buffer);
|
|
}
|
|
//console.log("Encode from %i to %i", buffer.sampleRate, this.targetSampleRate);
|
|
if (buffer.sampleRate == this.targetSampleRate)
|
|
return Promise.resolve(buffer);
|
|
let context;
|
|
context = new (window.webkitOfflineAudioContext || window.OfflineAudioContext)(buffer.numberOfChannels, Math.ceil(buffer.length * this.targetSampleRate / buffer.sampleRate), this.targetSampleRate);
|
|
let source = context.createBufferSource();
|
|
source.buffer = buffer;
|
|
source.start(0);
|
|
source.connect(context.destination);
|
|
if (typeof (this._use_promise) === "undefined") {
|
|
this._use_promise = navigator.browserSpecs.name != 'Safari';
|
|
}
|
|
if (this._use_promise)
|
|
return context.startRendering();
|
|
else {
|
|
return new Promise((resolve, reject) => {
|
|
context.oncomplete = event => resolve(event.renderedBuffer);
|
|
try {
|
|
context.startRendering();
|
|
}
|
|
catch (ex) {
|
|
reject(ex);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
//# sourceMappingURL=shared.js.map
|
|
//# sourceMappingURL=client.js.map
|