diff --git a/github b/github index 171e88f..6d45c4c 160000 --- a/github +++ b/github @@ -1 +1 @@ -Subproject commit 171e88fa1f9e4ea67522c1f6bc07b5ca3c8f4b49 +Subproject commit 6d45c4c883f9b2a53fe1bfeb23fe559b62a61cac diff --git a/jenkins/create_build.sh b/jenkins/create_build.sh index ed576d8..85386ad 100755 --- a/jenkins/create_build.sh +++ b/jenkins/create_build.sh @@ -121,6 +121,6 @@ function deploy_client() { #install_npm #compile_scripts -#compile_native -#package_client +compile_native +package_client deploy_client diff --git a/modules/renderer/PersistentLocalStorage.ts b/modules/renderer/PersistentLocalStorage.ts index 7f07d79..96d2ef5 100644 --- a/modules/renderer/PersistentLocalStorage.ts +++ b/modules/renderer/PersistentLocalStorage.ts @@ -8,7 +8,7 @@ const SETTINGS_DIR = path.join(APP_DATA, "settings"); let _local_storage: {[key: string]: any} = {}; let _local_storage_save: {[key: string]: boolean} = {}; export async function initialize() { - await fs.mkdirs(SETTINGS_DIR); + await fs.mkdirp(SETTINGS_DIR); const files = await fs.readdir(SETTINGS_DIR); for(const file of files) { diff --git a/modules/renderer/app_backend.ts b/modules/renderer/app_backend.ts index dcaaa95..a369fd3 100644 --- a/modules/renderer/app_backend.ts +++ b/modules/renderer/app_backend.ts @@ -1,6 +1,9 @@ -window["require_setup"](module); +import {createErrorModal} from "tc-shared/ui/elements/Modal"; import * as electron from "electron"; +import {tr, tra} from "tc-shared/i18n/localize"; +import {server_connections} from "tc-shared/ui/frames/connection_handlers"; +import {handle_connect_request} from "tc-shared/main"; electron.ipcRenderer.on('connect', (event, url) => handle_native_connect_request(url)); diff --git a/modules/renderer/audio/AudioPlayer.ts b/modules/renderer/audio/AudioPlayer.ts index b9d65c3..13023e2 100644 --- a/modules/renderer/audio/AudioPlayer.ts +++ b/modules/renderer/audio/AudioPlayer.ts @@ -1,132 +1,73 @@ -window["require_setup"](module); +import * as native from "tc-native/connection"; -import {audio as naudio} from "teaclient_connection"; - -namespace audio.player { - //FIXME: Native audio initialize handle! - - export interface Device { - device_id: string; - name: string; - } - - interface Navigator { - mozGetUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void; - webkitGetUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void; - } - - let _initialized_callbacks: (() => any)[] = []; - export let _initialized = false; - export let _initializing = false; - export let _audioContext: AudioContext; - export let _processor: ScriptProcessorNode; - export let _output_stream: naudio.playback.OwnedAudioOutputStream; - export let _current_device: naudio.AudioDevice; - - export function initialized() : boolean { - return _initialized; - } - - - export function context() : AudioContext { - if(!_audioContext) throw "Initialize first!"; - return _audioContext; - } - - export function destination() : AudioNode { - if(!_initialized) - throw "Audio player hasn't yet be initialized"; - return _processor || _audioContext.destination; - } - - export function on_ready(cb: () => any) { - if(_initialized) - cb(); - else - _initialized_callbacks.push(cb); - } - - export function initialize() { - if(_initializing) return; - _initializing = true; - - naudio.initialize(() => { - _output_stream = naudio.playback.create_stream(); - _output_stream.set_buffer_max_latency(0.4); - _output_stream.set_buffer_latency(0.02); - - _output_stream.callback_overflow = () => { - console.warn("Main audio overflow"); - _output_stream.clear(); - }; - _output_stream.callback_underflow = () => { - console.warn("Main audio underflow"); - }; - - _audioContext = new AudioContext({ - sampleRate: _output_stream.sample_rate - }); - _processor = _audioContext.createScriptProcessor(1024 * 8, _output_stream.channels, _output_stream.channels); - - _processor.onaudioprocess = function(event) { - const buffer = event.inputBuffer; - //console.log("Received %d channels of %d with a rate of %d", buffer.numberOfChannels, buffer.length, buffer.sampleRate); - const target_buffer = new Float32Array(buffer.numberOfChannels * buffer.length); - - for(let channel = 0; channel < buffer.numberOfChannels; channel++) { - const channel_data = buffer.getChannelData(channel); - target_buffer.set(channel_data, channel * buffer.length); - } - _output_stream.write_data_rated(target_buffer.buffer, false, buffer.sampleRate); - }; - _processor.connect(_audioContext.destination); - - - _initialized = true; - for(const callback of _initialized_callbacks) - callback(); - _initialized_callbacks = []; - }); - return true; - } - - export async function available_devices() : Promise { - return naudio.available_devices().filter(e => e.output_supported || e.output_default); - } - - export async function set_device(device_id?: string) : Promise { - const dev = naudio.available_devices().filter(e => e.device_id == device_id); - if(dev.length == 0) { - console.warn("Missing audio device with is %s", device_id); - throw "invalid device id"; - } - - try { - naudio.playback.set_device(dev[0].device_id); - } catch(error) { - if(error instanceof Error) - throw error.message; - throw error; - } - _current_device = dev[0]; - } - - export function current_device() : Device { - if(_current_device) - return _current_device; - - const dev = naudio.available_devices().filter(e => e.output_default); - if(dev.length > 0) - return dev[0]; - return {device_id: "default", name: "default"} as Device; - } - - export function get_master_volume() : number { - return naudio.playback.get_master_volume(); - } - export function set_master_volume(volume: number) { - naudio.playback.set_master_volume(volume); - } +//FIXME: Native audio initialize handle! +export interface Device { + device_id: string; + name: string; } -Object.assign(window["audio"] || (window["audio"] = {} as any), audio); \ No newline at end of file +let _initialized_callbacks: (() => any)[] = []; +export let _initialized = false; +export let _initializing = false; +export let _current_device: native.audio.AudioDevice; + +export function initialized() : boolean { + return _initialized; +} +export function on_ready(cb: () => any) { + if(_initialized) + cb(); + else + _initialized_callbacks.push(cb); +} + +export function initialize() { + if(_initializing) return; + _initializing = true; + + native.audio.initialize(() => { + _initialized = true; + for(const callback of _initialized_callbacks) + callback(); + _initialized_callbacks = []; + }); + return true; +} + +export async function available_devices() : Promise { + return native.audio.available_devices().filter(e => e.output_supported || e.output_default); +} + +export async function set_device(device_id?: string) : Promise { + const dev = native.audio.available_devices().filter(e => e.device_id == device_id); + if(dev.length == 0) { + console.warn("Missing audio device with is %s", device_id); + throw "invalid device id"; + } + + try { + native.audio.playback.set_device(dev[0].device_id); + } catch(error) { + if(error instanceof Error) + throw error.message; + throw error; + } + _current_device = dev[0]; +} + +export function current_device() : Device { + if(_current_device) + return _current_device; + + const dev = native.audio.available_devices().filter(e => e.output_default); + if(dev.length > 0) + return dev[0]; + return {device_id: "default", name: "default"} as Device; +} + +export function get_master_volume() : number { + return native.audio.playback.get_master_volume(); +} +export function set_master_volume(volume: number) { + native.audio.playback.set_master_volume(volume); +} \ No newline at end of file diff --git a/modules/renderer/audio/AudioRecorder.ts b/modules/renderer/audio/AudioRecorder.ts index ab900e0..40d1e61 100644 --- a/modules/renderer/audio/AudioRecorder.ts +++ b/modules/renderer/audio/AudioRecorder.ts @@ -1,498 +1,498 @@ -window["require_setup"](module); +import { + filter, + AbstractInput, + InputDevice, + InputState, + InputConsumer, + InputConsumerType, InputStartResult, LevelMeter +} from "tc-shared/voice/RecorderBase"; +import {audio} from "tc-native/connection"; +import {tr} from "tc-shared/i18n/localize"; -import {audio as naudio} from "teaclient_connection"; -// -/// +interface NativeDevice extends InputDevice { + device_index: number; + native: any; +} -export namespace _audio.recorder { - import InputDevice = audio.recorder.InputDevice; - import AbstractInput = audio.recorder.AbstractInput; +let _device_cache: NativeDevice[] = undefined; +export function devices() : InputDevice[] { + //TODO: Handle device updates! + if(!audio.initialized()) return []; - interface NativeDevice extends InputDevice { - device_index: number; - native: any; + return _device_cache || (_device_cache = audio.available_devices().filter(e => e.input_supported || e.input_default).map(e => { + return { + unique_id: e.device_id, + channels: 2, /* TODO */ + default_input: e.input_default, + supported: e.input_supported, + name: e.name, + driver: e.driver, + sample_rate: 48000, /* TODO! */ + native: e + } as NativeDevice + })); +} + +export function device_refresh_available() : boolean { return false; } +export function refresh_devices() : Promise { throw "not supported yet!"; } + +export function create_input() : AbstractInput { + return new NativeInput(); +} + +namespace filters { + export abstract class NativeFilter implements filter.Filter { + type: filter.Type; + handle: NativeInput; + enabled: boolean = false; + + protected constructor(handle, type) { this.handle = handle; this.type = type; } + + abstract initialize(); + abstract finalize(); + + + is_enabled(): boolean { return this.enabled; } } - let _device_cache: NativeDevice[] = undefined; - export function devices() : InputDevice[] { - //TODO: Handle device updates! - if(!naudio.initialized()) return []; + export class NThresholdFilter extends NativeFilter implements filter.ThresholdFilter { + private filter: audio.record.ThresholdConsumeFilter; - return _device_cache || (_device_cache = naudio.available_devices().filter(e => e.input_supported || e.input_default).map(e => { - return { - unique_id: e.device_id, - channels: 2, /* TODO */ - default_input: e.input_default, - supported: e.input_supported, - name: e.name, - driver: e.driver, - sample_rate: 48000, /* TODO! */ - native: e - } as NativeDevice - })); - } + private _margin_frames: number = 6; /* 120ms */ + private _threshold: number = 50; + private _callback_level: any; - export function device_refresh_available() : boolean { return false; } - export function refresh_devices() : Promise { throw "not supported yet!"; } + private _attack_smooth = 0; + private _release_smooth = 0; - export function create_input() : AbstractInput { - return new NativeInput(); - } + callback_level: (level: number) => any; - namespace filter { - export abstract class NativeFilter implements audio.recorder.filter.Filter { - type: audio.recorder.filter.Type; - handle: NativeInput; - enabled: boolean = false; + constructor(handle) { + super(handle, filter.Type.THRESHOLD); - protected constructor(handle, type) { this.handle = handle; this.type = type; } + Object.defineProperty(this, 'callback_level', { + get(): any { + return this._callback_level; + }, set(v: any): void { + if(v === this._callback_level) + return; - abstract initialize(); - abstract finalize(); - - - is_enabled(): boolean { return this.enabled; } + this._callback_level = v; + if(this.filter) + this.filter.set_analyze_filter(v); + }, + enumerable: true, + configurable: false, + }) } - export class NThresholdFilter extends NativeFilter implements audio.recorder.filter.ThresholdFilter { - private filter: naudio.record.ThresholdConsumeFilter; + get_margin_frames(): number { + return this.filter ? this.filter.get_margin_frames() : this._margin_frames; + } - private _margin_frames: number = 6; /* 120ms */ - private _threshold: number = 50; - private _callback_level: any; + get_threshold(): number { + return this.filter ? this.filter.get_threshold() : this._threshold; + } - private _attack_smooth = 0; - private _release_smooth = 0; + set_margin_frames(value: number) { + this._margin_frames = value; + if(this.filter) + this.filter.set_margin_frames(value); + } - callback_level: (level: number) => any; + get_attack_smooth(): number { + return this.filter ? this.filter.get_attack_smooth() : this._attack_smooth; + } - constructor(handle) { - super(handle, audio.recorder.filter.Type.THRESHOLD); + get_release_smooth(): number { + return this.filter ? this.filter.get_release_smooth() : this._release_smooth; + } - Object.defineProperty(this, 'callback_level', { - get(): any { - return this._callback_level; - }, set(v: any): void { - if(v === this._callback_level) - return; + set_attack_smooth(value: number) { + this._attack_smooth = value; + if(this.filter) + this.filter.set_attack_smooth(value); + } - this._callback_level = v; - if(this.filter) - this.filter.set_analyze_filter(v); - }, - enumerable: true, - configurable: false, - }) - } + set_release_smooth(value: number) { + this._release_smooth = value; + if(this.filter) + this.filter.set_release_smooth(value); + } - get_margin_frames(): number { - return this.filter ? this.filter.get_margin_frames() : this._margin_frames; - } + set_threshold(value: number): Promise { + if(typeof(value) === "string") + value = parseInt(value); /* yes... this happens */ + this._threshold = value; + if(this.filter) + this.filter.set_threshold(value); + return Promise.resolve(); + } - get_threshold(): number { - return this.filter ? this.filter.get_threshold() : this._threshold; - } - - set_margin_frames(value: number) { - this._margin_frames = value; - if(this.filter) - this.filter.set_margin_frames(value); - } - - get_attack_smooth(): number { - return this.filter ? this.filter.get_attack_smooth() : this._attack_smooth; - } - - get_release_smooth(): number { - return this.filter ? this.filter.get_release_smooth() : this._release_smooth; - } - - set_attack_smooth(value: number) { - this._attack_smooth = value; - if(this.filter) - this.filter.set_attack_smooth(value); - } - - set_release_smooth(value: number) { - this._release_smooth = value; - if(this.filter) - this.filter.set_release_smooth(value); - } - - set_threshold(value: number): Promise { - if(typeof(value) === "string") - value = parseInt(value); /* yes... this happens */ - this._threshold = value; - if(this.filter) - this.filter.set_threshold(value); - return Promise.resolve(); - } - - finalize() { - if(this.filter) { - if(this.handle.consumer) - this.handle.consumer.unregister_filter(this.filter); - this.filter = undefined; - } - } - - initialize() { - if(!this.handle.consumer) - return; - - this.finalize(); - this.filter = this.handle.consumer.create_filter_threshold(this._threshold); - if(this._callback_level) - this.filter.set_analyze_filter(this._callback_level); - this.filter.set_margin_frames(this._margin_frames); - this.filter.set_attack_smooth(this._attack_smooth); - this.filter.set_release_smooth(this._release_smooth); + finalize() { + if(this.filter) { + if(this.handle.consumer) + this.handle.consumer.unregister_filter(this.filter); + this.filter = undefined; } } - export class NStateFilter extends NativeFilter implements audio.recorder.filter.StateFilter { - private filter: naudio.record.StateConsumeFilter; - private active = false; - - constructor(handle) { - super(handle, audio.recorder.filter.Type.STATE); - } - - finalize() { - if(this.filter) { - if(this.handle.consumer) - this.handle.consumer.unregister_filter(this.filter); - this.filter = undefined; - } - } - - initialize() { - if(!this.handle.consumer) - return; - - this.finalize(); - this.filter = this.handle.consumer.create_filter_state(); - this.filter.set_consuming(this.active); - } - - is_active(): boolean { - return this.active; - } - - async set_state(state: boolean): Promise { - if(this.active === state) - return; - this.active = state; - if(this.filter) - this.filter.set_consuming(state); - } - } - - export class NVoiceLevelFilter extends NativeFilter implements audio.recorder.filter.VoiceLevelFilter { - private filter: naudio.record.VADConsumeFilter; - private level = 3; - private _margin_frames = 5; - - constructor(handle) { - super(handle, audio.recorder.filter.Type.VOICE_LEVEL); - } - - finalize() { - if(this.filter) { - if(this.handle.consumer) - this.handle.consumer.unregister_filter(this.filter); - this.filter = undefined; - } - } - - initialize() { - if(!this.handle.consumer) - return; - - this.finalize(); - this.filter = this.handle.consumer.create_filter_vad(this.level); - this.filter.set_margin_frames(this._margin_frames); - } - - get_level(): number { - return this.level; - } - - set_level(value: number) { - if(this.level === value) - return; - - this.level = value; - if(this.filter) { - this.finalize(); - this.initialize(); - } - } - - set_margin_frames(value: number) { - this._margin_frames = value; - if(this.filter) - this.filter.set_margin_frames(value); - } - - get_margin_frames(): number { - return this.filter ? this.filter.get_margin_frames() : this._margin_frames; - } - } - } - - export class NativeInput implements AbstractInput { - private handle: naudio.record.AudioRecorder; - consumer: naudio.record.AudioConsumer; - - private _current_device: audio.recorder.InputDevice; - private _current_state: audio.recorder.InputState = audio.recorder.InputState.PAUSED; - - callback_begin: () => any; - callback_end: () => any; - - private filters: filter.NativeFilter[] = []; - - constructor() { - this.handle = naudio.record.create_recorder(); - - this.consumer = this.handle.create_consumer(); - this.consumer.callback_ended = () => { - if(this._current_state !== audio.recorder.InputState.RECORDING) - return; - - this._current_state = audio.recorder.InputState.DRY; - if(this.callback_end) - this.callback_end(); - }; - this.consumer.callback_started = () => { - if(this._current_state !== audio.recorder.InputState.DRY) - return; - - this._current_state = audio.recorder.InputState.RECORDING; - if(this.callback_begin) - this.callback_begin(); - }; - - this._current_state = audio.recorder.InputState.PAUSED; - } - - /* TODO: some kind of finalize? */ - current_consumer(): audio.recorder.InputConsumer | undefined { - return { - type: audio.recorder.InputConsumerType.NATIVE - }; - } - - async set_consumer(consumer: audio.recorder.InputConsumer): Promise { - if(typeof(consumer) !== "undefined") - throw "we only support native consumers!"; /* TODO: May create a general wrapper? */ - return; - } - - async set_device(_device: audio.recorder.InputDevice | undefined): Promise { - if(_device === this._current_device) + initialize() { + if(!this.handle.consumer) return; - this._current_device = _device; - try { - await new Promise(resolve => this.handle.set_device(this._current_device ? this._current_device.unique_id : undefined, resolve)); - if(this._current_state !== audio.recorder.InputState.PAUSED && this._current_device) - await new Promise((resolve, reject) => { - this.handle.start(flag => { - if(typeof flag === "boolean" && flag) - resolve(); - else - reject(typeof flag === "string" ? flag : "failed to start"); - }); - }); - } catch(error) { - console.warn(tr("Failed to start playback on new input device (%o)"), error); - throw error; + this.finalize(); + this.filter = this.handle.consumer.create_filter_threshold(this._threshold); + if(this._callback_level) + this.filter.set_analyze_filter(this._callback_level); + this.filter.set_margin_frames(this._margin_frames); + this.filter.set_attack_smooth(this._attack_smooth); + this.filter.set_release_smooth(this._release_smooth); + } + } + + export class NStateFilter extends NativeFilter implements filter.StateFilter { + private filter: audio.record.StateConsumeFilter; + private active = false; + + constructor(handle) { + super(handle, filter.Type.STATE); + } + + finalize() { + if(this.filter) { + if(this.handle.consumer) + this.handle.consumer.unregister_filter(this.filter); + this.filter = undefined; } } - current_device(): audio.recorder.InputDevice | undefined { - return this._current_device; + initialize() { + if(!this.handle.consumer) + return; + + this.finalize(); + this.filter = this.handle.consumer.create_filter_state(); + this.filter.set_consuming(this.active); } - current_state(): audio.recorder.InputState { - return this._current_state; + is_active(): boolean { + return this.active; } - disable_filter(type: audio.recorder.filter.Type) { - const filter = this.get_filter(type) as filter.NativeFilter; - if(filter.is_enabled()) - filter.enabled = false; - filter.finalize(); + async set_state(state: boolean): Promise { + if(this.active === state) + return; + this.active = state; + if(this.filter) + this.filter.set_consuming(state); + } + } + + export class NVoiceLevelFilter extends NativeFilter implements filter.VoiceLevelFilter { + private filter: audio.record.VADConsumeFilter; + private level = 3; + private _margin_frames = 5; + + constructor(handle) { + super(handle, filter.Type.VOICE_LEVEL); } - enable_filter(type: audio.recorder.filter.Type) { - const filter = this.get_filter(type) as filter.NativeFilter; - if(!filter.is_enabled()) { - filter.enabled = true; - filter.initialize(); + finalize() { + if(this.filter) { + if(this.handle.consumer) + this.handle.consumer.unregister_filter(this.filter); + this.filter = undefined; } } - clear_filter() { - for(const filter of this.filters) { - filter.enabled = false; - filter.finalize(); + initialize() { + if(!this.handle.consumer) + return; + + this.finalize(); + this.filter = this.handle.consumer.create_filter_vad(this.level); + this.filter.set_margin_frames(this._margin_frames); + } + + get_level(): number { + return this.level; + } + + set_level(value: number) { + if(this.level === value) + return; + + this.level = value; + if(this.filter) { + this.finalize(); + this.initialize(); } } - get_filter(type: audio.recorder.filter.Type): audio.recorder.filter.Filter | undefined { - for(const filter of this.filters) - if(filter.type === type) - return filter; - - let _filter: filter.NativeFilter; - switch (type) { - case audio.recorder.filter.Type.THRESHOLD: - _filter = new filter.NThresholdFilter(this); - break; - case audio.recorder.filter.Type.STATE: - _filter = new filter.NStateFilter(this); - break; - case audio.recorder.filter.Type.VOICE_LEVEL: - _filter = new filter.NVoiceLevelFilter(this); - break; - default: - throw "this filter isn't supported!"; - } - this.filters.push(_filter); - return _filter; + set_margin_frames(value: number) { + this._margin_frames = value; + if(this.filter) + this.filter.set_margin_frames(value); } - supports_filter(type: audio.recorder.filter.Type) : boolean { - switch (type) { - case audio.recorder.filter.Type.THRESHOLD: - case audio.recorder.filter.Type.STATE: - case audio.recorder.filter.Type.VOICE_LEVEL: - return true; - default: - return false; - } + get_margin_frames(): number { + return this.filter ? this.filter.get_margin_frames() : this._margin_frames; } + } +} - async start(): Promise { - try { - await this.stop(); - } catch(error) { - console.warn(tr("Failed to stop old record session before start (%o)"), error); - } +export class NativeInput implements AbstractInput { + private handle: audio.record.AudioRecorder; + consumer: audio.record.AudioConsumer; - this._current_state = audio.recorder.InputState.DRY; - try { - if(this._current_device) - await new Promise((resolve, reject) => { - this.handle.start(flag => { - if(flag) - resolve(); - else - reject("start failed"); - }); - }); - for(const filter of this.filters) - if(filter.is_enabled()) - filter.initialize(); - return audio.recorder.InputStartResult.EOK; - } catch(error) { - this._current_state = audio.recorder.InputState.PAUSED; - throw error; - } - } + private _current_device: InputDevice; + private _current_state: InputState = InputState.PAUSED; - async stop(): Promise { - this.handle.stop(); - for(const filter of this.filters) - filter.finalize(); + callback_begin: () => any; + callback_end: () => any; + + private filters: filters.NativeFilter[] = []; + + constructor() { + this.handle = audio.record.create_recorder(); + + this.consumer = this.handle.create_consumer(); + this.consumer.callback_ended = () => { + if(this._current_state !== InputState.RECORDING) + return; + + this._current_state = InputState.DRY; if(this.callback_end) this.callback_end(); - this._current_state = audio.recorder.InputState.PAUSED; - } + }; + this.consumer.callback_started = () => { + if(this._current_state !== InputState.DRY) + return; - get_volume(): number { - return this.handle.get_volume(); - } + this._current_state = InputState.RECORDING; + if(this.callback_begin) + this.callback_begin(); + }; - set_volume(volume: number) { - this.handle.set_volume(volume); - } + this._current_state = InputState.PAUSED; } - export async function create_levelmeter(device: InputDevice) : Promise { - const meter = new NativeLevelmenter(device as any); - await meter.initialize(); - return meter; + /* TODO: some kind of finalize? */ + current_consumer(): InputConsumer | undefined { + return { + type: InputConsumerType.NATIVE + }; } - class NativeLevelmenter implements audio.recorder.LevelMeter { - readonly _device: NativeDevice; + async set_consumer(consumer: InputConsumer): Promise { + if(typeof(consumer) !== "undefined") + throw "we only support native consumers!"; /* TODO: May create a general wrapper? */ + return; + } - private _callback: (num: number) => any; - private _recorder: naudio.record.AudioRecorder; - private _consumer: naudio.record.AudioConsumer; - private _filter: naudio.record.ThresholdConsumeFilter; + async set_device(_device: InputDevice | undefined): Promise { + if(_device === this._current_device) + return; - constructor(device: NativeDevice) { - this._device = device; - } - - async initialize() { - try { - this._recorder = naudio.record.create_recorder(); - this._consumer = this._recorder.create_consumer(); - - this._filter = this._consumer.create_filter_threshold(.5); - this._filter.set_attack_smooth(.75); - this._filter.set_release_smooth(.75); - - await new Promise(resolve => this._recorder.set_device(this._device ? this._device.unique_id : undefined, resolve)); + this._current_device = _device; + try { + await new Promise(resolve => this.handle.set_device(this._current_device ? this._current_device.unique_id : undefined, resolve)); + if(this._current_state !== InputState.PAUSED && this._current_device) await new Promise((resolve, reject) => { - this._recorder.start(flag => { + this.handle.start(flag => { if(typeof flag === "boolean" && flag) resolve(); else reject(typeof flag === "string" ? flag : "failed to start"); }); }); - } catch(error) { - if(typeof(error) === "string") - throw error; - console.warn(tr("Failed to initialize levelmeter for device %o: %o"), this._device, error); - throw "initialize failed (lookup console)"; - } + } catch(error) { + console.warn(tr("Failed to start playback on new input device (%o)"), error); + throw error; + } + } - /* references this variable, needs a destory() call, else memory leak */ - this._filter.set_analyze_filter(value => { - (this._callback || (() => {}))(value); - }); + current_device(): InputDevice | undefined { + return this._current_device; + } + + current_state(): InputState { + return this._current_state; + } + + disable_filter(type: filter.Type) { + const filter = this.get_filter(type) as filters.NativeFilter; + if(filter.is_enabled()) + filter.enabled = false; + filter.finalize(); + } + + enable_filter(type: filter.Type) { + const filter = this.get_filter(type) as filters.NativeFilter; + if(!filter.is_enabled()) { + filter.enabled = true; + filter.initialize(); + } + } + + clear_filter() { + for(const filter of this.filters) { + filter.enabled = false; + filter.finalize(); + } + } + + get_filter(type: filter.Type): filter.Filter | undefined { + for(const filter of this.filters) + if(filter.type === type) + return filter; + + let _filter: filters.NativeFilter; + switch (type) { + case filter.Type.THRESHOLD: + _filter = new filters.NThresholdFilter(this); + break; + case filter.Type.STATE: + _filter = new filters.NStateFilter(this); + break; + case filter.Type.VOICE_LEVEL: + _filter = new filters.NVoiceLevelFilter(this); + break; + default: + throw "this filter isn't supported!"; + } + this.filters.push(_filter); + return _filter; + } + + supports_filter(type: filter.Type) : boolean { + switch (type) { + case filter.Type.THRESHOLD: + case filter.Type.STATE: + case filter.Type.VOICE_LEVEL: + return true; + default: + return false; + } + } + + async start(): Promise { + try { + await this.stop(); + } catch(error) { + console.warn(tr("Failed to stop old record session before start (%o)"), error); } - destory() { - if(this._filter) { - this._filter.set_analyze_filter(undefined); - this._consumer.unregister_filter(this._filter); - } - if(this._consumer) - this._recorder.delete_consumer(this._consumer); - this._recorder.stop(); - this._recorder.set_device(undefined, () => {}); /* -1 := No device */ - this._recorder = undefined; - this._consumer = undefined; - this._filter = undefined; + this._current_state = InputState.DRY; + try { + if(this._current_device) + await new Promise((resolve, reject) => { + this.handle.start(flag => { + if(flag) + resolve(); + else + reject("start failed"); + }); + }); + for(const filter of this.filters) + if(filter.is_enabled()) + filter.initialize(); + return InputStartResult.EOK; + } catch(error) { + this._current_state = InputState.PAUSED; + throw error; } + } - device(): audio.recorder.InputDevice { - return this._device; - } + async stop(): Promise { + this.handle.stop(); + for(const filter of this.filters) + filter.finalize(); + if(this.callback_end) + this.callback_end(); + this._current_state = InputState.PAUSED; + } - set_observer(callback: (value: number) => any) { - this._callback = callback; - } + get_volume(): number { + return this.handle.get_volume(); + } + + set_volume(volume: number) { + this.handle.set_volume(volume); } } -Object.assign(window["audio"] || (window["audio"] = {} as any), _audio); \ No newline at end of file +export async function create_levelmeter(device: InputDevice) : Promise { + const meter = new NativeLevelmenter(device as any); + await meter.initialize(); + return meter; +} + +class NativeLevelmenter implements LevelMeter { + readonly _device: NativeDevice; + + private _callback: (num: number) => any; + private _recorder: audio.record.AudioRecorder; + private _consumer: audio.record.AudioConsumer; + private _filter: audio.record.ThresholdConsumeFilter; + + constructor(device: NativeDevice) { + this._device = device; + } + + async initialize() { + try { + this._recorder = audio.record.create_recorder(); + this._consumer = this._recorder.create_consumer(); + + this._filter = this._consumer.create_filter_threshold(.5); + this._filter.set_attack_smooth(.75); + this._filter.set_release_smooth(.75); + + await new Promise(resolve => this._recorder.set_device(this._device ? this._device.unique_id : undefined, resolve)); + await new Promise((resolve, reject) => { + this._recorder.start(flag => { + if (typeof flag === "boolean" && flag) + resolve(); + else + reject(typeof flag === "string" ? flag : "failed to start"); + }); + }); + } catch (error) { + if (typeof (error) === "string") + throw error; + console.warn(tr("Failed to initialize levelmeter for device %o: %o"), this._device, error); + throw "initialize failed (lookup console)"; + } + + /* references this variable, needs a destory() call, else memory leak */ + this._filter.set_analyze_filter(value => { + (this._callback || (() => { + }))(value); + }); + } + + destory() { + if (this._filter) { + this._filter.set_analyze_filter(undefined); + this._consumer.unregister_filter(this._filter); + } + if (this._consumer) + this._recorder.delete_consumer(this._consumer); + this._recorder.stop(); + this._recorder.set_device(undefined, () => { + }); /* -1 := No device */ + this._recorder = undefined; + this._consumer = undefined; + this._filter = undefined; + } + + device(): InputDevice { + return this._device; + } + + set_observer(callback: (value: number) => any) { + this._callback = callback; + } +} \ No newline at end of file diff --git a/modules/renderer/audio/sounds.ts b/modules/renderer/audio/sounds.ts index c32a1e1..09d5c20 100644 --- a/modules/renderer/audio/sounds.ts +++ b/modules/renderer/audio/sounds.ts @@ -1,31 +1,24 @@ -window["require_setup"](module); -// -/// - -import {audio as naudio} from "teaclient_connection"; +import {audio as naudio} from "tc-native/connection"; import * as paths from "path"; +import {SoundFile} from "tc-shared/sound/Sounds"; -namespace audio.sounds { - export async function play_sound(file: sound.SoundFile) : Promise { - await new Promise((resolve, reject) => { - let pathname = paths.dirname(decodeURIComponent(location.pathname)); - if(pathname[0] === '/' && pathname[2] === ':') //e.g.: /C:/test... - pathname = pathname.substr(1); - const path = paths.join(pathname, file.path); +export async function play_sound(file: SoundFile) : Promise { + await new Promise((resolve, reject) => { + let pathname = paths.dirname(decodeURIComponent(location.pathname)); + if(pathname[0] === '/' && pathname[2] === ':') //e.g.: /C:/test... + pathname = pathname.substr(1); + const path = paths.join(pathname, file.path); - console.log(path); - naudio.sounds.playback_sound({ - callback: (result, message) => { - if(result == naudio.sounds.PlaybackResult.SUCCEEDED) - resolve(); - else - reject(naudio.sounds.PlaybackResult[result].toLowerCase() + ": " + message); - }, - file: path, - volume: file.volume - }); + console.log(path); + naudio.sounds.playback_sound({ + callback: (result, message) => { + if(result == naudio.sounds.PlaybackResult.SUCCEEDED) + resolve(); + else + reject(naudio.sounds.PlaybackResult[result].toLowerCase() + ": " + message); + }, + file: path, + volume: file.volume }); - } -} - -Object.assign(window["audio"] || (window["audio"] = {} as any), audio); \ No newline at end of file + }); +} \ No newline at end of file diff --git a/modules/renderer/backend-impl/audio/player.ts b/modules/renderer/backend-impl/audio/player.ts new file mode 100644 index 0000000..131dfd5 --- /dev/null +++ b/modules/renderer/backend-impl/audio/player.ts @@ -0,0 +1,16 @@ +import * as handler from "../../audio/AudioPlayer"; + +export const initialize = handler.initialize; +export const initialized = handler.initialized; + +export const context = handler.context; +export const get_master_volume = handler.get_master_volume; +export const set_master_volume = handler.set_master_volume; + +export const on_ready = handler.on_ready; + +export const available_devices = handler.available_devices; +export const set_device = handler.set_device; +export const current_device = handler.current_device; + +export const initializeFromGesture = () => {}; \ No newline at end of file diff --git a/modules/renderer/backend-impl/audio/recorder.ts b/modules/renderer/backend-impl/audio/recorder.ts new file mode 100644 index 0000000..f169447 --- /dev/null +++ b/modules/renderer/backend-impl/audio/recorder.ts @@ -0,0 +1,8 @@ +import * as handler from "../../audio/AudioRecorder"; + +export const devices = handler.devices; +export const device_refresh_available = handler.device_refresh_available; +export const refresh_devices = handler.refresh_devices; + +export const create_input = handler.create_input; +export const create_levelmeter = handler.create_levelmeter; \ No newline at end of file diff --git a/modules/renderer/backend-impl/audio/sounds.ts b/modules/renderer/backend-impl/audio/sounds.ts new file mode 100644 index 0000000..2d8fc0a --- /dev/null +++ b/modules/renderer/backend-impl/audio/sounds.ts @@ -0,0 +1,3 @@ +import * as handler from "../../audio/sounds"; + +export const play_sound = handler.play_sound; \ No newline at end of file diff --git a/modules/renderer/backend-impl/connection.ts b/modules/renderer/backend-impl/connection.ts new file mode 100644 index 0000000..60bad31 --- /dev/null +++ b/modules/renderer/backend-impl/connection.ts @@ -0,0 +1,4 @@ +import * as handler from "../connection/ServerConnection"; + +export const spawn_server_connection = handler.spawn_server_connection; +export const destroy_server_connection = handler.destroy_server_connection; \ No newline at end of file diff --git a/modules/renderer/backend-impl/dns.ts b/modules/renderer/backend-impl/dns.ts new file mode 100644 index 0000000..19cde92 --- /dev/null +++ b/modules/renderer/backend-impl/dns.ts @@ -0,0 +1,4 @@ +import * as handler from "../dns/dns_resolver"; + +export const supported = handler.supported; +export const resolve_address = handler.resolve_address; \ No newline at end of file diff --git a/modules/renderer/backend-impl/ppt.ts b/modules/renderer/backend-impl/ppt.ts new file mode 100644 index 0000000..8bd023c --- /dev/null +++ b/modules/renderer/backend-impl/ppt.ts @@ -0,0 +1,12 @@ +import * as handler from "../ppt"; + +export const initialize = handler.initialize; +export const finalize = handler.finalize; + +export const register_key_listener = handler.register_key_listener; +export const unregister_key_listener = handler.unregister_key_listener; + +export const register_key_hook = handler.register_key_hook; +export const unregister_key_hook = handler.unregister_key_hook; + +export const key_pressed = handler.key_pressed; \ No newline at end of file diff --git a/modules/renderer/connection/FileTransfer.ts b/modules/renderer/connection/FileTransfer.ts index e182ed4..4ef9c9f 100644 --- a/modules/renderer/connection/FileTransfer.ts +++ b/modules/renderer/connection/FileTransfer.ts @@ -1,186 +1,180 @@ -/// - - -window["require_setup"](module); -import * as native from "teaclient_connection"; +import * as native from "tc-native/connection"; import * as path from "path"; +import {DownloadKey, DownloadTransfer, UploadKey, UploadTransfer} from "tc-shared/FileManager"; +import {base64_encode_ab, str2ab8} from "tc-shared/utils/buffers"; -namespace _transfer { - class NativeFileDownload implements transfer.DownloadTransfer { - readonly key: transfer.DownloadKey; - private _handle: native.ft.NativeFileTransfer; - private _buffer: Uint8Array; +class NativeFileDownload implements DownloadTransfer { + readonly key: DownloadKey; + private _handle: native.ft.NativeFileTransfer; + private _buffer: Uint8Array; - private _result: Promise; - private _response: Response; + private _result: Promise; + private _response: Response; - private _result_success: () => any; - private _result_error: (error: any) => any; + private _result_success: () => any; + private _result_error: (error: any) => any; - constructor(key: transfer.DownloadKey) { - this.key = key; - this._buffer = new Uint8Array(key.total_size); - this._handle = native.ft.spawn_connection({ - client_transfer_id: key.client_transfer_id, - server_transfer_id: key.server_transfer_id, + constructor(key: DownloadKey) { + this.key = key; + this._buffer = new Uint8Array(key.total_size); + this._handle = native.ft.spawn_connection({ + client_transfer_id: key.client_transfer_id, + server_transfer_id: key.server_transfer_id, - remote_address: key.peer.hosts[0], - remote_port: key.peer.port, + remote_address: key.peer.hosts[0], + remote_port: key.peer.port, - transfer_key: key.key, + transfer_key: key.key, - object: native.ft.download_transfer_object_from_buffer(this._buffer.buffer) - }); - } - - get_key(): transfer.DownloadKey { - return this.key; - } - - async request_file(): Promise { - if(this._response) - return this._response; - - try { - await (this._result || this._start_transfer()); - } catch(error) { - throw error; - } - - if(this._response) - return this._response; - - const buffer = this._buffer.buffer.slice(this._buffer.byteOffset, this._buffer.byteOffset + Math.min(64, this._buffer.byteLength)); - - /* may another task has been stepped by and already set the response */ - return this._response || (this._response = new Response(this._buffer, { - status: 200, - statusText: "success", - headers: { - "X-media-bytes": base64_encode_ab(buffer) - - } - })); - } - - _start_transfer() : Promise { - return this._result = new Promise((resolve, reject) => { - this._result_error = (error) => { - this._result_error = undefined; - this._result_success = undefined; - reject(error); - }; - this._result_success = () => { - this._result_error = undefined; - this._result_success = undefined; - resolve(); - }; - - this._handle.callback_failed = this._result_error; - this._handle.callback_finished = aborted => { - if(aborted) - this._result_error("aborted"); - else - this._result_success(); - }; - - this._handle.start(); - }); - } + object: native.ft.download_transfer_object_from_buffer(this._buffer.buffer) + }); } - class NativeFileUpload implements transfer.UploadTransfer { - readonly transfer_key: transfer.UploadKey; - private _handle: native.ft.NativeFileTransfer; - - private _result: Promise; - - private _result_success: () => any; - private _result_error: (error: any) => any; - - constructor(key: transfer.UploadKey) { - this.transfer_key = key; - } - - async put_data(data: BlobPart | File) : Promise { - if(this._result) { - await this._result; - return; - } - - let buffer: native.ft.FileTransferSource; - - if(data instanceof File) { - if(data.size != this.transfer_key.total_size) - throw "invalid size"; - - buffer = native.ft.upload_transfer_object_from_file(path.dirname(data.path), data.name); - } else if(typeof(data) === "string") { - if(data.length != this.transfer_key.total_size) - throw "invalid size"; - - buffer = native.ft.upload_transfer_object_from_buffer(str2ab8(data)); - } else { - let buf = data; - if(buf.byteLength != this.transfer_key.total_size) - throw "invalid size"; - - if(ArrayBuffer.isView(buf)) - buf = buf.buffer.slice(buf.byteOffset); - - buffer = native.ft.upload_transfer_object_from_buffer(buf); - } - - this._handle = native.ft.spawn_connection({ - client_transfer_id: this.transfer_key.client_transfer_id, - server_transfer_id: this.transfer_key.server_transfer_id, - - remote_address: this.transfer_key.peer.hosts[0], - remote_port: this.transfer_key.peer.port, - - transfer_key: this.transfer_key.key, - - object: buffer - }); - - await (this._result = new Promise((resolve, reject) => { - this._result_error = (error) => { - this._result_error = undefined; - this._result_success = undefined; - reject(error); - }; - this._result_success = () => { - this._result_error = undefined; - this._result_success = undefined; - resolve(); - }; - - this._handle.callback_failed = this._result_error; - this._handle.callback_finished = aborted => { - if(aborted) - this._result_error("aborted"); - else - this._result_success(); - }; - - this._handle.start(); - })); - } - - get_key(): transfer.UploadKey { - return this.transfer_key; - } + get_key(): DownloadKey { + return this.key; } + async request_file(): Promise { + if(this._response) + return this._response; - export function spawn_download_transfer(key: transfer.DownloadKey) : transfer.DownloadTransfer { - return new NativeFileDownload(key); + try { + await (this._result || this._start_transfer()); + } catch(error) { + throw error; + } + + if(this._response) + return this._response; + + const buffer = this._buffer.buffer.slice(this._buffer.byteOffset, this._buffer.byteOffset + Math.min(64, this._buffer.byteLength)); + + /* may another task has been stepped by and already set the response */ + return this._response || (this._response = new Response(this._buffer, { + status: 200, + statusText: "success", + headers: { + "X-media-bytes": base64_encode_ab(buffer) + + } + })); } + _start_transfer() : Promise { + return this._result = new Promise((resolve, reject) => { + this._result_error = (error) => { + this._result_error = undefined; + this._result_success = undefined; + reject(error); + }; + this._result_success = () => { + this._result_error = undefined; + this._result_success = undefined; + resolve(); + }; - export function spawn_upload_transfer(key: transfer.UploadKey) : transfer.UploadTransfer { - return new NativeFileUpload(key); + this._handle.callback_failed = this._result_error; + this._handle.callback_finished = aborted => { + if(aborted) + this._result_error("aborted"); + else + this._result_success(); + }; + + this._handle.start(); + }); } } -Object.assign(window["transfer"] || (window["transfer"] = {} as any), _transfer); \ No newline at end of file +class NativeFileUpload implements UploadTransfer { + readonly transfer_key: UploadKey; + private _handle: native.ft.NativeFileTransfer; + + private _result: Promise; + + private _result_success: () => any; + private _result_error: (error: any) => any; + + constructor(key: UploadKey) { + this.transfer_key = key; + } + + async put_data(data: BlobPart | File) : Promise { + if(this._result) { + await this._result; + return; + } + + let buffer: native.ft.FileTransferSource; + + if(data instanceof File) { + if(data.size != this.transfer_key.total_size) + throw "invalid size"; + + buffer = native.ft.upload_transfer_object_from_file(path.dirname(data.path), data.name); + } else if(typeof(data) === "string") { + if(data.length != this.transfer_key.total_size) + throw "invalid size"; + + buffer = native.ft.upload_transfer_object_from_buffer(str2ab8(data)); + } else { + let buf = data; + if(buf.byteLength != this.transfer_key.total_size) + throw "invalid size"; + + if(ArrayBuffer.isView(buf)) + buf = buf.buffer.slice(buf.byteOffset); + + buffer = native.ft.upload_transfer_object_from_buffer(buf); + } + + this._handle = native.ft.spawn_connection({ + client_transfer_id: this.transfer_key.client_transfer_id, + server_transfer_id: this.transfer_key.server_transfer_id, + + remote_address: this.transfer_key.peer.hosts[0], + remote_port: this.transfer_key.peer.port, + + transfer_key: this.transfer_key.key, + + object: buffer + }); + + await (this._result = new Promise((resolve, reject) => { + this._result_error = (error) => { + this._result_error = undefined; + this._result_success = undefined; + reject(error); + }; + this._result_success = () => { + this._result_error = undefined; + this._result_success = undefined; + resolve(); + }; + + this._handle.callback_failed = this._result_error; + this._handle.callback_finished = aborted => { + if(aborted) + this._result_error("aborted"); + else + this._result_success(); + }; + + this._handle.start(); + })); + } + + get_key(): UploadKey { + return this.transfer_key; + } +} + + +export function spawn_download_transfer(key: DownloadKey) : DownloadTransfer { + return new NativeFileDownload(key); +} + + +export function spawn_upload_transfer(key: UploadKey) : UploadTransfer { + return new NativeFileUpload(key); +} \ No newline at end of file diff --git a/modules/renderer/connection/ServerConnection.ts b/modules/renderer/connection/ServerConnection.ts index 14025ef..d429942 100644 --- a/modules/renderer/connection/ServerConnection.ts +++ b/modules/renderer/connection/ServerConnection.ts @@ -1,318 +1,318 @@ -/// - -window["require_setup"](module); +import {AbstractCommandHandler, AbstractCommandHandlerBoss} from "tc-shared/connection/AbstractCommandHandler"; import { - destroy_server_connection as _destroy_server_connection, - NativeServerConnection, - ServerType, - spawn_server_connection as _spawn_server_connection -} from "teaclient_connection"; -import {_audio} from "./VoiceConnection"; + AbstractServerConnection, CommandOptionDefaults, CommandOptions, + ConnectionStateListener, + ServerCommand, + voice +} from "tc-shared/connection/ConnectionBase"; +import {CommandResult} from "tc-shared/connection/ServerConnectionDeclaration"; +import {tr} from "tc-shared/i18n/localize"; +import {ConnectionHandler, ConnectionState, DisconnectReason} from "tc-shared/ConnectionHandler"; +import {NativeServerConnection, ServerType, spawn_server_connection as spawn_native_server_connection, destroy_server_connection as destroy_native_server_connection} from "tc-native/connection"; +import {ConnectionCommandHandler} from "tc-shared/connection/CommandHandler"; +import {HandshakeHandler} from "tc-shared/connection/HandshakeHandler"; +import {ServerAddress} from "tc-shared/ui/server"; +import {TeaSpeakHandshakeHandler} from "tc-shared/profiles/identities/TeamSpeakIdentity"; +import AbstractVoiceConnection = voice.AbstractVoiceConnection; +import {VoiceConnection} from "./VoiceConnection"; -export namespace _connection { - export namespace native { - import VoiceConnection = _audio.native.VoiceConnection; +class ErrorCommandHandler extends AbstractCommandHandler { + private _handle: ServerConnection; - class ErrorCommandHandler extends connection.AbstractCommandHandler { - private _handle: ServerConnection; + constructor(handle: ServerConnection) { + super(handle); + this._handle = handle; + } - constructor(handle: ServerConnection) { - super(handle); - this._handle = handle; - } + handle_command(command: ServerCommand): boolean { + if(command.command === "error") { + const return_listener: {[key: string]: (result: CommandResult) => any} = this._handle["_return_listener"]; + const data = command.arguments[0]; - handle_command(command: connection.ServerCommand): boolean { - if(command.command === "error") { - const return_listener: {[key: string]: (result: CommandResult) => any} = this._handle["_return_listener"]; - const data = command.arguments[0]; - - let return_code : string = data["return_code"]; - if(!return_code) { - const listener = return_listener["last_command"] || return_listener["_clientinit"]; - if(typeof(listener) === "function") { - console.warn(tr("Received error without return code. Using last command (%o)"), listener); - listener(new CommandResult(data)); - delete return_listener["last_command"]; - delete return_listener["_clientinit"]; - } else { - console.warn(tr("Received error without return code."), data); - } - return false; - } - - if(return_listener[return_code]) { - return_listener[return_code](new CommandResult(data)); - } else { - console.warn(tr("Error received for no handler! (%o)"), data); - } - return true; - } else if(command.command == "initivexpand") { - if(command.arguments[0]["teaspeak"] == true) { - console.log("Using TeaSpeak identity type"); - this._handle.handshake_handler().startHandshake(); - } - return true; - } else if(command.command == "initivexpand2") { - /* its TeamSpeak or TeaSpeak with experimental 3.1 and not up2date */ - this._handle["_do_teamspeak"] = true; - } else if(command.command == "initserver") { - const return_listener: {[key: string]: (result: CommandResult) => any} = this._handle["_return_listener"]; - - if(typeof(return_listener["_clientinit"]) === "function") { - return_listener["_clientinit"](new CommandResult({id: 0, message: ""})); - delete return_listener["_clientinit"]; - } - - if(this._handle.onconnectionstatechanged) - this._handle.onconnectionstatechanged(ConnectionState.INITIALISING, ConnectionState.CONNECTING); - } else if(command.command == "notifyconnectioninforequest") { - this._handle.send_command("setconnectioninfo", - { - //TODO calculate - connection_ping: 0.0000, - connection_ping_deviation: 0.0, - - connection_packets_sent_speech: 0, - connection_packets_sent_keepalive: 0, - connection_packets_sent_control: 0, - connection_bytes_sent_speech: 0, - connection_bytes_sent_keepalive: 0, - connection_bytes_sent_control: 0, - connection_packets_received_speech: 0, - connection_packets_received_keepalive: 0, - connection_packets_received_control: 0, - connection_bytes_received_speech: 0, - connection_bytes_received_keepalive: 0, - connection_bytes_received_control: 0, - connection_server2client_packetloss_speech: 0.0000, - connection_server2client_packetloss_keepalive: 0.0000, - connection_server2client_packetloss_control: 0.0000, - connection_server2client_packetloss_total: 0.0000, - connection_bandwidth_sent_last_second_speech: 0, - connection_bandwidth_sent_last_second_keepalive: 0, - connection_bandwidth_sent_last_second_control: 0, - connection_bandwidth_sent_last_minute_speech: 0, - connection_bandwidth_sent_last_minute_keepalive: 0, - connection_bandwidth_sent_last_minute_control: 0, - connection_bandwidth_received_last_second_speech: 0, - connection_bandwidth_received_last_second_keepalive: 0, - connection_bandwidth_received_last_second_control: 0, - connection_bandwidth_received_last_minute_speech: 0, - connection_bandwidth_received_last_minute_keepalive: 0, - connection_bandwidth_received_last_minute_control: 0 - } - ); + let return_code : string = data["return_code"]; + if(!return_code) { + const listener = return_listener["last_command"] || return_listener["_clientinit"]; + if(typeof(listener) === "function") { + console.warn(tr("Received error without return code. Using last command (%o)"), listener); + listener(new CommandResult(data)); + delete return_listener["last_command"]; + delete return_listener["_clientinit"]; + } else { + console.warn(tr("Received error without return code."), data); } return false; } - } - export class ServerConnection extends connection.AbstractServerConnection { - private _native_handle: NativeServerConnection; - private _voice_connection: VoiceConnection; - - private _do_teamspeak: boolean; - private _return_listener: {[key: string]: (result: CommandResult) => any} = {}; - - private _command_handler: NativeConnectionCommandBoss; - private _command_error_handler: ErrorCommandHandler; - private _command_handler_default: connection.ConnectionCommandHandler; - - private _remote_address: ServerAddress; - private _handshake_handler: connection.HandshakeHandler; - - private _return_code_index: number = 0; - - onconnectionstatechanged: connection.ConnectionStateListener; - - constructor(props: ConnectionHandler) { - super(props); - - this._command_handler = new NativeConnectionCommandBoss(this); - this._command_error_handler = new ErrorCommandHandler(this); - this._command_handler_default = new connection.ConnectionCommandHandler(this); - - this._command_handler.register_handler(this._command_error_handler); - this._command_handler.register_handler(this._command_handler_default); - - this._native_handle = _spawn_server_connection(); - this._native_handle.callback_disconnect = reason => { - this.client.handleDisconnect(DisconnectReason.CONNECTION_CLOSED, { - reason: reason, - event: event - }); - }; - this._native_handle.callback_command = (command, args, switches) => { - console.log("Received: %o %o %o", command, args, switches); - //FIXME catch error - - this._command_handler.invoke_handle({ - command: command, - arguments: args - }); - }; - this._voice_connection = new VoiceConnection(this, this._native_handle._voice_connection); - - this.command_helper.initialize(); - this._voice_connection.setup(); - } - - native_handle() : NativeServerConnection { - return this._native_handle; - } - - finalize() { - if(this._native_handle) - _destroy_server_connection(this._native_handle); - this._native_handle = undefined; - } - - connect(address: ServerAddress, handshake: connection.HandshakeHandler, timeout?: number): Promise { - this._remote_address = address; - this._handshake_handler = handshake; - this._do_teamspeak = false; - handshake.setConnection(this); - handshake.initialize(); - - return new Promise((resolve, reject) => { - this._native_handle.connect({ - remote_host: address.host, - remote_port: address.port, - - timeout: typeof(timeout) === "number" ? timeout : -1, - - - callback: error => { - if(error != 0) { - /* required to notify the handle, just a promise reject does not work */ - this.client.handleDisconnect(DisconnectReason.CONNECT_FAILURE, error); - reject(this._native_handle.error_message(error)); - return; - } else { - resolve(); - } - - console.log("Remote server type: %o (%s)", this._native_handle.server_type, ServerType[this._native_handle.server_type]); - if(this._native_handle.server_type == ServerType.TEAMSPEAK || this._do_teamspeak) { - console.log("Trying to use TeamSpeak's identity system"); - this.handshake_handler().on_teamspeak(); - } - }, - - identity_key: (handshake.get_identity_handler() as profiles.identities.TeaSpeakHandshakeHandler).identity.private_key, - teamspeak: false - }) - }); - } - - - remote_address(): ServerAddress { - return this._remote_address; - } - - handshake_handler(): connection.HandshakeHandler { - return this._handshake_handler; - } - - connected(): boolean { - return typeof(this._native_handle) !== "undefined" && this._native_handle.connected(); - } - - disconnect(reason?: string): Promise { - console.trace("Disconnect: %s",reason); - return new Promise((resolve, reject) => this._native_handle.disconnect(reason || "", error => { - if(error == 0) - resolve(); - else - reject(this._native_handle.error_message(error)); - })); - } - - support_voice(): boolean { + if(return_listener[return_code]) { + return_listener[return_code](new CommandResult(data)); + } else { + console.warn(tr("Error received for no handler! (%o)"), data); + } return true; - } + } else if(command.command == "initivexpand") { + if(command.arguments[0]["teaspeak"] == true) { + console.log("Using TeaSpeak identity type"); + this._handle.handshake_handler().startHandshake(); + } + return true; + } else if(command.command == "initivexpand2") { + /* its TeamSpeak or TeaSpeak with experimental 3.1 and not up2date */ + this._handle["_do_teamspeak"] = true; + } else if(command.command == "initserver") { + const return_listener: {[key: string]: (result: CommandResult) => any} = this._handle["_return_listener"]; - voice_connection(): connection.voice.AbstractVoiceConnection { - return this._voice_connection; - } - - command_handler_boss(): connection.AbstractCommandHandlerBoss { - return this._command_handler; - } - - private generate_return_code() : string { - return (this._return_code_index++).toString(); - } - - send_command(command: string, data?: any, _options?: connection.CommandOptions): Promise { - if(!this.connected()) { - console.warn(tr("Tried to send a command without a valid connection.")); - return Promise.reject(tr("not connected")); + if(typeof(return_listener["_clientinit"]) === "function") { + return_listener["_clientinit"](new CommandResult({id: 0, message: ""})); + delete return_listener["_clientinit"]; } - const options: connection.CommandOptions = {}; - Object.assign(options, connection.CommandOptionDefaults); - Object.assign(options, _options); + if(this._handle.onconnectionstatechanged) + this._handle.onconnectionstatechanged(ConnectionState.INITIALISING, ConnectionState.CONNECTING); + } else if(command.command == "notifyconnectioninforequest") { + this._handle.send_command("setconnectioninfo", + { + //TODO calculate + connection_ping: 0.0000, + connection_ping_deviation: 0.0, - data = $.isArray(data) ? data : [data || {}]; - if(data.length == 0) /* we require min one arg to append return_code */ - data.push({}); - - let return_code = data[0]["return_code"] !== undefined ? data[0].return_code : this.generate_return_code(); - data[0]["return_code"] = return_code; - - console.log("Sending %s (%o)", command, data); - const promise = new Promise((resolve, reject) => { - const timeout_id = setTimeout(() => { - delete this._return_listener[return_code]; - reject("timeout"); - }, 5000); - - this._return_listener[return_code] = result => { - clearTimeout(timeout_id); - delete this._return_listener[return_code]; - - (result.success ? resolve : reject)(result); - }; - - if(command == "clientinit") - this._return_listener["_clientinit"] = this._return_listener[return_code]; /* fix for TS3 (clientinit does not accept a return code) */ - - try { - this._native_handle.send_command(command, data, options.flagset || []); - } catch(error) { - console.warn(tr("Failed to send command: %o"), error); + connection_packets_sent_speech: 0, + connection_packets_sent_keepalive: 0, + connection_packets_sent_control: 0, + connection_bytes_sent_speech: 0, + connection_bytes_sent_keepalive: 0, + connection_bytes_sent_control: 0, + connection_packets_received_speech: 0, + connection_packets_received_keepalive: 0, + connection_packets_received_control: 0, + connection_bytes_received_speech: 0, + connection_bytes_received_keepalive: 0, + connection_bytes_received_control: 0, + connection_server2client_packetloss_speech: 0.0000, + connection_server2client_packetloss_keepalive: 0.0000, + connection_server2client_packetloss_control: 0.0000, + connection_server2client_packetloss_total: 0.0000, + connection_bandwidth_sent_last_second_speech: 0, + connection_bandwidth_sent_last_second_keepalive: 0, + connection_bandwidth_sent_last_second_control: 0, + connection_bandwidth_sent_last_minute_speech: 0, + connection_bandwidth_sent_last_minute_keepalive: 0, + connection_bandwidth_sent_last_minute_control: 0, + connection_bandwidth_received_last_second_speech: 0, + connection_bandwidth_received_last_second_keepalive: 0, + connection_bandwidth_received_last_second_control: 0, + connection_bandwidth_received_last_minute_speech: 0, + connection_bandwidth_received_last_minute_keepalive: 0, + connection_bandwidth_received_last_minute_control: 0 } - }); - return this._command_handler_default.proxy_command_promise(promise, options); + ); } + return false; + } +} - ping(): { native: number; javascript?: number } { - return { - native: this._native_handle ? (this._native_handle.current_ping() / 1000) : -2 - }; +export class ServerConnection extends AbstractServerConnection { + private _native_handle: NativeServerConnection; + private _voice_connection: VoiceConnection; + + private _do_teamspeak: boolean; + private _return_listener: {[key: string]: (result: CommandResult) => any} = {}; + + private _command_handler: NativeConnectionCommandBoss; + private _command_error_handler: ErrorCommandHandler; + private _command_handler_default: ConnectionCommandHandler; + + private _remote_address: ServerAddress; + private _handshake_handler: HandshakeHandler; + + private _return_code_index: number = 0; + + onconnectionstatechanged: ConnectionStateListener; + + constructor(props: ConnectionHandler) { + super(props); + + this._command_handler = new NativeConnectionCommandBoss(this); + this._command_error_handler = new ErrorCommandHandler(this); + this._command_handler_default = new ConnectionCommandHandler(this); + + this._command_handler.register_handler(this._command_error_handler); + this._command_handler.register_handler(this._command_handler_default); + + this._native_handle = spawn_native_server_connection(); + this._native_handle.callback_disconnect = reason => { + this.client.handleDisconnect(DisconnectReason.CONNECTION_CLOSED, { + reason: reason, + event: event + }); + }; + this._native_handle.callback_command = (command, args, switches) => { + console.log("Received: %o %o %o", command, args, switches); + //FIXME catch error + + this._command_handler.invoke_handle({ + command: command, + arguments: args + }); + }; + this._voice_connection = new VoiceConnection(this, this._native_handle._voice_connection); + + this.command_helper.initialize(); + this._voice_connection.setup(); + } + + native_handle() : NativeServerConnection { + return this._native_handle; + } + + finalize() { + if(this._native_handle) + destroy_native_server_connection(this._native_handle); + this._native_handle = undefined; + } + + connect(address: ServerAddress, handshake: HandshakeHandler, timeout?: number): Promise { + this._remote_address = address; + this._handshake_handler = handshake; + this._do_teamspeak = false; + handshake.setConnection(this); + handshake.initialize(); + + return new Promise((resolve, reject) => { + this._native_handle.connect({ + remote_host: address.host, + remote_port: address.port, + + timeout: typeof(timeout) === "number" ? timeout : -1, + + + callback: error => { + if(error != 0) { + /* required to notify the handle, just a promise reject does not work */ + this.client.handleDisconnect(DisconnectReason.CONNECT_FAILURE, error); + reject(this._native_handle.error_message(error)); + return; + } else { + resolve(); + } + + console.log("Remote server type: %o (%s)", this._native_handle.server_type, ServerType[this._native_handle.server_type]); + if(this._native_handle.server_type == ServerType.TEAMSPEAK || this._do_teamspeak) { + console.log("Trying to use TeamSpeak's identity system"); + this.handshake_handler().on_teamspeak(); + } + }, + + identity_key: (handshake.get_identity_handler() as TeaSpeakHandshakeHandler).identity.private_key, + teamspeak: false + }) + }); + } + + + remote_address(): ServerAddress { + return this._remote_address; + } + + handshake_handler(): HandshakeHandler { + return this._handshake_handler; + } + + connected(): boolean { + return typeof(this._native_handle) !== "undefined" && this._native_handle.connected(); + } + + disconnect(reason?: string): Promise { + console.trace("Disconnect: %s",reason); + return new Promise((resolve, reject) => this._native_handle.disconnect(reason || "", error => { + if(error == 0) + resolve(); + else + reject(this._native_handle.error_message(error)); + })); + } + + support_voice(): boolean { + return true; + } + + voice_connection(): AbstractVoiceConnection { + return this._voice_connection; + } + + command_handler_boss(): AbstractCommandHandlerBoss { + return this._command_handler; + } + + private generate_return_code() : string { + return (this._return_code_index++).toString(); + } + + send_command(command: string, data?: any, _options?: CommandOptions): Promise { + if(!this.connected()) { + console.warn(tr("Tried to send a command without a valid connection.")); + return Promise.reject(tr("not connected")); + } + + const options: CommandOptions = {}; + Object.assign(options, CommandOptionDefaults); + Object.assign(options, _options); + + data = $.isArray(data) ? data : [data || {}]; + if(data.length == 0) /* we require min one arg to append return_code */ + data.push({}); + + let return_code = data[0]["return_code"] !== undefined ? data[0].return_code : this.generate_return_code(); + data[0]["return_code"] = return_code; + + console.log("Sending %s (%o)", command, data); + const promise = new Promise((resolve, reject) => { + const timeout_id = setTimeout(() => { + delete this._return_listener[return_code]; + reject("timeout"); + }, 5000); + + this._return_listener[return_code] = result => { + clearTimeout(timeout_id); + delete this._return_listener[return_code]; + + (result.success ? resolve : reject)(result); + }; + + if(command == "clientinit") + this._return_listener["_clientinit"] = this._return_listener[return_code]; /* fix for TS3 (clientinit does not accept a return code) */ + + try { + this._native_handle.send_command(command, data, options.flagset || []); + } catch(error) { + console.warn(tr("Failed to send command: %o"), error); } - } + }); + return this._command_handler_default.proxy_command_promise(promise, options); } - export class NativeConnectionCommandBoss extends connection.AbstractCommandHandlerBoss { - constructor(connection: connection.AbstractServerConnection) { - super(connection); - } - } - - - /* override the "normal" connection */ - export function spawn_server_connection(handle: ConnectionHandler) : connection.AbstractServerConnection { - console.log("Spawning native connection"); - return new native.ServerConnection(handle); /* will be overridden by the client */ - } - - export function destroy_server_connection(handle: connection.AbstractServerConnection) { - if(!(handle instanceof native.ServerConnection)) - throw "invalid handle"; - //TODO: Here! - console.log("Call to destroy a server connection"); + ping(): { native: number; javascript?: number } { + return { + native: this._native_handle ? (this._native_handle.current_ping() / 1000) : -2 + }; } } -Object.assign(window["connection"] || (window["connection"] = {} as any), _connection); \ No newline at end of file + +export class NativeConnectionCommandBoss extends AbstractCommandHandlerBoss { + constructor(connection: AbstractServerConnection) { + super(connection); + } +} + + +/* override the "normal" connection */ +export function spawn_server_connection(handle: ConnectionHandler) : AbstractServerConnection { + console.log("Spawning native connection"); + return new ServerConnection(handle); /* will be overridden by the client */ +} + +export function destroy_server_connection(handle: AbstractServerConnection) { + if(!(handle instanceof ServerConnection)) + throw "invalid handle"; + //TODO: Here! + console.log("Call to destroy a server connection"); +} \ No newline at end of file diff --git a/modules/renderer/connection/VoiceConnection.ts b/modules/renderer/connection/VoiceConnection.ts index 5586b4a..45f181f 100644 --- a/modules/renderer/connection/VoiceConnection.ts +++ b/modules/renderer/connection/VoiceConnection.ts @@ -1,182 +1,180 @@ -import {_connection} from "./ServerConnection"; -import {_audio as _recorder} from "../audio/AudioRecorder"; +import {voice} from "tc-shared/connection/ConnectionBase"; +import AbstractVoiceConnection = voice.AbstractVoiceConnection; +import {ServerConnection} from "./ServerConnection"; +import {NativeVoiceConnection} from "tc-native/connection"; +import {RecorderProfile} from "tc-shared/voice/RecorderProfile"; +import {tr} from "tc-shared/i18n/localize"; +import {LogCategory} from "tc-shared/log"; +import * as log from "tc-shared/log"; +import VoiceClient = voice.VoiceClient; +import LatencySettings = voice.LatencySettings; +import {NativeInput} from "../audio/AudioRecorder"; -import { - NativeVoiceConnection, - NativeVoiceClient -} from "teaclient_connection"; +export class VoiceConnection extends AbstractVoiceConnection { + readonly connection: ServerConnection; + readonly handle: NativeVoiceConnection; -export namespace _audio { - export namespace native { - import ServerConnection = _connection.native.ServerConnection; + private _audio_source: RecorderProfile; - export class VoiceConnection extends connection.voice.AbstractVoiceConnection { - readonly connection: ServerConnection; - readonly handle: NativeVoiceConnection; + constructor(connection: ServerConnection, voice: NativeVoiceConnection) { + super(connection); + this.connection = connection; + this.handle = voice; + } - private _audio_source: RecorderProfile; + setup() { } - constructor(connection: ServerConnection, voice: NativeVoiceConnection) { - super(connection); - this.connection = connection; - this.handle = voice; - } + async acquire_voice_recorder(recorder: RecorderProfile | undefined, enforce?: boolean) { + if(this._audio_source === recorder && !enforce) + return; - setup() { } + if(this._audio_source) + await this._audio_source.unmount(); - async acquire_voice_recorder(recorder: RecorderProfile | undefined, enforce?: boolean) { - if(this._audio_source === recorder && !enforce) - return; - - if(this._audio_source) - await this._audio_source.unmount(); - - if(recorder) { - if(!(recorder.input instanceof _recorder.recorder.NativeInput)) - throw "Recorder input must be an instance of NativeInput!"; - await recorder.unmount(); - } - - this.handleVoiceEnded(); - this._audio_source = recorder; - - if(recorder) { - recorder.current_handler = this.connection.client; - - recorder.callback_unmount = () => { - this._audio_source = undefined; - this.handle.set_audio_source(undefined); - this.connection.client.update_voice_status(undefined); - }; - - recorder.callback_start = this.on_voice_started.bind(this); - recorder.callback_stop = this.handleVoiceEnded.bind(this); - - recorder.callback_support_change = () => { - this.connection.client.update_voice_status(undefined); - }; - - this.handle.set_audio_source((recorder.input as _recorder.recorder.NativeInput).consumer); - } - this.connection.client.update_voice_status(undefined); - } - - voice_playback_support() : boolean { - return this.connection.connected(); - } - - voice_send_support() : boolean { - return this.connection.connected(); - } - - private current_channel_codec() : number { - const chandler = this.connection.client; - return (chandler.getClient().currentChannel() || {properties: { channel_codec: 4}}).properties.channel_codec; - } - - private handleVoiceEnded() { - const chandler = this.connection.client; - chandler.getClient().speaking = false; - - if(!chandler.connected) - return false; - - if(chandler.client_status.input_muted) - return false; - - console.log(tr("Local voice ended")); - //TODO - } - - private on_voice_started() { - const chandler = this.connection.client; - if(chandler.client_status.input_muted) { - /* evil hack due to the settings :D */ - log.warn(LogCategory.VOICE, tr("Received local voice started event, even thou we're muted! Do not send any voice.")); - if(this.handle) { - this.handle.enable_voice_send(false); - } - return; - } - - log.info(LogCategory.VOICE, tr("Local voice started")); - this.handle.enable_voice_send(true); - - const ch = chandler.getClient(); - if(ch) ch.speaking = true; - } - - connected(): boolean { - return true; /* we cant be disconnected at any time! */ - } - - voice_recorder(): RecorderProfile { - return this._audio_source; - } - - available_clients(): connection.voice.VoiceClient[] { - return this.handle.available_clients().map(e => Object.assign(e, { - support_latency_settings() { return true; }, - reset_latency_settings: function() { - const stream = this.get_stream(); - stream.set_buffer_latency(0.02); - stream.set_buffer_max_latency(0.2); - return this.latency_settings(); - }, - latency_settings: function (settings?: connection.voice.LatencySettings) : connection.voice.LatencySettings { - const stream = this.get_stream(); - if(typeof settings !== "undefined") { - stream.set_buffer_latency(settings.min_buffer / 1000); - stream.set_buffer_max_latency(settings.max_buffer / 100); - } - return { - max_buffer: Math.floor(stream.get_buffer_max_latency() * 1000), - min_buffer: Math.floor(stream.get_buffer_latency() * 1000) - }; - }, - - support_flush() { return true; }, - flush: function () { - const stream = this.get_stream(); - stream.flush_buffer(); - } - })); - } - - find_client(client_id: number) : connection.voice.VoiceClient | undefined { - for(const client of this.available_clients()) - if(client.client_id === client_id) - return client; - return undefined; - } - - unregister_client(client: connection.voice.VoiceClient): Promise { - this.handle.unregister_client(client.client_id); - return Promise.resolve(); - } - - register_client(client_id: number): connection.voice.VoiceClient { - const client = this.handle.register_client(client_id); - const c = this.find_client(client_id); - c.reset_latency_settings(); - return c; - } - - decoding_supported(codec: number): boolean { - return this.handle.decoding_supported(codec); - } - - encoding_supported(codec: number): boolean { - return this.handle.encoding_supported(codec); - } - - get_encoder_codec(): number { - return this.handle.get_encoder_codec(); - } - - set_encoder_codec(codec: number) { - return this.handle.set_encoder_codec(codec); - } + if(recorder) { + if(!(recorder.input instanceof NativeInput)) + throw "Recorder input must be an instance of NativeInput!"; + await recorder.unmount(); } + + this.handleVoiceEnded(); + this._audio_source = recorder; + + if(recorder) { + recorder.current_handler = this.connection.client; + + recorder.callback_unmount = () => { + this._audio_source = undefined; + this.handle.set_audio_source(undefined); + this.connection.client.update_voice_status(undefined); + }; + + recorder.callback_start = this.on_voice_started.bind(this); + recorder.callback_stop = this.handleVoiceEnded.bind(this); + + recorder.callback_support_change = () => { + this.connection.client.update_voice_status(undefined); + }; + + this.handle.set_audio_source((recorder.input as NativeInput).consumer); + } + this.connection.client.update_voice_status(undefined); + } + + voice_playback_support() : boolean { + return this.connection.connected(); + } + + voice_send_support() : boolean { + return this.connection.connected(); + } + + private current_channel_codec() : number { + const chandler = this.connection.client; + return (chandler.getClient().currentChannel() || {properties: { channel_codec: 4}}).properties.channel_codec; + } + + private handleVoiceEnded() { + const chandler = this.connection.client; + chandler.getClient().speaking = false; + + if(!chandler.connected) + return false; + + if(chandler.client_status.input_muted) + return false; + + console.log(tr("Local voice ended")); + //TODO + } + + private on_voice_started() { + const chandler = this.connection.client; + if(chandler.client_status.input_muted) { + /* evil hack due to the settings :D */ + log.warn(LogCategory.VOICE, tr("Received local voice started event, even thou we're muted! Do not send any voice.")); + if(this.handle) { + this.handle.enable_voice_send(false); + } + return; + } + + log.info(LogCategory.VOICE, tr("Local voice started")); + this.handle.enable_voice_send(true); + + const ch = chandler.getClient(); + if(ch) ch.speaking = true; + } + + connected(): boolean { + return true; /* we cant be disconnected at any time! */ + } + + voice_recorder(): RecorderProfile { + return this._audio_source; + } + + available_clients(): VoiceClient[] { + return this.handle.available_clients().map(e => Object.assign(e, { + support_latency_settings() { return true; }, + reset_latency_settings: function() { + const stream = this.get_stream(); + stream.set_buffer_latency(0.02); + stream.set_buffer_max_latency(0.2); + return this.latency_settings(); + }, + latency_settings: function (settings?: LatencySettings) : LatencySettings { + const stream = this.get_stream(); + if(typeof settings !== "undefined") { + stream.set_buffer_latency(settings.min_buffer / 1000); + stream.set_buffer_max_latency(settings.max_buffer / 100); + } + return { + max_buffer: Math.floor(stream.get_buffer_max_latency() * 1000), + min_buffer: Math.floor(stream.get_buffer_latency() * 1000) + }; + }, + + support_flush() { return true; }, + flush: function () { + const stream = this.get_stream(); + stream.flush_buffer(); + } + })); + } + + find_client(client_id: number) : VoiceClient | undefined { + for(const client of this.available_clients()) + if(client.client_id === client_id) + return client; + return undefined; + } + + unregister_client(client: VoiceClient): Promise { + this.handle.unregister_client(client.client_id); + return Promise.resolve(); + } + + register_client(client_id: number): VoiceClient { + const client = this.handle.register_client(client_id); + const c = this.find_client(client_id); + c.reset_latency_settings(); + return c; + } + + decoding_supported(codec: number): boolean { + return this.handle.decoding_supported(codec); + } + + encoding_supported(codec: number): boolean { + return this.handle.encoding_supported(codec); + } + + get_encoder_codec(): number { + return this.handle.get_encoder_codec(); + } + + set_encoder_codec(codec: number) { + return this.handle.set_encoder_codec(codec); } } \ No newline at end of file diff --git a/modules/renderer/context-menu.ts b/modules/renderer/context-menu.ts index e0a4a7c..8c10689 100644 --- a/modules/renderer/context-menu.ts +++ b/modules/renderer/context-menu.ts @@ -1,7 +1,5 @@ import {class_to_image} from "./icon-helper"; - -window["require_setup"](module); - +import * as contextmenu from "tc-shared/ui/elements/ContextMenu"; import * as electron from "electron"; const remote = electron.remote; const {Menu, MenuItem} = remote; @@ -123,6 +121,4 @@ class ElectronContextMenu implements contextmenu.ContextMenuProvider { html_format_enabled() { return false; } } -contextmenu.set_provider(new ElectronContextMenu()); - -export {}; \ No newline at end of file +contextmenu.set_provider(new ElectronContextMenu()); \ No newline at end of file diff --git a/modules/renderer/dns/dns_resolver.ts b/modules/renderer/dns/dns_resolver.ts index 396ccf5..48e4c58 100644 --- a/modules/renderer/dns/dns_resolver.ts +++ b/modules/renderer/dns/dns_resolver.ts @@ -1,34 +1,32 @@ -/// +import {ServerAddress} from "tc-shared/ui/server"; +import * as loader from "tc-loader"; -window["require_setup"](module); -import * as dns_handler from "teaclient_dns"; +import {AddressTarget, ResolveOptions} from "tc-shared/dns"; +import * as dns_handler from "tc-native/dns"; -namespace _dns { - export function supported() { return true; } - export async function resolve_address(address: ServerAddress, _options?: dns.ResolveOptions) : Promise { - /* backwards compatibility */ - if(typeof(address) === "string") { - address = { - host: address, - port: 9987 - } +export function supported() { return true; } +export async function resolve_address(address: ServerAddress, _options?: ResolveOptions) : Promise { + /* backwards compatibility */ + if(typeof(address) === "string") { + address = { + host: address, + port: 9987 } - - return new Promise((resolve, reject) => { - dns_handler.resolve_cr(address.host, address.port, result => { - if(typeof(result) === "string") - reject(result); - else - resolve({ - target_ip: result.host, - target_port: result.port - }); - }); - }) } + + return new Promise((resolve, reject) => { + dns_handler.resolve_cr(address.host, address.port, result => { + if(typeof(result) === "string") + reject(result); + else + resolve({ + target_ip: result.host, + target_port: result.port + }); + }); + }) } -Object.assign(window["dns"] || (window["dns"] = {} as any), _dns); loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, { name: "Native DNS initialized", function: async () => { diff --git a/modules/renderer/icon-helper.ts b/modules/renderer/icon-helper.ts index d18f490..1ba0a85 100644 --- a/modules/renderer/icon-helper.ts +++ b/modules/renderer/icon-helper.ts @@ -33,7 +33,7 @@ export function class_to_image(klass: string) : NativeImage { export async function initialize() { if(!_div) { - _div = $.spawn("div"); + _div = $(document.createElement("div")); _div.css('display', 'none'); _div.appendTo(document.body); } diff --git a/modules/renderer/imports/.copy_imports_shared.d.ts b/modules/renderer/imports/.copy_imports_shared.d.ts deleted file mode 100644 index f0b1fb7..0000000 --- a/modules/renderer/imports/.copy_imports_shared.d.ts +++ /dev/null @@ -1,5426 +0,0 @@ - -/* File: D:\TeaSpeak\web\shared\js\audio\audio.ts */ -declare namespace audio { - export namespace player { - export interface Device { - device_id: string; - driver: string; - name: string; - } - } -} - -/* File: D:\TeaSpeak\web\shared\js\bookmarks.ts */ -declare namespace bookmarks { - export const boorkmak_connect; - export interface ServerProperties { - server_address: string; - server_port: number; - server_password_hash?: string; - server_password?: string; - } - export enum BookmarkType { - ENTRY, - DIRECTORY - } - export interface Bookmark { - type: BookmarkType; - /* readonly */ parent: DirectoryBookmark; - server_properties: ServerProperties; - display_name: string; - unique_id: string; - nickname: string; - default_channel?: number | string; - default_channel_password_hash?: string; - default_channel_password?: string; - connect_profile: string; - last_icon_id?: number; - } - export interface DirectoryBookmark { - type: BookmarkType; - /* readonly */ parent: DirectoryBookmark; - readonly content: (Bookmark | DirectoryBookmark)[]; - unique_id: string; - display_name: string; - } - export function bookmarks(): DirectoryBookmark; - export function bookmarks_flat(): Bookmark[]; - export function find_bookmark(uuid: string): Bookmark | DirectoryBookmark | undefined; - export function parent_bookmark(bookmark: Bookmark): DirectoryBookmark; - export function create_bookmark(display_name: string, directory: DirectoryBookmark, server_properties: ServerProperties, nickname: string): Bookmark; - export function create_bookmark_directory(parent: DirectoryBookmark, name: string): DirectoryBookmark; - //TODO test if the new parent is within the old bookmark - export function change_directory(parent: DirectoryBookmark, bookmark: Bookmark | DirectoryBookmark); - export function save_bookmark(bookmark?: Bookmark | DirectoryBookmark); - export function delete_bookmark(bookmark: Bookmark | DirectoryBookmark); - export function add_current_server(); -} - -/* File: D:\TeaSpeak\web\shared\js\BrowserIPC.ts */ -declare interface Window { - BroadcastChannel: BroadcastChannel; -} -declare namespace bipc { - export interface BroadcastMessage { - timestamp: number; - receiver: string; - sender: string; - type: string; - data: any; - } - export interface ChannelMessage { - channel_id: string; - type: string; - data: any; - } - export interface ProcessQueryResponse { - request_timestamp: number; - request_query_id: string; - device_id: string; - protocol: number; - } - export interface CertificateAcceptCallback { - request_id: string; - } - export interface CertificateAcceptSucceeded { - } - export abstract class BasicIPCHandler { - protected static readonly BROADCAST_UNIQUE_ID; - protected static readonly PROTOCOL_VERSION; - protected _channels: Channel[]; - protected unique_id; - protected constructor(); - setup(); - get_local_address(); - abstract send_message(type: string, data: any, target?: string); - protected handle_message(message: BroadcastMessage); - create_channel(target_id?: string, channel_id?: string); - channels(): Channel[]; - delete_channel(channel: Channel); - private _query_results: { - [key: string]: ProcessQueryResponse[]; - }; - query_processes(timeout?: number): Promise; - private _cert_accept_callbacks: { - [key: string]: (() => any); - }; - register_certificate_accept_callback(callback: () => any): string; - private _cert_accept_succeeded: { - [sender: string]: (() => any); - }; - post_certificate_accpected(id: string, timeout?: number): Promise; - } - export interface Channel { - readonly channel_id: string; - target_id?: string; - message_handler: (remote_id: string, broadcast: boolean, message: ChannelMessage) => any; - send_message(type: string, message: any, target?: string); - } - export class BroadcastChannelIPC extends BasicIPCHandler { - private static readonly CHANNEL_NAME; - private channel: BroadcastChannel; - constructor(); - setup(); - private on_message(event: MessageEvent); - private on_error(event: MessageEvent); - send_message(type: string, data: any, target?: string); - } - export namespace connect { - export type ConnectRequestData = { - address: string; - profile?: string; - username?: string; - password?: { - value: string; - hashed: boolean; - }; - }; - export interface ConnectOffer { - request_id: string; - data: ConnectRequestData; - } - export interface ConnectOfferAnswer { - request_id: string; - accepted: boolean; - } - export interface ConnectExecute { - request_id: string; - } - export interface ConnectExecuted { - request_id: string; - succeeded: boolean; - message?: string; - } - /* The connect process: - * 1. Broadcast an offer - * 2. Wait 50ms for all offer responses or until the first one respond with "ok" - * 3. Select (if possible) on accepted offer and execute the connect - */ - export class ConnectHandler { - private static readonly CHANNEL_NAME; - readonly ipc_handler: BasicIPCHandler; - private ipc_channel: Channel; - public callback_available: (data: ConnectRequestData) => boolean; - public callback_execute: (data: ConnectRequestData) => boolean | string; - private _pending_connect_offers: { - id: string; - data: ConnectRequestData; - timeout: number; - remote_handler: string; - }[]; - private _pending_connects_requests: { - id: string; - data: ConnectRequestData; - timeout: number; - callback_success: () => any; - callback_failed: (message: string) => any; - callback_avail: () => Promise; - remote_handler?: string; - }[]; - constructor(ipc_handler: BasicIPCHandler); - public setup(); - private on_message(sender: string, broadcast: boolean, message: ChannelMessage); - post_connect_request(data: ConnectRequestData, callback_avail: () => Promise): Promise; - } - } - export namespace mproxy { - export interface MethodProxyInvokeData { - method_name: string; - arguments: any[]; - promise_id: string; - } - export interface MethodProxyResultData { - promise_id: string; - result: any; - success: boolean; - } - export interface MethodProxyCallback { - promise: Promise; - promise_id: string; - resolve: (object: any) => any; - reject: (object: any) => any; - } - export type MethodProxyConnectParameters = { - channel_id: string; - client_id: string; - }; - export abstract class MethodProxy { - readonly ipc_handler: BasicIPCHandler; - private _ipc_channel: Channel; - private _ipc_parameters: MethodProxyConnectParameters; - private readonly _local: boolean; - private readonly _slave: boolean; - private _connected: boolean; - private _proxied_methods: { - [key: string]: () => Promise; - }; - private _proxied_callbacks: { - [key: string]: MethodProxyCallback; - }; - protected constructor(ipc_handler: BasicIPCHandler, connect_params?: MethodProxyConnectParameters); - protected setup(); - protected finalize(); - protected register_method(method: (...args: any[]) => Promise | string); - private _handle_message(remote_id: string, boradcast: boolean, message: ChannelMessage); - private _handle_finalize(); - private _handle_remote_callback(remote_id: string); - private _send_result(promise_id: string, success: boolean, message: any); - private _handle_invoke(data: MethodProxyInvokeData); - private _handle_result(data: MethodProxyResultData); - generate_connect_parameters(): MethodProxyConnectParameters; - is_slave(); - is_master(); - protected abstract on_connected(); - protected abstract on_disconnected(); - } - } - export function setup(); - export function get_handler(); - export function get_connect_handler(); - export function supported(); -} - -/* File: D:\TeaSpeak\web\shared\js\connection\CommandHandler.ts */ -declare namespace connection { - export class ServerConnectionCommandBoss extends AbstractCommandHandlerBoss { - constructor(connection: AbstractServerConnection); - } - export class ConnectionCommandHandler extends AbstractCommandHandler { - readonly connection: AbstractServerConnection; - readonly connection_handler: ConnectionHandler; - constructor(connection: AbstractServerConnection); - private loggable_invoker(unique_id, client_id, name): log.server.base.Client | undefined; - proxy_command_promise(promise: Promise, options: connection.CommandOptions); - handle_command(command: ServerCommand): boolean; - set_handler(command: string, handler: any); - unset_handler(command: string, handler?: any); - handleCommandResult(json); - handleCommandServerInit(json); - handleNotifyServerConnectionInfo(json); - handleNotifyConnectionInfo(json); - private createChannelFromJson(json, ignoreOrder?: boolean); - handleCommandChannelList(json); - handleCommandChannelListFinished(json); - handleCommandChannelCreate(json); - handleCommandChannelShow(json); - handleCommandChannelDelete(json); - handleCommandChannelHide(json); - handleCommandClientEnterView(json); - handleCommandClientLeftView(json); - handleNotifyClientMoved(json); - handleNotifyChannelMoved(json); - handleNotifyChannelEdited(json); - handleNotifyTextMessage(json); - notifyClientChatComposing(json); - handleNotifyClientChatClosed(json); - handleNotifyClientUpdated(json); - handleNotifyServerEdited(json); - handleNotifyServerUpdated(json); - handleNotifyMusicPlayerInfo(json); - handleNotifyClientPoke(json); - //TODO server chat message - handleNotifyServerGroupClientAdd(json); - //TODO server chat message - handleNotifyServerGroupClientRemove(json); - //TODO server chat message - handleNotifyClientChannelGroupChanged(json); - handleNotifyChannelSubscribed(json); - handleNotifyChannelUnsubscribed(json); - handleNotifyConversationHistory(json: any[]); - handleNotifyConversationMessageDelete(json: any[]); - handleNotifyMusicStatusUpdate(json: any[]); - handleMusicPlayerSongChange(json: any[]); - handleNotifyPlaylistSongAdd(json: any[]); - handleNotifyPlaylistSongRemove(json: any[]); - handleNotifyPlaylistSongReorder(json: any[]); - handleNotifyPlaylistSongLoaded(json: any[]); - } -} - -/* File: D:\TeaSpeak\web\shared\js\connection\CommandHelper.ts */ -declare namespace connection { - export class CommandHelper extends AbstractCommandHandler { - private _who_am_i: any; - private _awaiters_unique_ids: { - [unique_id: string]: ((resolved: ClientNameInfo) => any)[]; - }; - private _awaiters_unique_dbid: { - [database_id: number]: ((resolved: ClientNameInfo) => any)[]; - }; - constructor(connection); - initialize(); - destroy(); - handle_command(command: connection.ServerCommand): boolean; - joinChannel(channel: ChannelEntry, password?: string): Promise; - sendMessage(message: string, type: ChatType, target?: ChannelEntry | ClientEntry): Promise; - updateClient(key: string, value: string): Promise; - info_from_uid(..._unique_ids: string[]): Promise; - private handle_notifyclientgetnamefromdbid(json: any[]); - info_from_cldbid(..._cldbid: number[]): Promise; - private handle_notifyclientnamefromuid(json: any[]); - request_query_list(server_id?: number): Promise; - request_playlist_list(): Promise; - request_playlist_songs(playlist_id: number): Promise; - request_playlist_client_list(playlist_id: number): Promise; - request_clients_by_server_group(group_id: number): Promise; - request_playlist_info(playlist_id: number): Promise; - /** - * @deprecated - * Its just a workaround for the query management. - * There is no garante that the whoami trick will work forever - */ - current_virtual_server_id(): Promise; - } -} - -/* File: D:\TeaSpeak\web\shared\js\connection\ConnectionBase.ts */ -declare namespace connection { - export interface CommandOptions { - flagset?: string[]; - process_result?: boolean; - timeout?: number /* default: 1000 */; - } - export const CommandOptionDefaults: CommandOptions; - export type ConnectionStateListener = (old_state: ConnectionState, new_state: ConnectionState) => any; - export abstract class AbstractServerConnection { - readonly client: ConnectionHandler; - readonly command_helper: CommandHelper; - protected constructor(client: ConnectionHandler); - /* resolved as soon a connection has been established. This does not means that the authentication had yet been done! */ - abstract connect(address: ServerAddress, handshake: HandshakeHandler, timeout?: number): Promise; - abstract connected(): boolean; - abstract disconnect(reason?: string): Promise; - abstract support_voice(): boolean; - abstract voice_connection(): voice.AbstractVoiceConnection | undefined; - abstract command_handler_boss(): AbstractCommandHandlerBoss; - abstract send_command(command: string, data?: any | any[], options?: CommandOptions): Promise; - // @ts-ignore - abstract get onconnectionstatechanged(): ConnectionStateListener; - // @ts-ignore - abstract set onconnectionstatechanged(listener: ConnectionStateListener); - abstract remote_address(): ServerAddress; - abstract handshake_handler(): HandshakeHandler; - abstract ping(): { - native: number; - javascript?: number; - }; - } - export namespace voice { - export enum PlayerState { - PREBUFFERING, - PLAYING, - BUFFERING, - STOPPING, - STOPPED - } - export type LatencySettings = { - min_buffer: number; /* milliseconds */ - max_buffer: number; /* milliseconds */ - }; - export interface VoiceClient { - client_id: number; - callback_playback: () => any; - callback_stopped: () => any; - callback_state_changed: (new_state: PlayerState) => any; - get_state(): PlayerState; - get_volume(): number; - set_volume(volume: number): void; - abort_replay(); - support_latency_settings(): boolean; - reset_latency_settings(); - latency_settings(settings?: LatencySettings): LatencySettings; - support_flush(): boolean; - flush(); - } - export abstract class AbstractVoiceConnection { - readonly connection: AbstractServerConnection; - protected constructor(connection: AbstractServerConnection); - abstract connected(): boolean; - abstract encoding_supported(codec: number): boolean; - abstract decoding_supported(codec: number): boolean; - abstract register_client(client_id: number): VoiceClient; - abstract available_clients(): VoiceClient[]; - abstract unregister_client(client: VoiceClient): Promise; - abstract voice_recorder(): RecorderProfile; - abstract acquire_voice_recorder(recorder: RecorderProfile | undefined): Promise; - abstract get_encoder_codec(): number; - abstract set_encoder_codec(codec: number); - } - } - export class ServerCommand { - command: string; - arguments: any[]; - } - export abstract class AbstractCommandHandler { - readonly connection: AbstractServerConnection; - handler_boss: AbstractCommandHandlerBoss | undefined; - volatile_handler_boss: boolean; - ignore_consumed: boolean; - protected constructor(connection: AbstractServerConnection); - /** - * @return If the command should be consumed - */ - abstract handle_command(command: ServerCommand): boolean; - } - export interface SingleCommandHandler { - name?: string; - command?: string; - timeout?: number; - /* if the return is true then the command handler will be removed */ - function: (command: ServerCommand) => boolean; - } - export abstract class AbstractCommandHandlerBoss { - readonly connection: AbstractServerConnection; - protected command_handlers: AbstractCommandHandler[]; - /* TODO: Timeout */ - protected single_command_handler: SingleCommandHandler[]; - protected constructor(connection: AbstractServerConnection); - destroy(); - register_handler(handler: AbstractCommandHandler); - unregister_handler(handler: AbstractCommandHandler); - register_single_handler(handler: SingleCommandHandler); - remove_single_handler(handler: SingleCommandHandler); - handlers(): AbstractCommandHandler[]; - invoke_handle(command: ServerCommand): boolean; - } -} - -/* File: D:\TeaSpeak\web\shared\js\connection\HandshakeHandler.ts */ -declare namespace connection { - export interface HandshakeIdentityHandler { - connection: AbstractServerConnection; - start_handshake(); - register_callback(callback: (success: boolean, message?: string) => any); - } - export class HandshakeHandler { - private connection: AbstractServerConnection; - private handshake_handler: HandshakeIdentityHandler; - private failed; - readonly profile: profiles.ConnectionProfile; - readonly parameters: ConnectParameters; - constructor(profile: profiles.ConnectionProfile, parameters: ConnectParameters); - setConnection(con: AbstractServerConnection); - initialize(); - get_identity_handler(): HandshakeIdentityHandler; - startHandshake(); - on_teamspeak(); - private handshake_failed(message: string); - private handshake_finished(version?: string); - } -} - -/* File: D:\TeaSpeak\web\shared\js\connection\ServerConnectionDeclaration.ts */ -declare enum ErrorID { - NOT_IMPLEMENTED = 0x2, - COMMAND_NOT_FOUND = 0x100, - PERMISSION_ERROR = 2568, - EMPTY_RESULT = 0x0501, - PLAYLIST_IS_IN_USE = 0x2103, - FILE_ALREADY_EXISTS = 2050, - CLIENT_INVALID_ID = 0x0200, - CONVERSATION_INVALID_ID = 0x2200, - CONVERSATION_MORE_DATA = 0x2201, - CONVERSATION_IS_PRIVATE = 0x2202 -} -declare class CommandResult { - success: boolean; - id: number; - message: string; - extra_message: string; - json: any; - constructor(json); -} -declare interface ClientNameInfo { - //cluid=tYzKUryn\/\/Y8VBMf8PHUT6B1eiE= name=Exp clname=Exp cldbid=9 - client_unique_id: string; - client_nickname: string; - client_database_id: number; -} -declare interface ClientNameFromUid { - promise: LaterPromise; - keys: string[]; - response: ClientNameInfo[]; -} -declare interface ServerGroupClient { - client_nickname: string; - client_unique_identifier: string; - client_database_id: number; -} -declare interface QueryListEntry { - username: string; - unique_id: string; - bounded_server: number; -} -declare interface QueryList { - flag_own: boolean; - flag_all: boolean; - queries: QueryListEntry[]; -} -declare interface Playlist { - playlist_id: number; - playlist_bot_id: number; - playlist_title: string; - playlist_type: number; - playlist_owner_dbid: number; - playlist_owner_name: string; - needed_power_modify: number; - needed_power_permission_modify: number; - needed_power_delete: number; - needed_power_song_add: number; - needed_power_song_move: number; - needed_power_song_remove: number; -} -declare interface PlaylistInfo { - playlist_id: number; - playlist_title: string; - playlist_description: string; - playlist_type: number; - playlist_owner_dbid: number; - playlist_owner_name: string; - playlist_flag_delete_played: boolean; - playlist_flag_finished: boolean; - playlist_replay_mode: number; - playlist_current_song_id: number; - playlist_max_songs: number; -} -declare interface PlaylistSong { - song_id: number; - song_previous_song_id: number; - song_invoker: string; - song_url: string; - song_url_loader: string; - song_loaded: boolean; - song_metadata: string; -} - -/* File: D:\TeaSpeak\web\shared\js\ConnectionHandler.ts */ -declare enum DisconnectReason { - HANDLER_DESTROYED, - REQUESTED, - DNS_FAILED, - CONNECT_FAILURE, - CONNECTION_CLOSED, - CONNECTION_FATAL_ERROR, - CONNECTION_PING_TIMEOUT, - CLIENT_KICKED, - CLIENT_BANNED, - HANDSHAKE_FAILED, - HANDSHAKE_TEAMSPEAK_REQUIRED, - HANDSHAKE_BANNED, - SERVER_CLOSED, - SERVER_REQUIRES_PASSWORD, - SERVER_HOSTMESSAGE, - IDENTITY_TOO_LOW, - UNKNOWN -} -declare enum ConnectionState { - UNCONNECTED, - CONNECTING, - INITIALISING, - CONNECTED, - DISCONNECTING -} -declare enum ViewReasonId { - VREASON_USER_ACTION = 0, - VREASON_MOVED = 1, - VREASON_SYSTEM = 2, - VREASON_TIMEOUT = 3, - VREASON_CHANNEL_KICK = 4, - VREASON_SERVER_KICK = 5, - VREASON_BAN = 6, - VREASON_SERVER_STOPPED = 7, - VREASON_SERVER_LEFT = 8, - VREASON_CHANNEL_UPDATED = 9, - VREASON_EDITED = 10, - VREASON_SERVER_SHUTDOWN = 11 -} -declare interface VoiceStatus { - input_hardware: boolean; - input_muted: boolean; - output_muted: boolean; - channel_codec_encoding_supported: boolean; - channel_codec_decoding_supported: boolean; - sound_playback_supported: boolean; - sound_record_supported; - away: boolean | string; - channel_subscribe_all: boolean; - queries_visible: boolean; -} -declare interface ConnectParameters { - nickname?: string; - channel?: { - target: string | number; - password?: string; - }; - token?: string; - password?: { - password: string; - hashed: boolean; - }; - auto_reconnect_attempt?: boolean; -} -declare class ConnectionHandler { - channelTree: ChannelTree; - serverConnection: connection.AbstractServerConnection; - fileManager: FileManager; - permissions: PermissionManager; - groups: GroupManager; - side_bar: chat.Frame; - settings: ServerSettings; - sound: sound.SoundManager; - hostbanner: Hostbanner; - tag_connection_handler: JQuery; - private _clientId: number; - private _local_client: LocalClientEntry; - private _reconnect_timer: NodeJS.Timer; - private _reconnect_attempt: boolean; - private _connect_initialize_id: number; - client_status: VoiceStatus; - invoke_resized_on_activate: boolean; - log: log.ServerLog; - constructor(); - tab_set_name(name: string); - setup(); - startConnection(addr: string, profile: profiles.ConnectionProfile, user_action: boolean, parameters: ConnectParameters); - getClient(): LocalClientEntry; - getClientId(); - // @ts-ignore - set clientId(id: number); - // @ts-ignore - get clientId(); - getServerConnection(): connection.AbstractServerConnection; - /** - * LISTENER - */ - onConnected(); - private initialize_server_settings(); - // @ts-ignore - get connected(): boolean; - private generate_ssl_certificate_accept(): JQuery; - private _certificate_modal: Modal; - handleDisconnect(type: DisconnectReason, data?: any); - cancel_reconnect(log_event: boolean); - private on_connection_state_changed(); - private _last_record_error_popup: number; - update_voice_status(targetChannel?: ChannelEntry); - sync_status_with_server(); - set_away_status(state: boolean | string); - resize_elements(); - acquire_recorder(voice_recoder: RecorderProfile, update_control_bar: boolean); - reconnect_properties(profile?: profiles.ConnectionProfile): ConnectParameters; - update_avatar(); - destroy(); -} - -/* File: D:\TeaSpeak\web\shared\js\crypto\asn1.ts */ -declare namespace asn1 { - export class Int10 { - constructor(value?: any); - sub(sub: number); - mulAdd(mul: number, add: number); - simplify(); - } - export class Stream { - private static HEX_DIGITS; - private static reTimeS; - private static reTimeL; - position: number; - data: string | ArrayBuffer; - constructor(data: string | Stream | ArrayBuffer, position: number); - length(): number; - get(position?: number); - hexByte(byte: number); - parseStringISO(start, end); - parseStringUTF(start, end); - parseStringBMP(start, end); - parseTime(start, end, shortYear); - parseInteger(start, end); - isASCII(start: number, end: number); - parseBitString(start, end, maxLength); - parseOctetString(start, end, maxLength); - parseOID(start, end, maxLength); - } - export enum TagClass { - UNIVERSAL = 0x00, - APPLICATION = 0x01, - CONTEXT = 0x02, - PRIVATE = 0x03 - } - export enum TagType { - EOC = 0x00, - BOOLEAN = 0x01, - INTEGER = 0x02, - BIT_STRING = 0x03, - OCTET_STRING = 0x04, - NULL = 0x05, - OBJECT_IDENTIFIER = 0x06, - ObjectDescriptor = 0x07, - EXTERNAL = 0x08, - REAL = 0x09, - ENUMERATED = 0x0A, - EMBEDDED_PDV = 0x0B, - UTF8String = 0x0C, - SEQUENCE = 0x10, - SET = 0x11, - NumericString = 0x12, - PrintableString = 0x13, - TeletextString = 0x14, - VideotexString = 0x15, - IA5String = 0x16, - UTCTime = 0x17, - GeneralizedTime = 0x18, - GraphicString = 0x19, - VisibleString = 0x1A, - GeneralString = 0x1B, - UniversalString = 0x1C, - BMPString = 0x1E - } - export class ASN1Tag { - tagClass: TagClass; - type: TagType; - tagConstructed: boolean; - tagNumber: number; - constructor(stream: Stream); - isUniversal(); - isEOC(); - } - export class ASN1 { - stream: Stream; - header: number; - length: number; - tag: ASN1Tag; - children: ASN1[]; - constructor(stream: Stream, header: number, length: number, tag: ASN1Tag, children: ASN1[]); - content(max_length?: number, type?: TagType); - typeName(): string; - toString(); - toPrettyString(indent); - posStart(); - posContent(); - posEnd(); - static decodeLength(stream: Stream); - static encodeLength(buffer: Uint8Array, offset: number, length: number); - } - export function decode(stream: string | ArrayBuffer); -} - -/* File: D:\TeaSpeak\web\shared\js\crypto\crc32.ts */ -declare class Crc32 { - private static readonly lookup; - private crc: number; - constructor(); - update(data: ArrayBufferLike); - digest(radix: number); -} - -/* File: D:\TeaSpeak\web\shared\js\crypto\hex.ts */ -declare namespace hex { - export function encode(buffer); -} - -/* File: D:\TeaSpeak\web\shared\js\crypto\sha.ts */ -declare function define($); -declare function unescape(string: string): string; -declare class _sha1 { - static arrayBuffer($: ArrayBuffer): ArrayBuffer; -} -declare namespace sha { - export function encode_text(buffer: string): ArrayBuffer; - export function sha1(message: string | ArrayBuffer): PromiseLike; -} - -/* File: D:\TeaSpeak\web\shared\js\dns.ts */ -declare namespace dns { - export interface AddressTarget { - target_ip: string; - target_port?: number; - } - export interface ResolveOptions { - timeout?: number; - allow_cache?: boolean; - max_depth?: number; - allow_srv?: boolean; - allow_cname?: boolean; - allow_any?: boolean; - allow_a?: boolean; - allow_aaaa?: boolean; - } - export const default_options: ResolveOptions; -} - -/* File: D:\TeaSpeak\web\shared\js\events.ts */ -declare namespace events { - export interface EventConvert { - as(): All[T]; - } - export interface Event { - readonly type: T; - } - export class SingletonEvent implements Event<"singletone-instance"> { - static readonly instance; - readonly type; - private constructor(); - } - export class Registry { - private handler: { - [key: string]: ((event) => void)[]; - }; - private connections: { - [key: string]: Registry[]; - }; - private debug_prefix; - enable_debug(prefix: string); - disable_debug(); - on(event: T, handler: (event?: Events[T] & Event & EventConvert) => void); - on(events: (keyof Events)[], handler: (event?: Event & EventConvert) => void); - on(events, handler); - off(handler: (event?: Event) => void); - off(event: T, handler: (event?: Event & EventConvert) => void); - off(event: (keyof Events)[], handler: (event?: Event & EventConvert) => void); - off(handler_or_events, handler?); - connect(event: T, target: Registry); - disconnect(event: T, target: Registry); - disconnect_all(target: Registry); - fire(event_type: T, data?: Events[T]); - destory(); - } - namespace global { } - export namespace channel_tree { - export interface client { - "enter_view": {}; - "left_view": {}; - "property_update": { - properties: string[]; - }; - "music_status_update": { - player_buffered_index: number; - player_replay_index: number; - }; - "music_song_change": { - "song": SongInfo; - }; - /* TODO: Move this out of the music bots interface? */ - "playlist_song_add": { - song: PlaylistSong; - }; - "playlist_song_remove": { - song_id: number; - }; - "playlist_song_reorder": { - song_id: number; - previous_song_id: number; - }; - "playlist_song_loaded": { - song_id: number; - success: boolean; - error_msg?: string; - metadata?: string; - }; - } - } - export namespace sidebar { - export interface music { - "open": {}; - "close": {}; - "bot_change": { - old: MusicClientEntry | undefined; - new: MusicClientEntry | undefined; - }; - "bot_property_update": { - properties: string[]; - }; - "action_play": {}; - "action_pause": {}; - "action_song_set": { - song_id: number; - }; - "action_forward": {}; - "action_rewind": {}; - "action_forward_ms": { - units: number; - }; - "action_rewind_ms": { - units: number; - }; - "action_song_add": {}; - "action_song_delete": { - song_id: number; - }; - "action_playlist_reload": {}; - "playtime_move_begin": {}; - "playtime_move_end": { - canceled: boolean; - target_time?: number; - }; - "reorder_begin": { - song_id: number; - entry: JQuery; - }; - "reorder_end": { - song_id: number; - canceled: boolean; - entry: JQuery; - previous_entry?: number; - }; - "player_time_update": channel_tree.client["music_status_update"]; - "player_song_change": channel_tree.client["music_song_change"]; - "playlist_song_add": channel_tree.client["playlist_song_add"] & { - insert_effect?: boolean; - }; - "playlist_song_remove": channel_tree.client["playlist_song_remove"]; - "playlist_song_reorder": channel_tree.client["playlist_song_reorder"]; - "playlist_song_loaded": channel_tree.client["playlist_song_loaded"] & { - html_entry?: JQuery; - }; - } - } - export namespace modal { - export type BotStatusType = "name" | "description" | "volume" | "country_code" | "channel_commander" | "priority_speaker"; - export type PlaylistStatusType = "replay_mode" | "finished" | "delete_played" | "max_size" | "notify_song_change"; - export interface music_manage { - show_container: { - container: "settings" | "permissions"; - }; - /* setting relevant */ - query_bot_status: {}; - bot_status: { - status: "success" | "error"; - error_msg?: string; - data?: { - name: string; - description: string; - volume: number; - country_code: string; - default_country_code: string; - channel_commander: boolean; - priority_speaker: boolean; - client_version: string; - client_platform: string; - uptime_mode: number; - bot_type: number; - }; - }; - set_bot_status: { - key: BotStatusType; - value: any; - }; - set_bot_status_result: { - key: BotStatusType; - status: "success" | "error" | "timeout"; - error_msg?: string; - value?: any; - }; - query_playlist_status: {}; - playlist_status: { - status: "success" | "error"; - error_msg?: string; - data?: { - replay_mode: number; - finished: boolean; - delete_played: boolean; - max_size: number; - notify_song_change: boolean; - }; - }; - set_playlist_status: { - key: PlaylistStatusType; - value: any; - }; - set_playlist_status_result: { - key: PlaylistStatusType; - status: "success" | "error" | "timeout"; - error_msg?: string; - value?: any; - }; - /* permission relevant */ - show_client_list: {}; - hide_client_list: {}; - filter_client_list: { - filter: string | undefined; - }; - "refresh_permissions": {}; - query_special_clients: {}; - special_client_list: { - status: "success" | "error" | "error-permission"; - error_msg?: string; - clients?: { - name: string; - unique_id: string; - database_id: number; - }[]; - }; - search_client: { - text: string; - }; - search_client_result: { - status: "error" | "timeout" | "empty" | "success"; - error_msg?: string; - client?: { - name: string; - unique_id: string; - database_id: number; - }; - }; - /* sets a client to set the permission for */ - special_client_set: { - client?: { - name: string; - unique_id: string; - database_id: number; - }; - }; - "query_general_permissions": {}; - "general_permissions": { - status: "error" | "timeout" | "success"; - error_msg?: string; - permissions?: { - [key: string]: number; - }; - }; - "set_general_permission_result": { - status: "error" | "success"; - key: string; - value?: number; - error_msg?: string; - }; - "set_general_permission": { - key: string; - value: number; - }; - "query_client_permissions": { - client_database_id: number; - }; - "client_permissions": { - status: "error" | "timeout" | "success"; - client_database_id: number; - error_msg?: string; - permissions?: { - [key: string]: number; - }; - }; - "set_client_permission_result": { - status: "error" | "success"; - client_database_id: number; - key: string; - value?: number; - error_msg?: string; - }; - "set_client_permission": { - client_database_id: number; - key: string; - value: number; - }; - "query_group_permissions": { - permission_name: string; - }; - "group_permissions": { - permission_name: string; - status: "error" | "timeout" | "success"; - groups?: { - name: string; - value: number; - id: number; - }[]; - error_msg?: string; - }; - } - } -} -declare const eclient; -declare const emusic; - -/* File: D:\TeaSpeak\web\shared\js\FileManager.ts */ -declare class FileEntry { - name: string; - datetime: number; - type: number; - size: number; -} -declare class FileListRequest { - path: string; - entries: FileEntry[]; - callback: (entries: FileEntry[]) => void; -} -declare namespace transfer { - export interface TransferKey { - client_transfer_id: number; - server_transfer_id: number; - key: string; - file_path: string; - file_name: string; - peer: { - hosts: string[]; - port: number; - }; - total_size: number; - } - export interface UploadOptions { - name: string; - path: string; - channel?: ChannelEntry; - channel_password?: string; - size: number; - overwrite: boolean; - } - export interface DownloadTransfer { - get_key(): DownloadKey; - request_file(): Promise; - } - export interface UploadTransfer { - get_key(): UploadKey; - put_data(data: BlobPart | File): Promise; - } - export type DownloadKey = TransferKey; - export type UploadKey = TransferKey; - export function spawn_download_transfer(key: DownloadKey): DownloadTransfer; - export function spawn_upload_transfer(key: UploadKey): UploadTransfer; -} -declare class RequestFileDownload implements transfer.DownloadTransfer { - readonly transfer_key: transfer.DownloadKey; - constructor(key: transfer.DownloadKey); - request_file(): Promise; - private try_fetch(url: string): Promise; - get_key(): transfer.DownloadKey; -} -declare class RequestFileUpload implements transfer.UploadTransfer { - readonly transfer_key: transfer.UploadKey; - constructor(key: transfer.DownloadKey); - get_key(): transfer.UploadKey; - put_data(data: BlobPart | File): Promise; - private try_put(data: FormData, url: string): Promise; -} -declare class FileManager extends connection.AbstractCommandHandler { - handle: ConnectionHandler; - icons: IconManager; - avatars: AvatarManager; - private listRequests: FileListRequest[]; - private pending_download_requests: transfer.DownloadKey[]; - private pending_upload_requests: transfer.UploadKey[]; - private transfer_counter: number; - constructor(client: ConnectionHandler); - destroy(); - handle_command(command: connection.ServerCommand): boolean; - /******************************** File list ********************************/ - //TODO multiple requests (same path) - requestFileList(path: string, channel?: ChannelEntry, password?: string): Promise; - private notifyFileList(json); - private notifyFileListFinished(json); - /******************************** File download/upload ********************************/ - download_file(path: string, file: string, channel?: ChannelEntry, password?: string): Promise; - upload_file(options: transfer.UploadOptions): Promise; - private notifyStartDownload(json); - private notifyStartUpload(json); - delete_file(props: { - name: string; - path?: string; - cid?: number; - cpw?: string; - }): Promise; -} -declare class Icon { - id: number; - url: string; -} -declare enum ImageType { - UNKNOWN, - BITMAP, - PNG, - GIF, - SVG, - JPEG -} -declare function media_image_type(type: ImageType, file?: boolean); -declare function image_type(encoded_data: string | ArrayBuffer, base64_encoded?: boolean); -declare class CacheManager { - readonly cache_name: string; - private _cache_category: Cache; - constructor(name: string); - setupped(): boolean; - reset(); - setup(); - cleanup(max_age: number); - resolve_cached(key: string, max_age?: number): Promise; - put_cache(key: string, value: Response, type?: string, headers?: { - [key: string]: string; - }); - delete(key: string); -} -declare class IconManager { - private static cache: CacheManager; - handle: FileManager; - private _id_urls: { - [id: number]: string; - }; - private _loading_promises: { - [id: number]: Promise; - }; - constructor(handle: FileManager); - destroy(); - clear_cache(); - delete_icon(id: number): Promise; - iconList(): Promise; - create_icon_download(id: number): Promise; - private static _response_url(response: Response); - resolved_cached?(id: number): Promise; - private static _static_id_url: { - [icon: number]: string; - }; - private static _static_cached_promise: { - [icon: number]: Promise; - }; - static load_cached_icon(id: number, ignore_age?: boolean): Promise | Icon; - private _load_icon(id: number): Promise; - download_icon(id: number): Promise; - resolve_icon(id: number): Promise; - static generate_tag(icon: Promise | Icon | undefined, options?: { - animate?: boolean; - }): JQuery; - generateTag(id: number, options?: { - animate?: boolean; - }): JQuery; -} -declare class Avatar { - client_avatar_id: string; - avatar_id: string; - url: string; - type: ImageType; -} -declare class AvatarManager { - handle: FileManager; - private static cache: CacheManager; - private _cached_avatars: { - [response_avatar_id: number]: Avatar; - }; - private _loading_promises: { - [response_avatar_id: number]: Promise; - }; - constructor(handle: FileManager); - destroy(); - private _response_url(response: Response, type: ImageType): Promise; - resolved_cached?(client_avatar_id: string, avatar_version?: string): Promise; - create_avatar_download(client_avatar_id: string): Promise; - private _load_avatar(client_avatar_id: string, avatar_version: string); - /* loads an avatar by the avatar id and optional with the avatar version */ - load_avatar(client_avatar_id: string, avatar_version: string): Promise; - generate_client_tag(client: ClientEntry): JQuery; - update_cache(client_avatar_id: string, avatar_id: string); - generate_tag(client_avatar_id: string, avatar_id?: string, options?: { - callback_image?: (tag: JQuery) => any; - callback_avatar?: (avatar: Avatar) => any; - }): JQuery; - unique_id_2_avatar_id(unique_id: string); - private generate_default_image(): JQuery; - generate_chat_tag(client: { - id?: number; - database_id?: number; - }, client_unique_id: string, callback_loaded?: (successfully: boolean, error?: any) => any): JQuery; -} - -/* File: D:\TeaSpeak\web\shared\js\i18n\country.ts */ -declare namespace i18n { - export function country_name(alpha_code: string, fallback?: string); -} - -/* File: D:\TeaSpeak\web\shared\js\i18n\localize.ts */ -declare function guid(); -declare namespace i18n { - export interface TranslationKey { - message: string; - line?: number; - character?: number; - filename?: string; - } - export interface Translation { - key: TranslationKey; - translated: string; - flags?: string[]; - } - export interface Contributor { - name: string; - email: string; - } - export interface TranslationFile { - path: string; - full_url: string; - translations: Translation[]; - } - export interface RepositoryTranslation { - key: string; - path: string; - country_code: string; - name: string; - contributors: Contributor[]; - } - export interface TranslationRepository { - unique_id: string; - url: string; - name?: string; - contact?: string; - translations?: RepositoryTranslation[]; - load_timestamp?: number; - } - export function tr(message: string, key?: string); - export function tra(message: string, ...args: any[]); - export function load_file(url: string, path: string): Promise; - export function load_repository(url: string): Promise; - export namespace config { - export interface TranslationConfig { - current_repository_url?: string; - current_language?: string; - current_translation_url?: string; - current_translation_path?: string; - } - export interface RepositoryConfig { - repositories?: { - url?: string; - repository?: TranslationRepository; - }[]; - } - export function repository_config(); - export function save_repository_config(); - export function translation_config(): TranslationConfig; - export function save_translation_config(); - } - export function register_repository(repository: TranslationRepository); - export function registered_repositories(): TranslationRepository[]; - export function delete_repository(repository: TranslationRepository); - export function iterate_repositories(callback_entry: (repository: TranslationRepository) => any): Promise; - export function select_translation(repository: TranslationRepository, entry: RepositoryTranslation); - /* ATTENTION: This method is called before most other library inizialisations! */ - export function initialize(): Promise; -} -declare const tr: typeof i18n.tr; -declare const tra: typeof i18n.tra; - -/* File: D:\TeaSpeak\web\shared\js\log.ts */ -declare enum LogCategory { - CHANNEL, - CHANNEL_PROPERTIES, - CLIENT, - BOOKMARKS, - SERVER, - PERMISSIONS, - GENERAL, - NETWORKING, - VOICE, - CHAT, - AUDIO, - I18N, - IPC, - IDENTITIES, - STATISTICS, - DNS -} -declare namespace log { - export enum LogType { - TRACE, - DEBUG, - INFO, - WARNING, - ERROR - } - export let enabled_mapping; - //Values will be overridden by initialize() - export let level_mapping; - export enum GroupMode { - NATIVE, - PREFIX - } - //Category Example: ?log.i18n.enabled=0 - //Level Example A: ?log.level.trace.enabled=0 - //Level Example B: ?log.level=0 - export function initialize(default_level: LogType); - export function log(type: LogType, category: LogCategory, message: string, ...optionalParams: any[]); - export function trace(category: LogCategory, message: string, ...optionalParams: any[]); - export function debug(category: LogCategory, message: string, ...optionalParams: any[]); - export function info(category: LogCategory, message: string, ...optionalParams: any[]); - export function warn(category: LogCategory, message: string, ...optionalParams: any[]); - export function error(category: LogCategory, message: string, ...optionalParams: any[]); - export function group(level: LogType, category: LogCategory, name: string, ...optionalParams: any[]): Group; - export function table(level: LogType, category: LogCategory, title: string, arguments: any); - export class Group { - readonly mode: GroupMode; - readonly level: LogType; - readonly category: LogCategory; - readonly enabled: boolean; - owner: Group; - private readonly name: string; - private readonly optionalParams: any[][]; - private _collapsed: boolean; - private initialized; - private _log_prefix: string; - constructor(mode: GroupMode, level: LogType, category: LogCategory, name: string, optionalParams: any[][], owner?: Group); - group(level: LogType, name: string, ...optionalParams: any[]): Group; - collapsed(flag?: boolean): this; - log(message: string, ...optionalParams: any[]): this; - end(); - // @ts-ignore - get prefix(): string; - // @ts-ignore - set prefix(prefix: string); - } -} - -/* File: D:\TeaSpeak\web\shared\js\main.ts */ -declare const js_render; -declare const native_client; -declare function getUserMediaFunctionPromise(): (constraints: MediaStreamConstraints) => Promise; -declare interface Window { - open_connected_question: () => Promise; -} -declare function setup_close(); -declare function moment(...arguments): any; -declare function setup_jsrender(): boolean; -declare function initialize(): Promise; -declare function initialize_app(): Promise; -declare function str2ab8(str); -declare function arrayBufferBase64(base64: string); -declare function base64_encode_ab(source: ArrayBufferLike); -declare function handle_connect_request(properties: bipc.connect.ConnectRequestData, connection: ConnectionHandler); -declare function main(); -declare const task_teaweb_starter: loader.Task; -declare const task_connect_handler: loader.Task; -declare const task_certificate_callback: loader.Task; - -/* File: D:\TeaSpeak\web\shared\js\permission\GroupManager.ts */ -declare enum GroupType { - QUERY, - TEMPLATE, - NORMAL -} -declare enum GroupTarget { - SERVER, - CHANNEL -} -declare class GroupProperties { - iconid: number; - sortid: number; - savedb: boolean; - namemode: number; -} -declare class GroupPermissionRequest { - group_id: number; - promise: LaterPromise; -} -declare class Group { - properties: GroupProperties; - readonly handle: GroupManager; - readonly id: number; - readonly target: GroupTarget; - readonly type: GroupType; - name: string; - requiredModifyPower: number; - requiredMemberAddPower: number; - requiredMemberRemovePower: number; - constructor(handle: GroupManager, id: number, target: GroupTarget, type: GroupType, name: string); - updateProperty(key, value); -} -declare class GroupManager extends connection.AbstractCommandHandler { - readonly handle: ConnectionHandler; - serverGroups: Group[]; - channelGroups: Group[]; - private requests_group_permissions: GroupPermissionRequest[]; - constructor(client: ConnectionHandler); - destroy(); - handle_command(command: connection.ServerCommand): boolean; - requestGroups(); - static sorter(): (a: Group, b: Group) => number; - serverGroup?(id: number): Group; - channelGroup?(id: number): Group; - private handle_grouplist(json); - request_permissions(group: Group): Promise; - private handle_group_permission_list(json: any[]); -} - -/* File: D:\TeaSpeak\web\shared\js\permission\PermissionManager.ts */ -declare enum PermissionType { - B_SERVERINSTANCE_HELP_VIEW = "b_serverinstance_help_view", - B_SERVERINSTANCE_VERSION_VIEW = "b_serverinstance_version_view", - B_SERVERINSTANCE_INFO_VIEW = "b_serverinstance_info_view", - B_SERVERINSTANCE_VIRTUALSERVER_LIST = "b_serverinstance_virtualserver_list", - B_SERVERINSTANCE_BINDING_LIST = "b_serverinstance_binding_list", - B_SERVERINSTANCE_PERMISSION_LIST = "b_serverinstance_permission_list", - B_SERVERINSTANCE_PERMISSION_FIND = "b_serverinstance_permission_find", - B_VIRTUALSERVER_CREATE = "b_virtualserver_create", - B_VIRTUALSERVER_DELETE = "b_virtualserver_delete", - B_VIRTUALSERVER_START_ANY = "b_virtualserver_start_any", - B_VIRTUALSERVER_STOP_ANY = "b_virtualserver_stop_any", - B_VIRTUALSERVER_CHANGE_MACHINE_ID = "b_virtualserver_change_machine_id", - B_VIRTUALSERVER_CHANGE_TEMPLATE = "b_virtualserver_change_template", - B_SERVERQUERY_LOGIN = "b_serverquery_login", - B_SERVERINSTANCE_TEXTMESSAGE_SEND = "b_serverinstance_textmessage_send", - B_SERVERINSTANCE_LOG_VIEW = "b_serverinstance_log_view", - B_SERVERINSTANCE_LOG_ADD = "b_serverinstance_log_add", - B_SERVERINSTANCE_STOP = "b_serverinstance_stop", - B_SERVERINSTANCE_MODIFY_SETTINGS = "b_serverinstance_modify_settings", - B_SERVERINSTANCE_MODIFY_QUERYGROUP = "b_serverinstance_modify_querygroup", - B_SERVERINSTANCE_MODIFY_TEMPLATES = "b_serverinstance_modify_templates", - B_VIRTUALSERVER_SELECT = "b_virtualserver_select", - B_VIRTUALSERVER_SELECT_GODMODE = "b_virtualserver_select_godmode", - B_VIRTUALSERVER_INFO_VIEW = "b_virtualserver_info_view", - B_VIRTUALSERVER_CONNECTIONINFO_VIEW = "b_virtualserver_connectioninfo_view", - B_VIRTUALSERVER_CHANNEL_LIST = "b_virtualserver_channel_list", - B_VIRTUALSERVER_CHANNEL_SEARCH = "b_virtualserver_channel_search", - B_VIRTUALSERVER_CLIENT_LIST = "b_virtualserver_client_list", - B_VIRTUALSERVER_CLIENT_SEARCH = "b_virtualserver_client_search", - B_VIRTUALSERVER_CLIENT_DBLIST = "b_virtualserver_client_dblist", - B_VIRTUALSERVER_CLIENT_DBSEARCH = "b_virtualserver_client_dbsearch", - B_VIRTUALSERVER_CLIENT_DBINFO = "b_virtualserver_client_dbinfo", - B_VIRTUALSERVER_PERMISSION_FIND = "b_virtualserver_permission_find", - B_VIRTUALSERVER_CUSTOM_SEARCH = "b_virtualserver_custom_search", - B_VIRTUALSERVER_START = "b_virtualserver_start", - B_VIRTUALSERVER_STOP = "b_virtualserver_stop", - B_VIRTUALSERVER_TOKEN_LIST = "b_virtualserver_token_list", - B_VIRTUALSERVER_TOKEN_ADD = "b_virtualserver_token_add", - B_VIRTUALSERVER_TOKEN_USE = "b_virtualserver_token_use", - B_VIRTUALSERVER_TOKEN_DELETE = "b_virtualserver_token_delete", - B_VIRTUALSERVER_LOG_VIEW = "b_virtualserver_log_view", - B_VIRTUALSERVER_LOG_ADD = "b_virtualserver_log_add", - B_VIRTUALSERVER_JOIN_IGNORE_PASSWORD = "b_virtualserver_join_ignore_password", - B_VIRTUALSERVER_NOTIFY_REGISTER = "b_virtualserver_notify_register", - B_VIRTUALSERVER_NOTIFY_UNREGISTER = "b_virtualserver_notify_unregister", - B_VIRTUALSERVER_SNAPSHOT_CREATE = "b_virtualserver_snapshot_create", - B_VIRTUALSERVER_SNAPSHOT_DEPLOY = "b_virtualserver_snapshot_deploy", - B_VIRTUALSERVER_PERMISSION_RESET = "b_virtualserver_permission_reset", - B_VIRTUALSERVER_MODIFY_NAME = "b_virtualserver_modify_name", - B_VIRTUALSERVER_MODIFY_WELCOMEMESSAGE = "b_virtualserver_modify_welcomemessage", - B_VIRTUALSERVER_MODIFY_MAXCLIENTS = "b_virtualserver_modify_maxclients", - B_VIRTUALSERVER_MODIFY_RESERVED_SLOTS = "b_virtualserver_modify_reserved_slots", - B_VIRTUALSERVER_MODIFY_PASSWORD = "b_virtualserver_modify_password", - B_VIRTUALSERVER_MODIFY_DEFAULT_SERVERGROUP = "b_virtualserver_modify_default_servergroup", - B_VIRTUALSERVER_MODIFY_DEFAULT_MUSICGROUP = "b_virtualserver_modify_default_musicgroup", - B_VIRTUALSERVER_MODIFY_DEFAULT_CHANNELGROUP = "b_virtualserver_modify_default_channelgroup", - B_VIRTUALSERVER_MODIFY_DEFAULT_CHANNELADMINGROUP = "b_virtualserver_modify_default_channeladmingroup", - B_VIRTUALSERVER_MODIFY_CHANNEL_FORCED_SILENCE = "b_virtualserver_modify_channel_forced_silence", - B_VIRTUALSERVER_MODIFY_COMPLAIN = "b_virtualserver_modify_complain", - B_VIRTUALSERVER_MODIFY_ANTIFLOOD = "b_virtualserver_modify_antiflood", - B_VIRTUALSERVER_MODIFY_FT_SETTINGS = "b_virtualserver_modify_ft_settings", - B_VIRTUALSERVER_MODIFY_FT_QUOTAS = "b_virtualserver_modify_ft_quotas", - B_VIRTUALSERVER_MODIFY_HOSTMESSAGE = "b_virtualserver_modify_hostmessage", - B_VIRTUALSERVER_MODIFY_HOSTBANNER = "b_virtualserver_modify_hostbanner", - B_VIRTUALSERVER_MODIFY_HOSTBUTTON = "b_virtualserver_modify_hostbutton", - B_VIRTUALSERVER_MODIFY_PORT = "b_virtualserver_modify_port", - B_VIRTUALSERVER_MODIFY_HOST = "b_virtualserver_modify_host", - B_VIRTUALSERVER_MODIFY_DEFAULT_MESSAGES = "b_virtualserver_modify_default_messages", - B_VIRTUALSERVER_MODIFY_AUTOSTART = "b_virtualserver_modify_autostart", - B_VIRTUALSERVER_MODIFY_NEEDED_IDENTITY_SECURITY_LEVEL = "b_virtualserver_modify_needed_identity_security_level", - B_VIRTUALSERVER_MODIFY_PRIORITY_SPEAKER_DIMM_MODIFICATOR = "b_virtualserver_modify_priority_speaker_dimm_modificator", - B_VIRTUALSERVER_MODIFY_LOG_SETTINGS = "b_virtualserver_modify_log_settings", - B_VIRTUALSERVER_MODIFY_MIN_CLIENT_VERSION = "b_virtualserver_modify_min_client_version", - B_VIRTUALSERVER_MODIFY_ICON_ID = "b_virtualserver_modify_icon_id", - B_VIRTUALSERVER_MODIFY_WEBLIST = "b_virtualserver_modify_weblist", - B_VIRTUALSERVER_MODIFY_CODEC_ENCRYPTION_MODE = "b_virtualserver_modify_codec_encryption_mode", - B_VIRTUALSERVER_MODIFY_TEMPORARY_PASSWORDS = "b_virtualserver_modify_temporary_passwords", - B_VIRTUALSERVER_MODIFY_TEMPORARY_PASSWORDS_OWN = "b_virtualserver_modify_temporary_passwords_own", - B_VIRTUALSERVER_MODIFY_CHANNEL_TEMP_DELETE_DELAY_DEFAULT = "b_virtualserver_modify_channel_temp_delete_delay_default", - B_VIRTUALSERVER_MODIFY_MUSIC_BOT_LIMIT = "b_virtualserver_modify_music_bot_limit", - B_VIRTUALSERVER_MODIFY_COUNTRY_CODE = "b_virtualserver_modify_country_code", - I_CHANNEL_MIN_DEPTH = "i_channel_min_depth", - I_CHANNEL_MAX_DEPTH = "i_channel_max_depth", - B_CHANNEL_GROUP_INHERITANCE_END = "b_channel_group_inheritance_end", - I_CHANNEL_PERMISSION_MODIFY_POWER = "i_channel_permission_modify_power", - I_CHANNEL_NEEDED_PERMISSION_MODIFY_POWER = "i_channel_needed_permission_modify_power", - B_CHANNEL_INFO_VIEW = "b_channel_info_view", - B_CHANNEL_CREATE_CHILD = "b_channel_create_child", - B_CHANNEL_CREATE_PERMANENT = "b_channel_create_permanent", - B_CHANNEL_CREATE_SEMI_PERMANENT = "b_channel_create_semi_permanent", - B_CHANNEL_CREATE_TEMPORARY = "b_channel_create_temporary", - B_CHANNEL_CREATE_PRIVATE = "b_channel_create_private", - B_CHANNEL_CREATE_WITH_TOPIC = "b_channel_create_with_topic", - B_CHANNEL_CREATE_WITH_DESCRIPTION = "b_channel_create_with_description", - B_CHANNEL_CREATE_WITH_PASSWORD = "b_channel_create_with_password", - B_CHANNEL_CREATE_MODIFY_WITH_CODEC_SPEEX8 = "b_channel_create_modify_with_codec_speex8", - B_CHANNEL_CREATE_MODIFY_WITH_CODEC_SPEEX16 = "b_channel_create_modify_with_codec_speex16", - B_CHANNEL_CREATE_MODIFY_WITH_CODEC_SPEEX32 = "b_channel_create_modify_with_codec_speex32", - B_CHANNEL_CREATE_MODIFY_WITH_CODEC_CELTMONO48 = "b_channel_create_modify_with_codec_celtmono48", - B_CHANNEL_CREATE_MODIFY_WITH_CODEC_OPUSVOICE = "b_channel_create_modify_with_codec_opusvoice", - B_CHANNEL_CREATE_MODIFY_WITH_CODEC_OPUSMUSIC = "b_channel_create_modify_with_codec_opusmusic", - I_CHANNEL_CREATE_MODIFY_WITH_CODEC_MAXQUALITY = "i_channel_create_modify_with_codec_maxquality", - I_CHANNEL_CREATE_MODIFY_WITH_CODEC_LATENCY_FACTOR_MIN = "i_channel_create_modify_with_codec_latency_factor_min", - I_CHANNEL_CREATE_MODIFY_CONVERSATION_HISTORY_LENGTH = "i_channel_create_modify_conversation_history_length", - B_CHANNEL_CREATE_MODIFY_CONVERSATION_HISTORY_UNLIMITED = "b_channel_create_modify_conversation_history_unlimited", - B_CHANNEL_CREATE_MODIFY_CONVERSATION_PRIVATE = "b_channel_create_modify_conversation_private", - B_CHANNEL_CREATE_WITH_MAXCLIENTS = "b_channel_create_with_maxclients", - B_CHANNEL_CREATE_WITH_MAXFAMILYCLIENTS = "b_channel_create_with_maxfamilyclients", - B_CHANNEL_CREATE_WITH_SORTORDER = "b_channel_create_with_sortorder", - B_CHANNEL_CREATE_WITH_DEFAULT = "b_channel_create_with_default", - B_CHANNEL_CREATE_WITH_NEEDED_TALK_POWER = "b_channel_create_with_needed_talk_power", - B_CHANNEL_CREATE_MODIFY_WITH_FORCE_PASSWORD = "b_channel_create_modify_with_force_password", - I_CHANNEL_CREATE_MODIFY_WITH_TEMP_DELETE_DELAY = "i_channel_create_modify_with_temp_delete_delay", - B_CHANNEL_MODIFY_PARENT = "b_channel_modify_parent", - B_CHANNEL_MODIFY_MAKE_DEFAULT = "b_channel_modify_make_default", - B_CHANNEL_MODIFY_MAKE_PERMANENT = "b_channel_modify_make_permanent", - B_CHANNEL_MODIFY_MAKE_SEMI_PERMANENT = "b_channel_modify_make_semi_permanent", - B_CHANNEL_MODIFY_MAKE_TEMPORARY = "b_channel_modify_make_temporary", - B_CHANNEL_MODIFY_NAME = "b_channel_modify_name", - B_CHANNEL_MODIFY_TOPIC = "b_channel_modify_topic", - B_CHANNEL_MODIFY_DESCRIPTION = "b_channel_modify_description", - B_CHANNEL_MODIFY_PASSWORD = "b_channel_modify_password", - B_CHANNEL_MODIFY_CODEC = "b_channel_modify_codec", - B_CHANNEL_MODIFY_CODEC_QUALITY = "b_channel_modify_codec_quality", - B_CHANNEL_MODIFY_CODEC_LATENCY_FACTOR = "b_channel_modify_codec_latency_factor", - B_CHANNEL_MODIFY_MAXCLIENTS = "b_channel_modify_maxclients", - B_CHANNEL_MODIFY_MAXFAMILYCLIENTS = "b_channel_modify_maxfamilyclients", - B_CHANNEL_MODIFY_SORTORDER = "b_channel_modify_sortorder", - B_CHANNEL_MODIFY_NEEDED_TALK_POWER = "b_channel_modify_needed_talk_power", - I_CHANNEL_MODIFY_POWER = "i_channel_modify_power", - I_CHANNEL_NEEDED_MODIFY_POWER = "i_channel_needed_modify_power", - B_CHANNEL_MODIFY_MAKE_CODEC_ENCRYPTED = "b_channel_modify_make_codec_encrypted", - B_CHANNEL_MODIFY_TEMP_DELETE_DELAY = "b_channel_modify_temp_delete_delay", - B_CHANNEL_DELETE_PERMANENT = "b_channel_delete_permanent", - B_CHANNEL_DELETE_SEMI_PERMANENT = "b_channel_delete_semi_permanent", - B_CHANNEL_DELETE_TEMPORARY = "b_channel_delete_temporary", - B_CHANNEL_DELETE_FLAG_FORCE = "b_channel_delete_flag_force", - I_CHANNEL_DELETE_POWER = "i_channel_delete_power", - B_CHANNEL_CONVERSATION_MESSAGE_DELETE = "b_channel_conversation_message_delete", - I_CHANNEL_NEEDED_DELETE_POWER = "i_channel_needed_delete_power", - B_CHANNEL_JOIN_PERMANENT = "b_channel_join_permanent", - B_CHANNEL_JOIN_SEMI_PERMANENT = "b_channel_join_semi_permanent", - B_CHANNEL_JOIN_TEMPORARY = "b_channel_join_temporary", - B_CHANNEL_JOIN_IGNORE_PASSWORD = "b_channel_join_ignore_password", - B_CHANNEL_JOIN_IGNORE_MAXCLIENTS = "b_channel_join_ignore_maxclients", - B_CHANNEL_IGNORE_VIEW_POWER = "b_channel_ignore_view_power", - I_CHANNEL_JOIN_POWER = "i_channel_join_power", - I_CHANNEL_NEEDED_JOIN_POWER = "i_channel_needed_join_power", - B_CHANNEL_IGNORE_JOIN_POWER = "b_channel_ignore_join_power", - B_CHANNEL_IGNORE_DESCRIPTION_VIEW_POWER = "b_channel_ignore_description_view_power", - I_CHANNEL_VIEW_POWER = "i_channel_view_power", - I_CHANNEL_NEEDED_VIEW_POWER = "i_channel_needed_view_power", - I_CHANNEL_SUBSCRIBE_POWER = "i_channel_subscribe_power", - I_CHANNEL_NEEDED_SUBSCRIBE_POWER = "i_channel_needed_subscribe_power", - I_CHANNEL_DESCRIPTION_VIEW_POWER = "i_channel_description_view_power", - I_CHANNEL_NEEDED_DESCRIPTION_VIEW_POWER = "i_channel_needed_description_view_power", - I_ICON_ID = "i_icon_id", - I_MAX_ICON_FILESIZE = "i_max_icon_filesize", - I_MAX_PLAYLIST_SIZE = "i_max_playlist_size", - I_MAX_PLAYLISTS = "i_max_playlists", - B_ICON_MANAGE = "b_icon_manage", - B_GROUP_IS_PERMANENT = "b_group_is_permanent", - I_GROUP_AUTO_UPDATE_TYPE = "i_group_auto_update_type", - I_GROUP_AUTO_UPDATE_MAX_VALUE = "i_group_auto_update_max_value", - I_GROUP_SORT_ID = "i_group_sort_id", - I_GROUP_SHOW_NAME_IN_TREE = "i_group_show_name_in_tree", - B_VIRTUALSERVER_SERVERGROUP_CREATE = "b_virtualserver_servergroup_create", - B_VIRTUALSERVER_SERVERGROUP_LIST = "b_virtualserver_servergroup_list", - B_VIRTUALSERVER_SERVERGROUP_PERMISSION_LIST = "b_virtualserver_servergroup_permission_list", - B_VIRTUALSERVER_SERVERGROUP_CLIENT_LIST = "b_virtualserver_servergroup_client_list", - B_VIRTUALSERVER_CHANNELGROUP_CREATE = "b_virtualserver_channelgroup_create", - B_VIRTUALSERVER_CHANNELGROUP_LIST = "b_virtualserver_channelgroup_list", - B_VIRTUALSERVER_CHANNELGROUP_PERMISSION_LIST = "b_virtualserver_channelgroup_permission_list", - B_VIRTUALSERVER_CHANNELGROUP_CLIENT_LIST = "b_virtualserver_channelgroup_client_list", - B_VIRTUALSERVER_CLIENT_PERMISSION_LIST = "b_virtualserver_client_permission_list", - B_VIRTUALSERVER_CHANNEL_PERMISSION_LIST = "b_virtualserver_channel_permission_list", - B_VIRTUALSERVER_CHANNELCLIENT_PERMISSION_LIST = "b_virtualserver_channelclient_permission_list", - B_VIRTUALSERVER_PLAYLIST_PERMISSION_LIST = "b_virtualserver_playlist_permission_list", - I_SERVER_GROUP_MODIFY_POWER = "i_server_group_modify_power", - I_SERVER_GROUP_NEEDED_MODIFY_POWER = "i_server_group_needed_modify_power", - I_SERVER_GROUP_MEMBER_ADD_POWER = "i_server_group_member_add_power", - I_SERVER_GROUP_SELF_ADD_POWER = "i_server_group_self_add_power", - I_SERVER_GROUP_NEEDED_MEMBER_ADD_POWER = "i_server_group_needed_member_add_power", - I_SERVER_GROUP_MEMBER_REMOVE_POWER = "i_server_group_member_remove_power", - I_SERVER_GROUP_SELF_REMOVE_POWER = "i_server_group_self_remove_power", - I_SERVER_GROUP_NEEDED_MEMBER_REMOVE_POWER = "i_server_group_needed_member_remove_power", - I_CHANNEL_GROUP_MODIFY_POWER = "i_channel_group_modify_power", - I_CHANNEL_GROUP_NEEDED_MODIFY_POWER = "i_channel_group_needed_modify_power", - I_CHANNEL_GROUP_MEMBER_ADD_POWER = "i_channel_group_member_add_power", - I_CHANNEL_GROUP_SELF_ADD_POWER = "i_channel_group_self_add_power", - I_CHANNEL_GROUP_NEEDED_MEMBER_ADD_POWER = "i_channel_group_needed_member_add_power", - I_CHANNEL_GROUP_MEMBER_REMOVE_POWER = "i_channel_group_member_remove_power", - I_CHANNEL_GROUP_SELF_REMOVE_POWER = "i_channel_group_self_remove_power", - I_CHANNEL_GROUP_NEEDED_MEMBER_REMOVE_POWER = "i_channel_group_needed_member_remove_power", - I_GROUP_MEMBER_ADD_POWER = "i_group_member_add_power", - I_GROUP_NEEDED_MEMBER_ADD_POWER = "i_group_needed_member_add_power", - I_GROUP_MEMBER_REMOVE_POWER = "i_group_member_remove_power", - I_GROUP_NEEDED_MEMBER_REMOVE_POWER = "i_group_needed_member_remove_power", - I_GROUP_MODIFY_POWER = "i_group_modify_power", - I_GROUP_NEEDED_MODIFY_POWER = "i_group_needed_modify_power", - I_PERMISSION_MODIFY_POWER = "i_permission_modify_power", - B_PERMISSION_MODIFY_POWER_IGNORE = "b_permission_modify_power_ignore", - B_VIRTUALSERVER_SERVERGROUP_DELETE = "b_virtualserver_servergroup_delete", - B_VIRTUALSERVER_CHANNELGROUP_DELETE = "b_virtualserver_channelgroup_delete", - I_CLIENT_PERMISSION_MODIFY_POWER = "i_client_permission_modify_power", - I_CLIENT_NEEDED_PERMISSION_MODIFY_POWER = "i_client_needed_permission_modify_power", - I_CLIENT_MAX_CLONES_UID = "i_client_max_clones_uid", - I_CLIENT_MAX_CLONES_IP = "i_client_max_clones_ip", - I_CLIENT_MAX_CLONES_HWID = "i_client_max_clones_hwid", - I_CLIENT_MAX_IDLETIME = "i_client_max_idletime", - I_CLIENT_MAX_AVATAR_FILESIZE = "i_client_max_avatar_filesize", - I_CLIENT_MAX_CHANNEL_SUBSCRIPTIONS = "i_client_max_channel_subscriptions", - I_CLIENT_MAX_CHANNELS = "i_client_max_channels", - I_CLIENT_MAX_TEMPORARY_CHANNELS = "i_client_max_temporary_channels", - I_CLIENT_MAX_SEMI_CHANNELS = "i_client_max_semi_channels", - I_CLIENT_MAX_PERMANENT_CHANNELS = "i_client_max_permanent_channels", - B_CLIENT_USE_PRIORITY_SPEAKER = "b_client_use_priority_speaker", - B_CLIENT_SKIP_CHANNELGROUP_PERMISSIONS = "b_client_skip_channelgroup_permissions", - B_CLIENT_FORCE_PUSH_TO_TALK = "b_client_force_push_to_talk", - B_CLIENT_IGNORE_BANS = "b_client_ignore_bans", - B_CLIENT_IGNORE_VPN = "b_client_ignore_vpn", - B_CLIENT_IGNORE_ANTIFLOOD = "b_client_ignore_antiflood", - B_CLIENT_ENFORCE_VALID_HWID = "b_client_enforce_valid_hwid", - B_CLIENT_ALLOW_INVALID_PACKET = "b_client_allow_invalid_packet", - B_CLIENT_ALLOW_INVALID_BADGES = "b_client_allow_invalid_badges", - B_CLIENT_ISSUE_CLIENT_QUERY_COMMAND = "b_client_issue_client_query_command", - B_CLIENT_USE_RESERVED_SLOT = "b_client_use_reserved_slot", - B_CLIENT_USE_CHANNEL_COMMANDER = "b_client_use_channel_commander", - B_CLIENT_REQUEST_TALKER = "b_client_request_talker", - B_CLIENT_AVATAR_DELETE_OTHER = "b_client_avatar_delete_other", - B_CLIENT_IS_STICKY = "b_client_is_sticky", - B_CLIENT_IGNORE_STICKY = "b_client_ignore_sticky", - B_CLIENT_MUSIC_CREATE_PERMANENT = "b_client_music_create_permanent", - B_CLIENT_MUSIC_CREATE_SEMI_PERMANENT = "b_client_music_create_semi_permanent", - B_CLIENT_MUSIC_CREATE_TEMPORARY = "b_client_music_create_temporary", - B_CLIENT_MUSIC_MODIFY_PERMANENT = "b_client_music_modify_permanent", - B_CLIENT_MUSIC_MODIFY_SEMI_PERMANENT = "b_client_music_modify_semi_permanent", - B_CLIENT_MUSIC_MODIFY_TEMPORARY = "b_client_music_modify_temporary", - I_CLIENT_MUSIC_CREATE_MODIFY_MAX_VOLUME = "i_client_music_create_modify_max_volume", - I_CLIENT_MUSIC_LIMIT = "i_client_music_limit", - I_CLIENT_MUSIC_NEEDED_DELETE_POWER = "i_client_music_needed_delete_power", - I_CLIENT_MUSIC_DELETE_POWER = "i_client_music_delete_power", - I_CLIENT_MUSIC_PLAY_POWER = "i_client_music_play_power", - I_CLIENT_MUSIC_NEEDED_PLAY_POWER = "i_client_music_needed_play_power", - I_CLIENT_MUSIC_MODIFY_POWER = "i_client_music_modify_power", - I_CLIENT_MUSIC_NEEDED_MODIFY_POWER = "i_client_music_needed_modify_power", - I_CLIENT_MUSIC_RENAME_POWER = "i_client_music_rename_power", - I_CLIENT_MUSIC_NEEDED_RENAME_POWER = "i_client_music_needed_rename_power", - B_PLAYLIST_CREATE = "b_playlist_create", - I_PLAYLIST_VIEW_POWER = "i_playlist_view_power", - I_PLAYLIST_NEEDED_VIEW_POWER = "i_playlist_needed_view_power", - I_PLAYLIST_MODIFY_POWER = "i_playlist_modify_power", - I_PLAYLIST_NEEDED_MODIFY_POWER = "i_playlist_needed_modify_power", - I_PLAYLIST_PERMISSION_MODIFY_POWER = "i_playlist_permission_modify_power", - I_PLAYLIST_NEEDED_PERMISSION_MODIFY_POWER = "i_playlist_needed_permission_modify_power", - I_PLAYLIST_DELETE_POWER = "i_playlist_delete_power", - I_PLAYLIST_NEEDED_DELETE_POWER = "i_playlist_needed_delete_power", - I_PLAYLIST_SONG_ADD_POWER = "i_playlist_song_add_power", - I_PLAYLIST_SONG_NEEDED_ADD_POWER = "i_playlist_song_needed_add_power", - I_PLAYLIST_SONG_REMOVE_POWER = "i_playlist_song_remove_power", - I_PLAYLIST_SONG_NEEDED_REMOVE_POWER = "i_playlist_song_needed_remove_power", - B_CLIENT_INFO_VIEW = "b_client_info_view", - B_CLIENT_PERMISSIONOVERVIEW_VIEW = "b_client_permissionoverview_view", - B_CLIENT_PERMISSIONOVERVIEW_OWN = "b_client_permissionoverview_own", - B_CLIENT_REMOTEADDRESS_VIEW = "b_client_remoteaddress_view", - I_CLIENT_SERVERQUERY_VIEW_POWER = "i_client_serverquery_view_power", - I_CLIENT_NEEDED_SERVERQUERY_VIEW_POWER = "i_client_needed_serverquery_view_power", - B_CLIENT_CUSTOM_INFO_VIEW = "b_client_custom_info_view", - B_CLIENT_MUSIC_CHANNEL_LIST = "b_client_music_channel_list", - B_CLIENT_MUSIC_SERVER_LIST = "b_client_music_server_list", - I_CLIENT_MUSIC_INFO = "i_client_music_info", - I_CLIENT_MUSIC_NEEDED_INFO = "i_client_music_needed_info", - I_CLIENT_KICK_FROM_SERVER_POWER = "i_client_kick_from_server_power", - I_CLIENT_NEEDED_KICK_FROM_SERVER_POWER = "i_client_needed_kick_from_server_power", - I_CLIENT_KICK_FROM_CHANNEL_POWER = "i_client_kick_from_channel_power", - I_CLIENT_NEEDED_KICK_FROM_CHANNEL_POWER = "i_client_needed_kick_from_channel_power", - I_CLIENT_BAN_POWER = "i_client_ban_power", - I_CLIENT_NEEDED_BAN_POWER = "i_client_needed_ban_power", - I_CLIENT_MOVE_POWER = "i_client_move_power", - I_CLIENT_NEEDED_MOVE_POWER = "i_client_needed_move_power", - I_CLIENT_COMPLAIN_POWER = "i_client_complain_power", - I_CLIENT_NEEDED_COMPLAIN_POWER = "i_client_needed_complain_power", - B_CLIENT_COMPLAIN_LIST = "b_client_complain_list", - B_CLIENT_COMPLAIN_DELETE_OWN = "b_client_complain_delete_own", - B_CLIENT_COMPLAIN_DELETE = "b_client_complain_delete", - B_CLIENT_BAN_LIST = "b_client_ban_list", - B_CLIENT_BAN_LIST_GLOBAL = "b_client_ban_list_global", - B_CLIENT_BAN_TRIGGER_LIST = "b_client_ban_trigger_list", - B_CLIENT_BAN_CREATE = "b_client_ban_create", - B_CLIENT_BAN_CREATE_GLOBAL = "b_client_ban_create_global", - B_CLIENT_BAN_NAME = "b_client_ban_name", - B_CLIENT_BAN_IP = "b_client_ban_ip", - B_CLIENT_BAN_HWID = "b_client_ban_hwid", - B_CLIENT_BAN_EDIT = "b_client_ban_edit", - B_CLIENT_BAN_EDIT_GLOBAL = "b_client_ban_edit_global", - B_CLIENT_BAN_DELETE_OWN = "b_client_ban_delete_own", - B_CLIENT_BAN_DELETE = "b_client_ban_delete", - B_CLIENT_BAN_DELETE_OWN_GLOBAL = "b_client_ban_delete_own_global", - B_CLIENT_BAN_DELETE_GLOBAL = "b_client_ban_delete_global", - I_CLIENT_BAN_MAX_BANTIME = "i_client_ban_max_bantime", - I_CLIENT_PRIVATE_TEXTMESSAGE_POWER = "i_client_private_textmessage_power", - I_CLIENT_NEEDED_PRIVATE_TEXTMESSAGE_POWER = "i_client_needed_private_textmessage_power", - B_CLIENT_EVEN_TEXTMESSAGE_SEND = "b_client_even_textmessage_send", - B_CLIENT_SERVER_TEXTMESSAGE_SEND = "b_client_server_textmessage_send", - B_CLIENT_CHANNEL_TEXTMESSAGE_SEND = "b_client_channel_textmessage_send", - B_CLIENT_OFFLINE_TEXTMESSAGE_SEND = "b_client_offline_textmessage_send", - I_CLIENT_TALK_POWER = "i_client_talk_power", - I_CLIENT_NEEDED_TALK_POWER = "i_client_needed_talk_power", - I_CLIENT_POKE_POWER = "i_client_poke_power", - I_CLIENT_NEEDED_POKE_POWER = "i_client_needed_poke_power", - B_CLIENT_SET_FLAG_TALKER = "b_client_set_flag_talker", - I_CLIENT_WHISPER_POWER = "i_client_whisper_power", - I_CLIENT_NEEDED_WHISPER_POWER = "i_client_needed_whisper_power", - B_CLIENT_MODIFY_DESCRIPTION = "b_client_modify_description", - B_CLIENT_MODIFY_OWN_DESCRIPTION = "b_client_modify_own_description", - B_CLIENT_USE_BBCODE_ANY = "b_client_use_bbcode_any", - B_CLIENT_USE_BBCODE_URL = "b_client_use_bbcode_url", - B_CLIENT_USE_BBCODE_IMAGE = "b_client_use_bbcode_image", - B_CLIENT_MODIFY_DBPROPERTIES = "b_client_modify_dbproperties", - B_CLIENT_DELETE_DBPROPERTIES = "b_client_delete_dbproperties", - B_CLIENT_CREATE_MODIFY_SERVERQUERY_LOGIN = "b_client_create_modify_serverquery_login", - B_CLIENT_QUERY_CREATE = "b_client_query_create", - B_CLIENT_QUERY_LIST = "b_client_query_list", - B_CLIENT_QUERY_LIST_OWN = "b_client_query_list_own", - B_CLIENT_QUERY_RENAME = "b_client_query_rename", - B_CLIENT_QUERY_RENAME_OWN = "b_client_query_rename_own", - B_CLIENT_QUERY_CHANGE_PASSWORD = "b_client_query_change_password", - B_CLIENT_QUERY_CHANGE_OWN_PASSWORD = "b_client_query_change_own_password", - B_CLIENT_QUERY_CHANGE_PASSWORD_GLOBAL = "b_client_query_change_password_global", - B_CLIENT_QUERY_DELETE = "b_client_query_delete", - B_CLIENT_QUERY_DELETE_OWN = "b_client_query_delete_own", - B_FT_IGNORE_PASSWORD = "b_ft_ignore_password", - B_FT_TRANSFER_LIST = "b_ft_transfer_list", - I_FT_FILE_UPLOAD_POWER = "i_ft_file_upload_power", - I_FT_NEEDED_FILE_UPLOAD_POWER = "i_ft_needed_file_upload_power", - I_FT_FILE_DOWNLOAD_POWER = "i_ft_file_download_power", - I_FT_NEEDED_FILE_DOWNLOAD_POWER = "i_ft_needed_file_download_power", - I_FT_FILE_DELETE_POWER = "i_ft_file_delete_power", - I_FT_NEEDED_FILE_DELETE_POWER = "i_ft_needed_file_delete_power", - I_FT_FILE_RENAME_POWER = "i_ft_file_rename_power", - I_FT_NEEDED_FILE_RENAME_POWER = "i_ft_needed_file_rename_power", - I_FT_FILE_BROWSE_POWER = "i_ft_file_browse_power", - I_FT_NEEDED_FILE_BROWSE_POWER = "i_ft_needed_file_browse_power", - I_FT_DIRECTORY_CREATE_POWER = "i_ft_directory_create_power", - I_FT_NEEDED_DIRECTORY_CREATE_POWER = "i_ft_needed_directory_create_power", - I_FT_QUOTA_MB_DOWNLOAD_PER_CLIENT = "i_ft_quota_mb_download_per_client", - I_FT_QUOTA_MB_UPLOAD_PER_CLIENT = "i_ft_quota_mb_upload_per_client" -} -declare class PermissionInfo { - name: string; - id: number; - description: string; - is_boolean(); - id_grant(): number; -} -declare class PermissionGroup { - begin: number; - end: number; - deep: number; - name: string; -} -declare class GroupedPermissions { - group: PermissionGroup; - permissions: PermissionInfo[]; - children: GroupedPermissions[]; - parent: GroupedPermissions; -} -declare class PermissionValue { - readonly type: PermissionInfo; - value: number; - flag_skip: boolean; - flag_negate: boolean; - granted_value: number; - constructor(type, value?); - granted(requiredValue: number, required?: boolean): boolean; - hasValue(): boolean; - hasGrant(): boolean; -} -declare class NeededPermissionValue extends PermissionValue { - constructor(type, value); -} -declare namespace permissions { - export type PermissionRequestKeys = { - client_id?: number; - channel_id?: number; - playlist_id?: number; - }; - export type PermissionRequest = PermissionRequestKeys & { - timeout_id: any; - promise: LaterPromise; - }; - export namespace find { - export type Entry = { - type: "server" | "channel" | "client" | "client_channel" | "channel_group" | "server_group"; - value: number; - id: number; - }; - export type Client = Entry & { - type: "client"; - client_id: number; - }; - export type Channel = Entry & { - type: "channel"; - channel_id: number; - }; - export type Server = Entry & { - type: "server"; - }; - export type ClientChannel = Entry & { - type: "client_channel"; - client_id: number; - channel_id: number; - }; - export type ChannelGroup = Entry & { - type: "channel_group"; - group_id: number; - }; - export type ServerGroup = Entry & { - type: "server_group"; - group_id: number; - }; - } -} -declare type RequestLists = "requests_channel_permissions" | "requests_client_permissions" | "requests_client_channel_permissions" | "requests_playlist_permissions" | "requests_playlist_client_permissions"; -declare class PermissionManager extends connection.AbstractCommandHandler { - readonly handle: ConnectionHandler; - permissionList: PermissionInfo[]; - permissionGroups: PermissionGroup[]; - neededPermissions: NeededPermissionValue[]; - needed_permission_change_listener: { - [permission: string]: (() => any)[]; - }; - requests_channel_permissions: permissions.PermissionRequest[]; - requests_client_permissions: permissions.PermissionRequest[]; - requests_client_channel_permissions: permissions.PermissionRequest[]; - requests_playlist_permissions: permissions.PermissionRequest[]; - requests_playlist_client_permissions: permissions.PermissionRequest[]; - requests_permfind: { - timeout_id: number; - permission: string; - callback: (status: "success" | "error", data: any) => void; - }[]; - initializedListener: ((initialized: boolean) => void)[]; - private _cacheNeededPermissions: any; - /* Static info mapping until TeaSpeak implements a detailed info */ - static readonly group_mapping: { - name: string; - deep: number; - }[]; - private _group_mapping; - public static parse_permission_bulk(json: any[], manager: PermissionManager): PermissionValue[]; - constructor(client: ConnectionHandler); - destroy(); - handle_command(command: connection.ServerCommand): boolean; - initialized(): boolean; - public requestPermissionList(); - private onPermissionList(json); - private onNeededPermissions(json); - register_needed_permission(key: PermissionType, listener: () => any); - unregister_needed_permission(key: PermissionType, listener: () => any); - resolveInfo?(key: number | string | PermissionType): PermissionInfo; - /* channel permission request */ - private onChannelPermList(json); - private execute_channel_permission_request(request: permissions.PermissionRequestKeys); - requestChannelPermissions(channelId: number): Promise; - /* client permission request */ - private onClientPermList(json: any[]); - private execute_client_permission_request(request: permissions.PermissionRequestKeys); - requestClientPermissions(client_id: number): Promise; - /* client channel permission request */ - private onChannelClientPermList(json: any[]); - private execute_client_channel_permission_request(request: permissions.PermissionRequestKeys); - requestClientChannelPermissions(client_id: number, channel_id: number): Promise; - /* playlist permissions */ - private onPlaylistPermList(json: any[]); - private execute_playlist_permission_request(request: permissions.PermissionRequestKeys); - requestPlaylistPermissions(playlist_id: number): Promise; - /* playlist client permissions */ - private onPlaylistClientPermList(json: any[]); - private execute_playlist_client_permission_request(request: permissions.PermissionRequestKeys); - requestPlaylistClientPermissions(playlist_id: number, client_database_id: number): Promise; - private readonly criteria_equal; - private execute_permission_request(list: RequestLists, criteria: permissions.PermissionRequestKeys, execute: (criteria: permissions.PermissionRequestKeys) => any): Promise; - private fullfill_permission_request(list: RequestLists, criteria: permissions.PermissionRequestKeys, status: "success" | "error", result: any); - find_permission(...permissions: string[]): Promise; - neededPermission(key: number | string | PermissionType | PermissionInfo): NeededPermissionValue; - groupedPermissions(): GroupedPermissions[]; - /** - * Generates an enum with all know permission types, used for the enum above - */ - export_permission_types(); -} - -/* File: D:\TeaSpeak\web\shared\js\PPTListener.ts */ -declare enum KeyCode { - KEY_CANCEL = 3, - KEY_HELP = 6, - KEY_BACK_SPACE = 8, - KEY_TAB = 9, - KEY_CLEAR = 12, - KEY_RETURN = 13, - KEY_ENTER = 14, - KEY_SHIFT = 16, - KEY_CONTROL = 17, - KEY_ALT = 18, - KEY_PAUSE = 19, - KEY_CAPS_LOCK = 20, - KEY_ESCAPE = 27, - KEY_SPACE = 32, - KEY_PAGE_UP = 33, - KEY_PAGE_DOWN = 34, - KEY_END = 35, - KEY_HOME = 36, - KEY_LEFT = 37, - KEY_UP = 38, - KEY_RIGHT = 39, - KEY_DOWN = 40, - KEY_PRINTSCREEN = 44, - KEY_INSERT = 45, - KEY_DELETE = 46, - KEY_0 = 48, - KEY_1 = 49, - KEY_2 = 50, - KEY_3 = 51, - KEY_4 = 52, - KEY_5 = 53, - KEY_6 = 54, - KEY_7 = 55, - KEY_8 = 56, - KEY_9 = 57, - KEY_SEMICOLON = 59, - KEY_EQUALS = 61, - KEY_A = 65, - KEY_B = 66, - KEY_C = 67, - KEY_D = 68, - KEY_E = 69, - KEY_F = 70, - KEY_G = 71, - KEY_H = 72, - KEY_I = 73, - KEY_J = 74, - KEY_K = 75, - KEY_L = 76, - KEY_M = 77, - KEY_N = 78, - KEY_O = 79, - KEY_P = 80, - KEY_Q = 81, - KEY_R = 82, - KEY_S = 83, - KEY_T = 84, - KEY_U = 85, - KEY_V = 86, - KEY_W = 87, - KEY_X = 88, - KEY_Y = 89, - KEY_Z = 90, - KEY_LEFT_CMD = 91, - KEY_RIGHT_CMD = 93, - KEY_CONTEXT_MENU = 93, - KEY_NUMPAD0 = 96, - KEY_NUMPAD1 = 97, - KEY_NUMPAD2 = 98, - KEY_NUMPAD3 = 99, - KEY_NUMPAD4 = 100, - KEY_NUMPAD5 = 101, - KEY_NUMPAD6 = 102, - KEY_NUMPAD7 = 103, - KEY_NUMPAD8 = 104, - KEY_NUMPAD9 = 105, - KEY_MULTIPLY = 106, - KEY_ADD = 107, - KEY_SEPARATOR = 108, - KEY_SUBTRACT = 109, - KEY_DECIMAL = 110, - KEY_DIVIDE = 111, - KEY_F1 = 112, - KEY_F2 = 113, - KEY_F3 = 114, - KEY_F4 = 115, - KEY_F5 = 116, - KEY_F6 = 117, - KEY_F7 = 118, - KEY_F8 = 119, - KEY_F9 = 120, - KEY_F10 = 121, - KEY_F11 = 122, - KEY_F12 = 123, - KEY_F13 = 124, - KEY_F14 = 125, - KEY_F15 = 126, - KEY_F16 = 127, - KEY_F17 = 128, - KEY_F18 = 129, - KEY_F19 = 130, - KEY_F20 = 131, - KEY_F21 = 132, - KEY_F22 = 133, - KEY_F23 = 134, - KEY_F24 = 135, - KEY_NUM_LOCK = 144, - KEY_SCROLL_LOCK = 145, - KEY_COMMA = 188, - KEY_PERIOD = 190, - KEY_SLASH = 191, - KEY_BACK_QUOTE = 192, - KEY_OPEN_BRACKET = 219, - KEY_BACK_SLASH = 220, - KEY_CLOSE_BRACKET = 221, - KEY_QUOTE = 222, - KEY_META = 224 -} -declare namespace ppt { - export enum EventType { - KEY_PRESS, - KEY_RELEASE, - KEY_TYPED - } - export enum SpecialKey { - CTRL, - WINDOWS, - SHIFT, - ALT - } - export interface KeyDescriptor { - key_code: string; - key_ctrl: boolean; - key_windows: boolean; - key_shift: boolean; - key_alt: boolean; - } - export interface KeyEvent extends KeyDescriptor { - readonly type: EventType; - readonly key: string; - } - export interface KeyHook extends KeyDescriptor { - cancel: boolean; - callback_press: () => any; - callback_release: () => any; - } - export function key_description(key: KeyDescriptor); -} - -/* File: D:\TeaSpeak\web\shared\js\profiles\ConnectionProfile.ts */ -declare namespace profiles { - export class ConnectionProfile { - id: string; - profile_name: string; - default_username: string; - default_password: string; - selected_identity_type: string; - identities: { - [key: string]: identities.Identity; - }; - constructor(id: string); - connect_username(): string; - selected_identity(current_type?: identities.IdentitifyType): identities.Identity; - selected_type?(): identities.IdentitifyType; - set_identity(type: identities.IdentitifyType, identity: identities.Identity); - spawn_identity_handshake_handler?(connection: connection.AbstractServerConnection): connection.HandshakeIdentityHandler; - encode?(): string; - valid(): boolean; - } - export function load(): Promise; - export function create_new_profile(name: string, id?: string): ConnectionProfile; - export function save(); - export function mark_need_save(); - export function requires_save(): boolean; - export function profiles(): ConnectionProfile[]; - export function find_profile(id: string): ConnectionProfile | undefined; - export function find_profile_by_name(name: string): ConnectionProfile | undefined; - export function default_profile(): ConnectionProfile; - export function set_default_profile(profile: ConnectionProfile); - export function delete_profile(profile: ConnectionProfile); -} - -/* File: D:\TeaSpeak\web\shared\js\profiles\identities\NameIdentity.ts */ -declare namespace profiles.identities { - export class NameHandshakeHandler extends AbstractHandshakeIdentityHandler { - readonly identity: NameIdentity; - handler: HandshakeCommandHandler; - constructor(connection: connection.AbstractServerConnection, identity: profiles.identities.NameIdentity); - start_handshake(); - protected trigger_fail(message: string); - protected trigger_success(); - } - export class NameIdentity implements Identity { - private _name: string; - constructor(name?: string); - set_name(name: string); - name(): string; - fallback_name(): string | undefined; - uid(): string; - type(): IdentitifyType; - valid(): boolean; - decode(data): Promise; - encode?(): string; - spawn_identity_handshake_handler(connection: connection.AbstractServerConnection): connection.HandshakeIdentityHandler; - } -} - -/* File: D:\TeaSpeak\web\shared\js\profiles\identities\TeaForumIdentity.ts */ -declare namespace profiles.identities { - export class TeaForumHandshakeHandler extends AbstractHandshakeIdentityHandler { - readonly identity: TeaForumIdentity; - handler: HandshakeCommandHandler; - constructor(connection: connection.AbstractServerConnection, identity: profiles.identities.TeaForumIdentity); - start_handshake(); - private handle_proof(json); - protected trigger_fail(message: string); - protected trigger_success(); - } - export class TeaForumIdentity implements Identity { - private readonly identity_data: forum.Data; - valid(): boolean; - constructor(data: forum.Data); - data(): forum.Data; - decode(data): Promise; - encode(): string; - spawn_identity_handshake_handler(connection: connection.AbstractServerConnection): connection.HandshakeIdentityHandler; - fallback_name(): string | undefined; - type(): profiles.identities.IdentitifyType; - uid(): string; - } - export function set_static_identity(identity: TeaForumIdentity); - export function update_forum(); - export function valid_static_forum_identity(): boolean; - export function static_forum_identity(): TeaForumIdentity | undefined; -} - -/* File: D:\TeaSpeak\web\shared\js\profiles\identities\TeamSpeakIdentity.ts */ -declare namespace profiles.identities { - export namespace CryptoHelper { - export function base64_url_encode(str); - export function base64_url_decode(str: string, pad?: boolean); - export function arraybuffer_to_string(buf); - export function export_ecc_key(crypto_key: CryptoKey, public_key: boolean): Promise; - export function decrypt_ts_identity(buffer: Uint8Array): Promise; - export function encrypt_ts_identity(buffer: Uint8Array): Promise; - /** - * @param buffer base64 encoded ASN.1 string - */ - export function decode_tomcrypt_key(buffer: string); - } - export class TeaSpeakHandshakeHandler extends AbstractHandshakeIdentityHandler { - identity: TeaSpeakIdentity; - handler: HandshakeCommandHandler; - constructor(connection: connection.AbstractServerConnection, identity: TeaSpeakIdentity); - start_handshake(); - private handle_proof(json); - protected trigger_fail(message: string); - protected trigger_success(); - } - export class IdentityPOWWorker { - private _worker: Worker; - private _current_hash: string; - private _best_level: number; - initialize(key: string); - mine(hash: string, iterations: number, target: number, timeout?: number): Promise; - current_hash(): string; - current_level(): number; - finalize(timeout?: number); - private handle_message(message: any); - } - export class TeaSpeakIdentity implements Identity { - static generate_new(): Promise; - static import_ts(ts_string: string, ini?: boolean): Promise; - hash_number: string; - private_key: string; - _name: string; - public_key: string; - private _initialized: boolean; - private _crypto_key: CryptoKey; - private _crypto_key_sign: CryptoKey; - private _unique_id: string; - constructor(private_key?: string, hash?: string, name?: string, initialize?: boolean); - fallback_name(): string | undefined; - uid(): string; - type(): IdentitifyType; - valid(): boolean; - decode(data: string): Promise; - encode?(): string; - level(): Promise; - /** - * @param {string} a - * @param {string} b - * @description b must be smaller (in bytes) then a - */ - private string_add(a: string, b: string); - improve_level_for(time: number, threads: number): Promise; - improve_level(target: number, threads: number, active_callback: () => boolean, callback_level?: (current: number) => any, callback_status?: (hash_rate: number) => any): Promise; - private initialize(); - export_ts(ini?: boolean): Promise; - sign_message(message: string, hash?: string): Promise; - spawn_identity_handshake_handler(connection: connection.AbstractServerConnection): connection.HandshakeIdentityHandler; - } -} - -/* File: D:\TeaSpeak\web\shared\js\profiles\identities\teaspeak-forum.ts */ -declare interface Window { - grecaptcha: GReCaptcha; -} -declare interface GReCaptcha { - render(container: string | HTMLElement, parameters: { - sitekey: string; - theme?: "dark" | "light"; - size?: "compact" | "normal"; - tabindex?: number; - callback?: (token: string) => any; - "expired-callback"?: () => any; - "error-callback"?: (error: any) => any; - }): string; /* widget_id */ - reset(widget_id?: string); -} -declare namespace forum { - export namespace gcaptcha { - export function initialize(): Promise; - export function spawn(container: JQuery, key: string, callback_data: (token: string) => any): Promise; - } - export class Data { - readonly auth_key: string; - readonly raw: string; - readonly sign: string; - parsed: { - user_id: number; - user_name: string; - data_age: number; - user_group_id: number; - is_staff: boolean; - user_groups: number[]; - }; - constructor(auth: string, raw: string, sign: string); - data_json(): string; - data_sign(): string; - name(): string; - user_id(); - user_group(); - is_stuff(): boolean; - is_premium(): boolean; - data_age(): Date; - is_expired(): boolean; - should_renew(): boolean; - } - export function logged_in(): boolean; - export function data(): Data; - export interface LoginResult { - status: "success" | "captcha" | "error"; - error_message?: string; - captcha?: { - type: "gre-captcha" | "unknown"; - data: any; /* in case of gre-captcha it would be the side key */ - }; - } - export function login(username: string, password: string, captcha?: any): Promise; - export function renew_data(): Promise<"success" | "login-required">; - export function logout(): Promise; -} - -/* File: D:\TeaSpeak\web\shared\js\profiles\Identity.ts */ -declare namespace profiles.identities { - export enum IdentitifyType { - TEAFORO, - TEAMSPEAK, - NICKNAME - } - export interface Identity { - fallback_name(): string | undefined; - uid(): string; - type(): IdentitifyType; - valid(): boolean; - encode?(): string; - decode(data: string): Promise; - spawn_identity_handshake_handler(connection: connection.AbstractServerConnection): connection.HandshakeIdentityHandler; - } - export function decode_identity(type: IdentitifyType, data: string): Promise; - export function create_identity(type: IdentitifyType); - export class HandshakeCommandHandler extends connection.AbstractCommandHandler { - readonly handle: T; - constructor(connection: connection.AbstractServerConnection, handle: T); - handle_command(command: connection.ServerCommand): boolean; - } - export abstract class AbstractHandshakeIdentityHandler implements connection.HandshakeIdentityHandler { - connection: connection.AbstractServerConnection; - protected callbacks: ((success: boolean, message?: string) => any)[]; - protected constructor(connection: connection.AbstractServerConnection); - register_callback(callback: (success: boolean, message?: string) => any); - abstract start_handshake(); - protected trigger_success(); - protected trigger_fail(message: string); - } -} - -/* File: D:\TeaSpeak\web\shared\js\proto.ts */ -declare interface Array { - remove(elem?: T): boolean; - last?(): T; - pop_front(): T | undefined; -} -declare interface JSON { - map_to(object: T, json: any, variables?: string | string[], validator?: (map_field: string, map_value: string) => boolean, variable_direction?: number): number; - map_field_to(object: T, value: any, field: string): boolean; -} -declare type JQueryScrollType = "height" | "width"; -declare interface JQuery { - render(values?: any): string; - renderTag(values?: any): JQuery; - hasScrollBar(direction?: JQueryScrollType): boolean; - visible_height(): number; - visible_width(): number; - /* bootstrap */ - alert(): JQuery; - modal(properties: any): this; - bootstrapMaterialDesign(): this; - /* first element which matches the selector, could be the element itself or a parent */ - firstParent(selector: string): JQuery; -} -declare interface JQueryStatic { - spawn(tagName: K): JQuery; - views: any; -} -declare interface String { - format(...fmt): string; - format(arguments: string[]): string; -} -declare function concatenate(resultConstructor, ...arrays); -declare function formatDate(secs: number): string; -declare function calculate_width(text: string): number; -declare interface Twemoji { - parse(message: string): string; -} -declare let twemoji: Twemoji; -declare interface HighlightJS { - listLanguages(): string[]; - getLanguage(name: string): any | undefined; - highlight(language: string, text: string, ignore_illegals?: boolean): HighlightJSResult; - highlightAuto(text: string): HighlightJSResult; -} -declare interface HighlightJSResult { - language: string; - relevance: number; - value: string; - second_best?: any; -} -declare interface DOMPurify { - sanitize(html: string, config?: { - ADD_ATTR?: string[]; - ADD_TAGS?: string[]; - }): string; -} -declare let DOMPurify: DOMPurify; -declare let remarkable: typeof window.remarkable; -declare class webkitAudioContext extends AudioContext { -} -declare class webkitOfflineAudioContext extends OfflineAudioContext { -} -declare interface Window { - readonly webkitAudioContext: typeof webkitAudioContext; - readonly AudioContext: typeof webkitAudioContext; - readonly OfflineAudioContext: typeof OfflineAudioContext; - readonly webkitOfflineAudioContext: typeof webkitOfflineAudioContext; - readonly RTCPeerConnection: typeof RTCPeerConnection; - readonly Pointer_stringify: any; - readonly jsrender: any; - twemoji: Twemoji; - hljs: HighlightJS; - remarkable: any; - require(id: string): any; -} -declare interface Navigator { - browserSpecs: { - name: string; - version: string; - }; - mozGetUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void; - webkitGetUserMedia(constraints: MediaStreamConstraints, successCallback: NavigatorUserMediaSuccessCallback, errorCallback: NavigatorUserMediaErrorCallback): void; -} - -/* File: D:\TeaSpeak\web\shared\js\settings.ts */ -declare interface SettingsKey { - key: string; - fallback_keys?: string | string[]; - fallback_imports?: { - [key: string]: (value: string) => T; - }; - description?: string; - default_value?: T; - require_restart?: boolean; -} -declare class SettingsBase { - protected static readonly UPDATE_DIRECT: boolean; - protected static transformStO?(input?: string, _default?: T, default_type?: string): T; - protected static transformOtS?(input: T): string; - protected static resolveKey(key: SettingsKey, _default: T, resolver: (key: string) => string | boolean, default_type?: string): T; - protected static keyify(key: string | SettingsKey): SettingsKey; -} -declare class StaticSettings extends SettingsBase { - private static _instance: StaticSettings; - // @ts-ignore - static get instance(): StaticSettings; - protected _handle: StaticSettings; - protected _staticPropsTag: JQuery; - protected constructor(_reserved?); - private initializeStatic(); - static?(key: string | SettingsKey, _default?: T, default_type?: string): T; - deleteStatic(key: string | SettingsKey); -} -declare class Settings extends StaticSettings { - static readonly KEY_DISABLE_COSMETIC_SLOWDOWN: SettingsKey; - static readonly KEY_DISABLE_CONTEXT_MENU: SettingsKey; - static readonly KEY_DISABLE_GLOBAL_CONTEXT_MENU: SettingsKey; - static readonly KEY_DISABLE_UNLOAD_DIALOG: SettingsKey; - static readonly KEY_DISABLE_VOICE: SettingsKey; - static readonly KEY_DISABLE_MULTI_SESSION: SettingsKey; - static readonly KEY_LOAD_DUMMY_ERROR: SettingsKey; - /* Control bar */ - static readonly KEY_CONTROL_MUTE_INPUT: SettingsKey; - static readonly KEY_CONTROL_MUTE_OUTPUT: SettingsKey; - static readonly KEY_CONTROL_SHOW_QUERIES: SettingsKey; - static readonly KEY_CONTROL_CHANNEL_SUBSCRIBE_ALL: SettingsKey; - /* Connect parameters */ - static readonly KEY_FLAG_CONNECT_DEFAULT: SettingsKey; - static readonly KEY_CONNECT_ADDRESS: SettingsKey; - static readonly KEY_CONNECT_PROFILE: SettingsKey; - static readonly KEY_CONNECT_USERNAME: SettingsKey; - static readonly KEY_CONNECT_PASSWORD: SettingsKey; - static readonly KEY_FLAG_CONNECT_PASSWORD: SettingsKey; - static readonly KEY_CONNECT_HISTORY: SettingsKey; - static readonly KEY_CONNECT_NO_DNSPROXY: SettingsKey; - static readonly KEY_CERTIFICATE_CALLBACK: SettingsKey; - /* sounds */ - static readonly KEY_SOUND_MASTER: SettingsKey; - static readonly KEY_SOUND_MASTER_SOUNDS: SettingsKey; - static readonly KEY_CHAT_FIXED_TIMESTAMPS: SettingsKey; - static readonly KEY_CHAT_COLLOQUIAL_TIMESTAMPS: SettingsKey; - static readonly KEY_CHAT_COLORED_EMOJIES: SettingsKey; - static readonly KEY_CHAT_TAG_URLS: SettingsKey; - static readonly KEY_CHAT_ENABLE_MARKDOWN: SettingsKey; - static readonly KEY_CHAT_ENABLE_BBCODE: SettingsKey; - static readonly KEY_SWITCH_INSTANT_CHAT: SettingsKey; - static readonly KEY_SWITCH_INSTANT_CLIENT: SettingsKey; - static readonly KEY_HOSTBANNER_BACKGROUND: SettingsKey; - static readonly KEY_CHANNEL_EDIT_ADVANCED: SettingsKey; - static readonly KEY_PERMISSIONS_SHOW_ALL: SettingsKey; - static readonly KEY_TEAFORO_URL: SettingsKey; - static readonly KEY_FONT_SIZE: SettingsKey; - static readonly KEY_ICON_SIZE: SettingsKey; - static readonly KEY_LAST_INVITE_LINK_TYPE: SettingsKey; - static readonly FN_INVITE_LINK_SETTING: (name: string) => SettingsKey; - static readonly FN_SERVER_CHANNEL_SUBSCRIBE_MODE: (channel_id: number) => SettingsKey; - static readonly FN_PROFILE_RECORD: (name: string) => SettingsKey; - static readonly KEYS; - static initialize(); - private cacheGlobal; - private saveWorker: NodeJS.Timer; - private updated: boolean; - constructor(); - static_global?(key: string | SettingsKey, _default?: T): T; - global?(key: string | SettingsKey, _default?: T): T; - changeGlobal(key: string | SettingsKey, value?: T); - save(); -} -declare class ServerSettings extends SettingsBase { - private cacheServer; - private _server_unique_id: string; - private _server_save_worker: NodeJS.Timer; - private _server_settings_updated: boolean; - private _destroyed; - constructor(); - destroy(); - server?(key: string | SettingsKey, _default?: T): T; - changeServer(key: string | SettingsKey, value?: T); - setServer(server_unique_id: string); - save(); -} -declare let settings: Settings; - -/* File: D:\TeaSpeak\web\shared\js\sound\Sounds.ts */ -declare enum Sound { - SOUND_TEST = "sound.test", - SOUND_EGG = "sound.egg", - AWAY_ACTIVATED = "away_activated", - AWAY_DEACTIVATED = "away_deactivated", - MICROPHONE_MUTED = "microphone.muted", - MICROPHONE_ACTIVATED = "microphone.activated", - SOUND_MUTED = "sound.muted", - SOUND_ACTIVATED = "sound.activated", - CONNECTION_CONNECTED = "connection.connected", - CONNECTION_DISCONNECTED = "connection.disconnected", - CONNECTION_BANNED = "connection.banned", - CONNECTION_DISCONNECTED_TIMEOUT = "connection.disconnected.timeout", - CONNECTION_REFUSED = "connection.refused", - SERVER_EDITED = "server.edited", - SERVER_EDITED_SELF = "server.edited.self", - SERVER_KICKED = "server.kicked", - CHANNEL_CREATED = "channel.created", - CHANNEL_MOVED = "channel.moved", - CHANNEL_EDITED = "channel.edited", - CHANNEL_EDITED_SELF = "channel.edited.self", - CHANNEL_DELETED = "channel.deleted", - CHANNEL_JOINED = "channel.joined", - CHANNEL_KICKED = "channel.kicked", - USER_MOVED = "user.moved", - USER_MOVED_SELF = "user.moved.self", - USER_POKED_SELF = "user.poked.self", - USER_BANNED = "user.banned", - USER_ENTERED = "user.joined", - USER_ENTERED_MOVED = "user.joined.moved", - USER_ENTERED_KICKED = "user.joined.kicked", - USER_ENTERED_CONNECT = "user.joined.connect", - USER_LEFT = "user.left", - USER_LEFT_MOVED = "user.left.moved", - USER_LEFT_KICKED_CHANNEL = "user.left.kicked.server", - USER_LEFT_KICKED_SERVER = "user.left.kicked.channel", - USER_LEFT_DISCONNECT = "user.left.disconnect", - USER_LEFT_BANNED = "user.left.banned", - USER_LEFT_TIMEOUT = "user.left.timeout", - ERROR_INSUFFICIENT_PERMISSIONS = "error.insufficient_permissions", - MESSAGE_SEND = "message.send", - MESSAGE_RECEIVED = "message.received", - GROUP_SERVER_ASSIGNED = "group.server.assigned", - GROUP_SERVER_REVOKED = "group.server.revoked", - GROUP_CHANNEL_CHANGED = "group.channel.changed", - GROUP_SERVER_ASSIGNED_SELF = "group.server.assigned.self", - GROUP_SERVER_REVOKED_SELF = "group.server.revoked.self", - GROUP_CHANNEL_CHANGED_SELF = "group.channel.changed.self" -} -declare namespace sound { - export interface SoundHandle { - key: string; - filename: string; - } - export interface SoundFile { - path: string; - volume?: number; - } - export function get_sound_volume(sound: Sound, default_volume?: number): number; - export function set_sound_volume(sound: Sound, volume: number); - export function get_master_volume(): number; - export function set_master_volume(volume: number); - export function overlap_activated(): boolean; - export function set_overlap_activated(flag: boolean); - export function ignore_output_muted(): boolean; - export function set_ignore_output_muted(flag: boolean); - export function reinitialisize_audio(); - export function save(); - export function initialize(): Promise; - export interface PlaybackOptions { - ignore_muted?: boolean; - ignore_overlap?: boolean; - default_volume?: number; - callback?: (flag: boolean) => any; - } - export function resolve_sound(sound: Sound): Promise; - export let manager: SoundManager; - export class SoundManager { - private readonly _handle: ConnectionHandler; - private _playing_sounds: { - [key: string]: number; - }; - constructor(handle: ConnectionHandler); - play(_sound: Sound, options?: PlaybackOptions); - } -} - -/* File: D:\TeaSpeak\web\shared\js\stats.ts */ -declare namespace stats { - export enum CloseCodes { - UNSET = 3000, - RECONNECT = 3001, - INTERNAL_ERROR = 3002, - BANNED = 3100 - } - export enum ConnectionState { - CONNECTING, - INITIALIZING, - CONNECTED, - UNSET - } - export class SessionConfig { - /* - * All collected statistics will only be cached by the stats server. - * No data will be saved. - */ - volatile_collection_only?: boolean; - /* - * Anonymize all IP addresses which will be provided while the stats collection. - * This option is quite useless when volatile_collection_only is active. - */ - anonymize_ip_addresses?: boolean; - } - export class Config extends SessionConfig { - verbose?: boolean; - reconnect_interval?: number; - } - export interface UserCountData { - online_users: number; - unique_online_users: number; - } - export type UserCountListener = (data: UserCountData) => any; - export function initialize(config: Config); - export function register_user_count_listener(listener: UserCountListener); - export function all_user_count_listener(): UserCountListener[]; - export function deregister_user_count_listener(listener: UserCountListener); - namespace connection { - export let connection_state: ConnectionState; - export function start_connection(); - export function close_connection(); - export function cancel_reconnect(); - namespace handler { } - } -} - -/* File: D:\TeaSpeak\web\shared\js\ui\channel.ts */ -declare enum ChannelType { - PERMANENT, - SEMI_PERMANENT, - TEMPORARY -} -declare namespace ChannelType { - export function normalize(mode: ChannelType); -} -declare enum ChannelSubscribeMode { - SUBSCRIBED, - UNSUBSCRIBED, - INHERITED -} -declare class ChannelProperties { - channel_order: number; - channel_name: string; - channel_name_phonetic: string; - channel_topic: string; - channel_password: string; - channel_codec: number; - channel_codec_quality: number; - channel_codec_is_unencrypted: boolean; - channel_maxclients: number; - channel_maxfamilyclients: number; - channel_needed_talk_power: number; - channel_flag_permanent: boolean; - channel_flag_semi_permanent: boolean; - channel_flag_default: boolean; - channel_flag_password: boolean; - channel_flag_maxclients_unlimited: boolean; - channel_flag_maxfamilyclients_inherited: boolean; - channel_flag_maxfamilyclients_unlimited: boolean; - channel_icon_id: number; - channel_delete_delay: number; - //Only after request - channel_description: string; - channel_flag_conversation_private: boolean; - channel_conversation_history_length: number; -} -declare class ChannelEntry { - channelTree: ChannelTree; - channelId: number; - parent?: ChannelEntry; - properties: ChannelProperties; - channel_previous?: ChannelEntry; - channel_next?: ChannelEntry; - private _channel_name_alignment: string; - private _channel_name_formatted: string; - private _family_index: number; - //HTML DOM elements - private _tag_root: JQuery; - private _tag_siblings: JQuery; - private _tag_clients: JQuery; - private _tag_channel: JQuery; - private _destroyed; - private _cachedPassword: string; - private _cached_channel_description: string; - private _cached_channel_description_promise: Promise; - private _cached_channel_description_promise_resolve: any; - private _cached_channel_description_promise_reject: any; - private _flag_subscribed: boolean; - private _subscribe_mode: ChannelSubscribeMode; - constructor(channelId, channelName, parent?); - destroy(); - channelName(); - formattedChannelName(); - getChannelDescription(): Promise; - parent_channel(); - hasParent(); - getChannelId(); - children(deep?): ChannelEntry[]; - clients(deep?): ClientEntry[]; - clients_ordered(): ClientEntry[]; - update_family_index(enforce?: boolean); - calculate_family_index(enforce_recalculate?: boolean): number; - private initializeTag(); - rootTag(): JQuery; - channelTag(): JQuery; - siblingTag(): JQuery; - clientTag(): JQuery; - private _reorder_timer: number; - reorderClients(sync?: boolean); - initializeListener(); - showContextMenu(x: number, y: number, on_close?: () => void); - handle_frame_resized(); - private static NAME_ALIGNMENTS: string[]; - private __updateChannelName(); - recalculate_repetitive_name(); - updateVariables(...variables: { - key: string; - value: string; - }[]); - updateChannelTypeIcon(); - generate_bbcode(); - generate_tag(braces?: boolean): JQuery; - channelType(): ChannelType; - joinChannel(); - cached_password(); - subscribe(): Promise; - unsubscribe(inherited_subscription_mode?: boolean): Promise; - // @ts-ignore - get flag_subscribed(): boolean; - // @ts-ignore - set flag_subscribed(flag: boolean); - // @ts-ignore - get subscribe_mode(): ChannelSubscribeMode; - // @ts-ignore - set subscribe_mode(mode: ChannelSubscribeMode); - // @ts-ignore - set flag_text_unread(flag: boolean); - log_data(): log.server.base.Channel; -} - -/* File: D:\TeaSpeak\web\shared\js\ui\client_move.ts */ -declare class ClientMover { - static readonly listener_root; - static readonly move_element; - readonly channel_tree: ChannelTree; - selected_client: ClientEntry | ClientEntry[]; - hovered_channel: HTMLDivElement; - callback: (channel?: ChannelEntry) => any; - enabled: boolean; - private _bound_finish; - private _bound_move; - private _active: boolean; - private origin_point: { - x: number; - y: number; - }; - constructor(tree: ChannelTree); - is_active(); - private hover_text(); - private bbcode_text(); - activate(client: ClientEntry | ClientEntry[], callback: (channel?: ChannelEntry) => any, event: any); - private move_listener(event); - private finish_listener(event); - deactivate(); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\client.ts */ -declare enum ClientType { - CLIENT_VOICE, - CLIENT_QUERY, - CLIENT_INTERNAL, - CLIENT_WEB, - CLIENT_MUSIC, - CLIENT_UNDEFINED -} -declare class ClientProperties { - client_type: ClientType; - client_type_exact: ClientType; - client_database_id: number; - client_version: string; - client_platform: string; - client_nickname: string; - client_unique_identifier: string; - client_description: string; - client_servergroups: string; - client_channel_group_id: number; - client_lastconnected: number; - client_created: number; - client_totalconnections: number; - client_flag_avatar: string; - client_icon_id: number; - client_away_message: string; - client_away: boolean; - client_country: string; - client_input_hardware: boolean; - client_output_hardware: boolean; - client_input_muted: boolean; - client_output_muted: boolean; - client_is_channel_commander: boolean; - client_teaforo_id: number; - client_teaforo_name: string; - client_teaforo_flags: number; - /* not updated in view! */ - client_month_bytes_uploaded: number; - client_month_bytes_downloaded: number; - client_total_bytes_uploaded: number; - client_total_bytes_downloaded: number; - client_talk_power: number; - client_is_priority_speaker: boolean; -} -declare class ClientConnectionInfo { - connection_bandwidth_received_last_minute_control: number; - connection_bandwidth_received_last_minute_keepalive: number; - connection_bandwidth_received_last_minute_speech: number; - connection_bandwidth_received_last_second_control: number; - connection_bandwidth_received_last_second_keepalive: number; - connection_bandwidth_received_last_second_speech: number; - connection_bandwidth_sent_last_minute_control: number; - connection_bandwidth_sent_last_minute_keepalive: number; - connection_bandwidth_sent_last_minute_speech: number; - connection_bandwidth_sent_last_second_control: number; - connection_bandwidth_sent_last_second_keepalive: number; - connection_bandwidth_sent_last_second_speech: number; - connection_bytes_received_control: number; - connection_bytes_received_keepalive: number; - connection_bytes_received_speech: number; - connection_bytes_sent_control: number; - connection_bytes_sent_keepalive: number; - connection_bytes_sent_speech: number; - connection_packets_received_control: number; - connection_packets_received_keepalive: number; - connection_packets_received_speech: number; - connection_packets_sent_control: number; - connection_packets_sent_keepalive: number; - connection_packets_sent_speech: number; - connection_ping: number; - connection_ping_deviation: number; - connection_server2client_packetloss_control: number; - connection_server2client_packetloss_keepalive: number; - connection_server2client_packetloss_speech: number; - connection_server2client_packetloss_total: number; - connection_client2server_packetloss_speech: number; - connection_client2server_packetloss_keepalive: number; - connection_client2server_packetloss_control: number; - connection_client2server_packetloss_total: number; - connection_filetransfer_bandwidth_sent: number; - connection_filetransfer_bandwidth_received: number; - connection_connected_time: number; - connection_idle_time: number; - connection_client_ip: string | undefined; - connection_client_port: number; -} -declare class ClientEntry { - readonly events: events.Registry; - protected _clientId: number; - protected _channel: ChannelEntry; - protected _tag: JQuery; - protected _properties: ClientProperties; - protected lastVariableUpdate: number; - protected _speaking: boolean; - protected _listener_initialized: boolean; - protected _audio_handle: connection.voice.VoiceClient; - protected _audio_volume: number; - protected _audio_muted: boolean; - private _info_variables_promise: Promise; - private _info_variables_promise_timestamp: number; - private _info_connection_promise: Promise; - private _info_connection_promise_timestamp: number; - private _info_connection_promise_resolve: any; - private _info_connection_promise_reject: any; - channelTree: ChannelTree; - constructor(clientId: number, clientName, properties?: ClientProperties); - destroy(); - tree_unregistered(); - set_audio_handle(handle: connection.voice.VoiceClient); - get_audio_handle(): connection.voice.VoiceClient; - // @ts-ignore - get properties(): ClientProperties; - currentChannel(): ChannelEntry; - clientNickName(); - clientUid(); - clientId(); - is_muted(); - set_muted(flag: boolean, update_icon: boolean, force?: boolean); - protected initializeListener(); - protected contextmenu_info(): contextmenu.MenuEntry[]; - protected assignment_context(): contextmenu.MenuEntry[]; - open_assignment_modal(); - open_text_chat(); - showContextMenu(x: number, y: number, on_close?: () => void); - // @ts-ignore - get tag(): JQuery; - static bbcodeTag(id: number, name: string, uid: string): string; - static chatTag(id: number, name: string, uid: string, braces?: boolean): JQuery; - create_bbcode(): string; - createChatTag(braces?: boolean): JQuery; - // @ts-ignore - set speaking(flag); - updateClientStatusIcons(); - updateClientSpeakIcon(); - updateAwayMessage(); - updateVariables(...variables: { - key: string; - value: string; - }[]); - update_displayed_client_groups(); - updateClientVariables(force_update?: boolean): Promise; - updateClientIcon(); - updateGroupIcon(group: Group); - update_group_icon_order(); - assignedServerGroupIds(): number[]; - assignedChannelGroup(): number; - groupAssigned(group: Group): boolean; - onDelete(); - calculateOnlineTime(): number; - avatarId?(): string; - update_family_index(); - log_data(): log.server.base.Client; - /* max 1s ago, so we could update every second */ - request_connection_info(): Promise; - set_connection_info(info: ClientConnectionInfo); - // @ts-ignore - set flag_text_unread(flag: boolean); -} -declare class LocalClientEntry extends ClientEntry { - handle: ConnectionHandler; - private renaming: boolean; - constructor(handle: ConnectionHandler); - showContextMenu(x: number, y: number, on_close?: () => void): void; - initializeListener(): void; - openRename(): void; -} -declare class MusicClientProperties extends ClientProperties { - player_state: number; - player_volume: number; - client_playlist_id: number; - client_disabled: boolean; - client_flag_notify_song_change: boolean; - client_bot_type: number; - client_uptime_mode: number; -} -declare class SongInfo { - song_id: number; - song_url: string; - song_invoker: number; - song_loaded: boolean; - /* only if song_loaded = true */ - song_title: string; - song_description: string; - song_thumbnail: string; - song_length: number; -} -declare class MusicClientPlayerInfo extends SongInfo { - bot_id: number; - player_state: number; - player_buffered_index: number; - player_replay_index: number; - player_max_index: number; - player_seekable: boolean; - player_title: string; - player_description: string; -} -declare class MusicClientEntry extends ClientEntry { - private _info_promise: Promise; - private _info_promise_age: number; - private _info_promise_resolve: any; - private _info_promise_reject: any; - constructor(clientId, clientName); - destroy(); - // @ts-ignore - get properties(): MusicClientProperties; - showContextMenu(x: number, y: number, on_close?: () => void): void; - initializeListener(): void; - handlePlayerInfo(json); - requestPlayerInfo(max_age?: number): Promise; -} - -/* File: D:\TeaSpeak\web\shared\js\ui\elements\context_divider.ts */ -declare interface JQuery { - dividerfy(): this; -} - -/* File: D:\TeaSpeak\web\shared\js\ui\elements\context_menu.ts */ -declare namespace contextmenu { - export interface MenuEntry { - callback?: () => void; - type: MenuEntryType; - name: (() => string) | string; - icon_class?: string; - icon_path?: string; - disabled?: boolean; - visible?: boolean; - checkbox_checked?: boolean; - invalidPermission?: boolean; - sub_menu?: MenuEntry[]; - } - export enum MenuEntryType { - CLOSE, - ENTRY, - CHECKBOX, - HR, - SUB_MENU - } - export class Entry { - static HR(); - static CLOSE(callback: () => void); - } - export interface ContextMenuProvider { - despawn_context_menu(); - spawn_context_menu(x: number, y: number, ...entries: MenuEntry[]); - initialize(); - finalize(); - html_format_enabled(): boolean; - } - export function spawn_context_menu(x: number, y: number, ...entries: MenuEntry[]); - export function despawn_context_menu(); - export function get_provider(): ContextMenuProvider; - export function set_provider(_provider: ContextMenuProvider); -} -declare class HTMLContextMenuProvider implements contextmenu.ContextMenuProvider { - private _global_click_listener: (event) => any; - private _context_menu: JQuery; - private _close_callbacks: (() => any)[]; - private _visible; - despawn_context_menu(); - finalize(); - initialize(); - private on_global_click(event); - private generate_tag(entry: contextmenu.MenuEntry): JQuery; - spawn_context_menu(x: number, y: number, ...entries: contextmenu.MenuEntry[]); - html_format_enabled(): boolean; -} - -/* File: D:\TeaSpeak\web\shared\js\ui\elements\modal.ts */ -declare enum ElementType { - HEADER, - BODY, - FOOTER -} -declare type BodyCreator = (() => JQuery | JQuery[] | string) | string | JQuery | JQuery[]; -declare const ModalFunctions; -declare class ModalProperties { - template?: string; - header: BodyCreator; - body: BodyCreator; - footer: BodyCreator; - closeListener: (() => void) | (() => void)[]; - registerCloseListener(listener: () => void): this; - width: number | string; - min_width?: number | string; - height: number | string; - closeable: boolean; - triggerClose(); - template_properties?: any; - trigger_tab: boolean; - full_size?: boolean; -} -declare namespace modal { - export function initialize_modals(); -} -declare let _global_modal_count; -declare let _global_modal_last: HTMLElement; -declare let _global_modal_last_time: number; -declare class Modal { - private _htmlTag: JQuery; - properties: ModalProperties; - shown: boolean; - open_listener: (() => any)[]; - close_listener: (() => any)[]; - close_elements: JQuery; - constructor(props: ModalProperties); - // @ts-ignore - get htmlTag(): JQuery; - private _create(); - open(); - close(); - set_closeable(flag: boolean); -} -declare function createModal(data: ModalProperties | any): Modal; -declare class InputModalProperties extends ModalProperties { - maxLength?: number; - field_title?: string; - field_label?: string; - field_placeholder?: string; - error_message?: string; -} -declare function createInputModal(headMessage: BodyCreator, question: BodyCreator, validator: (input: string) => boolean, callback: (flag: boolean | string) => void, props?: InputModalProperties | any): Modal; -declare function createErrorModal(header: BodyCreator, message: BodyCreator, props?: ModalProperties | any); -declare function createInfoModal(header: BodyCreator, message: BodyCreator, props?: ModalProperties | any); -declare interface ModalElements { - header?: BodyCreator; - body?: BodyCreator; - footer?: BodyCreator; -} -declare interface JQuery { - modalize(entry_callback?: (header: JQuery, body: JQuery, footer: JQuery) => ModalElements | void, properties?: ModalProperties | any): Modal; -} - -/* File: D:\TeaSpeak\web\shared\js\ui\elements\net_graph.ts */ -declare namespace net.graph { - export type Entry = { - timestamp: number; - upload?: number; - download?: number; - highlight?: boolean; - }; - export type Style = { - background_color: string; - separator_color: string; - separator_count: number; - separator_width: number; - upload: { - fill: string; - stroke: string; - strike_width: number; - }; - download: { - fill: string; - stroke: string; - strike_width: number; - }; - }; - export type TimeSpan = { - origin: { - begin: number; - end: number; - time: number; - }; - target: { - begin: number; - end: number; - time: number; - }; - }; - /* Great explanation of Bezier curves: http://en.wikipedia.org/wiki/Bezier_curve#Quadratic_curves - * - * Assuming A was the last point in the line plotted and B is the new point, - * we draw a curve with control points P and Q as below. - * - * A---P - * | - * | - * | - * Q---B - * - * Importantly, A and P are at the same y coordinate, as are B and Q. This is - * so adjacent curves appear to flow as one. - */ - export class Graph { - private static _loops: (() => any)[]; - readonly canvas: HTMLCanvasElement; - public style: Style; - private _canvas_context: CanvasRenderingContext2D; - private _entries: Entry[]; - private _entry_max; - private _max_space; - private _max_gap; - private _listener_mouse_move; - private _listener_mouse_out; - private _animate_loop; - _time_span: TimeSpan; - private _detailed_shown; - callback_detailed_info: (upload: number, download: number, timestamp: number, event: MouseEvent) => any; - callback_detailed_hide: () => any; - constructor(canvas: HTMLCanvasElement); - initialize(); - terminate(); - max_gap_size(value?: number): number; - private recalculate_cache(time_span?: boolean); - insert_entry(entry: Entry); - insert_entries(entries: Entry[]); - resize(); - cleanup(); - calculate_time_span(): { - begin: number; - end: number; - }; - draw(); - private on_mouse_move(event: MouseEvent); - private on_mouse_leave(event: MouseEvent); - } -} - -/* File: D:\TeaSpeak\web\shared\js\ui\elements\slider.ts */ -declare interface SliderOptions { - min_value?: number; - max_value?: number; - initial_value?: number; - step?: number; - unit?: string; - value_field?: JQuery | JQuery[]; -} -declare interface Slider { - value(value?: number): number; -} -declare function sliderfy(slider: JQuery, options?: SliderOptions): Slider; - -/* File: D:\TeaSpeak\web\shared\js\ui\elements\tab.ts */ -declare interface JQuery { - asTabWidget(copy?: boolean): JQuery; - tabify(copy?: boolean): this; - changeElementType(type: string): JQuery; -} -declare var TabFunctions; - -/* File: D:\TeaSpeak\web\shared\js\ui\elements\tooltip.ts */ -declare function tooltip(entry: JQuery); -declare namespace tooltip { - export type Handle = { - show(); - is_shown(); - hide(); - update(); - }; - export function initialize(entry: JQuery, callbacks?: { - on_show?(tag: JQuery); - on_hide?(tag: JQuery); - }): Handle; -} - -/* File: D:\TeaSpeak\web\shared\js\ui\frames\chat_frame.ts */ -declare namespace chat { - export enum InfoFrameMode { - NONE = "none", - CHANNEL_CHAT = "channel_chat", - PRIVATE_CHAT = "private_chat", - CLIENT_INFO = "client_info", - MUSIC_BOT = "music_bot" - } - export class InfoFrame { - private readonly handle: Frame; - private _html_tag: JQuery; - private _mode: InfoFrameMode; - private _value_ping: JQuery; - private _ping_updater: number; - private _channel_text: ChannelEntry; - private _channel_voice: ChannelEntry; - private _button_conversation: HTMLElement; - private _button_bot_manage: JQuery; - private _button_song_add: JQuery; - constructor(handle: Frame); - html_tag(): JQuery; - destroy(); - private _build_html_tag(); - update_ping(); - update_channel_talk(); - update_channel_text(); - update_channel_client_count(channel: ChannelEntry); - private update_channel_limit(channel: ChannelEntry, tag: JQuery); - private update_server_limit(server: ServerEntry, tag: JQuery); - update_chat_counter(); - current_mode(): InfoFrameMode; - set_mode(mode: InfoFrameMode); - } - export enum FrameContent { - NONE, - PRIVATE_CHAT, - CHANNEL_CHAT, - CLIENT_INFO, - MUSIC_BOT - } - export class Frame { - readonly handle: ConnectionHandler; - private _info_frame: InfoFrame; - private _html_tag: JQuery; - private _container_info: JQuery; - private _container_chat: JQuery; - private _content_type: FrameContent; - private _conversations: PrivateConverations; - private _client_info: ClientInfo; - private _music_info: MusicInfo; - private _channel_conversations: channel.ConversationManager; - constructor(handle: ConnectionHandler); - html_tag(): JQuery; - info_frame(): InfoFrame; - content_type(): FrameContent; - destroy(); - private _build_html_tag(); - private_conversations(): PrivateConverations; - channel_conversations(): channel.ConversationManager; - client_info(): ClientInfo; - music_info(): MusicInfo; - private _clear(); - show_private_conversations(); - show_channel_conversations(); - show_client_info(client: ClientEntry); - show_music_player(client: MusicClientEntry); - set_content(type: FrameContent); - } -} - -/* File: D:\TeaSpeak\web\shared\js\ui\frames\chat.ts */ -declare enum ChatType { - GENERAL, - SERVER, - CHANNEL, - CLIENT -} -declare const xbbcode: any; -declare namespace MessageHelper { - export function htmlEscape(message: string): string[]; - export function formatElement(object: any, escape_html?: boolean): JQuery[]; - export function formatMessage(pattern: string, ...objects: any[]): JQuery[]; - export function bbcode_chat(message: string): JQuery[]; - export namespace network { - export const KB; - export const MB; - export const GB; - export const TB; - export function format_bytes(value: number, options?: { - time?: string; - unit?: string; - exact?: boolean; - }): string; - } - export const K; - export const M; - export const G; - export const T; - export function format_number(value: number, options?: { - time?: string; - unit?: string; - }); - export const TIME_SECOND; - export const TIME_MINUTE; - export const TIME_HOUR; - export const TIME_DAY; - export const TIME_WEEK; - export function format_time(time: number, default_value: string); - export function set_icon_size(size: string); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\frames\connection_handlers.ts */ -declare let server_connections: ServerConnectionManager; -declare class ServerConnectionManager { - private connection_handlers: ConnectionHandler[]; - private active_handler: ConnectionHandler | undefined; - private _container_log_server: JQuery; - private _container_channel_tree: JQuery; - private _container_hostbanner: JQuery; - private _container_chat: JQuery; - private _tag: JQuery; - private _tag_connection_entries: JQuery; - private _tag_buttons_scoll: JQuery; - private _tag_button_scoll_right: JQuery; - private _tag_button_scoll_left: JQuery; - constructor(tag: JQuery); - spawn_server_connection_handler(): ConnectionHandler; - destroy_server_connection_handler(handler: ConnectionHandler); - set_active_connection_handler(handler: ConnectionHandler); - active_connection_handler(): ConnectionHandler | undefined; - server_connection_handlers(): ConnectionHandler[]; - update_ui(); - private _update_scroll(); - private _button_scroll_right_clicked(); - private _button_scroll_left_clicked(); - private _update_scroll_buttons(); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\frames\ControlBar.ts */ -declare let control_bar: ControlBar; -declare type MicrophoneState = "disabled" | "muted" | "enabled"; -declare type HeadphoneState = "muted" | "enabled"; -declare type AwayState = "away-global" | "away" | "online"; -declare class ControlBar { - private _button_away_active: AwayState; - private _button_microphone: MicrophoneState; - private _button_speakers: HeadphoneState; - private _button_subscribe_all: boolean; - private _button_query_visible: boolean; - private connection_handler: ConnectionHandler | undefined; - private _button_hostbanner: JQuery; - htmlTag: JQuery; - constructor(htmlTag: JQuery); - initialize_connection_handler_state(handler?: ConnectionHandler); - set_connection_handler(handler?: ConnectionHandler); - apply_server_state(); - apply_server_hostbutton(); - apply_server_voice_state(); - current_connection_handler(); - initialise(); - // @ts-ignore - set button_away_active(flag: AwayState); - update_button_away(); - // @ts-ignore - set button_microphone(state: MicrophoneState); - // @ts-ignore - set button_speaker(state: HeadphoneState); - // @ts-ignore - set button_subscribe_all(state: boolean); - // @ts-ignore - set button_query_visible(state: boolean); - /* UI listener */ - private on_away_toggle(); - private on_away_enable(); - private on_away_disable(); - private on_away_set_message(); - private on_away_enable_global(); - private on_away_disable_global(); - private on_away_set_message_global(); - private on_toggle_microphone(); - private on_toggle_sound(); - private on_toggle_channel_subscribe(); - private on_toggle_query_view(); - private on_open_settings(); - private on_open_connect(); - private on_open_connect_new_tab(); - update_connection_state(); - private on_execute_disconnect(); - private on_token_use(); - private on_token_list(); - private on_open_permissions(); - private on_open_banslist(); - private on_bookmark_server_add(); - update_bookmark_status(); - update_bookmarks(); - private on_bookmark_manage(); - private on_open_query_create(); - private on_open_query_manage(); - private on_open_playlist_manage(); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\frames\hostbanner.ts */ -declare class Hostbanner { - readonly html_tag: JQuery; - readonly client: ConnectionHandler; - private _destryed; - private updater: NodeJS.Timer; - constructor(client: ConnectionHandler); - destroy(); - update(); - public static generate_tag(banner_url: string | undefined, gfx_interval: number, mode: number): Promise; - private generate_tag?(): Promise; -} - -/* File: D:\TeaSpeak\web\shared\js\ui\frames\MenuBar.ts */ -declare namespace top_menu { - export interface HRItem { - } - export interface MenuItem { - append_item(label: string): MenuItem; - append_hr(): HRItem; - delete_item(item: MenuItem | HRItem); - items(): (MenuItem | HRItem)[]; - icon(klass?: string | Promise | Icon): string; - label(value?: string): string; - visible(value?: boolean): boolean; - disabled(value?: boolean): boolean; - click(callback: () => any): this; - } - export interface MenuBarDriver { - initialize(); - append_item(label: string): MenuItem; - delete_item(item: MenuItem); - items(): MenuItem[]; - flush_changes(); - } - export function driver(): MenuBarDriver; - export function set_driver(driver: MenuBarDriver); - export interface NativeActions { - open_dev_tools(); - reload_page(); - check_native_update(); - open_change_log(); - quit(); - show_dev_tools(): boolean; - } - export let native_actions: NativeActions; - namespace html { - export class HTMLHrItem implements top_menu.HRItem { - readonly html_tag: JQuery; - constructor(); - } - export class HTMLMenuItem implements top_menu.MenuItem { - readonly html_tag: JQuery; - readonly _label_tag: JQuery; - readonly _label_icon_tag: JQuery; - readonly _label_text_tag: JQuery; - readonly _submenu_tag: JQuery; - private _items: (MenuItem | HRItem)[]; - private _label: string; - private _callback_click: () => any; - constructor(label: string, mode: "side" | "down"); - append_item(label: string): top_menu.MenuItem; - append_hr(): HRItem; - delete_item(item: top_menu.MenuItem | top_menu.HRItem); - disabled(value?: boolean): boolean; - items(): (top_menu.MenuItem | top_menu.HRItem)[]; - label(value?: string): string; - visible(value?: boolean): boolean; - click(callback: () => any): this; - icon(klass?: string | Promise | Icon): string; - } - export class HTMLMenuBarDriver implements MenuBarDriver { - private static _instance: HTMLMenuBarDriver; - public static instance(): HTMLMenuBarDriver; - readonly html_tag: JQuery; - private _items: MenuItem[]; - constructor(); - append_item(label: string): top_menu.MenuItem; - close(); - delete_item(item: MenuItem); - items(): top_menu.MenuItem[]; - flush_changes(); - initialize(); - } - } - export function rebuild_bookmarks(); - export function update_state(); - namespace native { - export function initialize(); - } - export function initialize(); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\frames\server_log.ts */ -declare namespace log { - export namespace server { - export enum Type { - CONNECTION_BEGIN = "connection_begin", - CONNECTION_HOSTNAME_RESOLVE = "connection_hostname_resolve", - CONNECTION_HOSTNAME_RESOLVE_ERROR = "connection_hostname_resolve_error", - CONNECTION_HOSTNAME_RESOLVED = "connection_hostname_resolved", - CONNECTION_LOGIN = "connection_login", - CONNECTION_CONNECTED = "connection_connected", - CONNECTION_FAILED = "connection_failed", - DISCONNECTED = "disconnected", - CONNECTION_VOICE_SETUP_FAILED = "connection_voice_setup_failed", - CONNECTION_COMMAND_ERROR = "connection_command_error", - GLOBAL_MESSAGE = "global_message", - SERVER_WELCOME_MESSAGE = "server_welcome_message", - SERVER_HOST_MESSAGE = "server_host_message", - SERVER_HOST_MESSAGE_DISCONNECT = "server_host_message_disconnect", - SERVER_CLOSED = "server_closed", - SERVER_BANNED = "server_banned", - SERVER_REQUIRES_PASSWORD = "server_requires_password", - CLIENT_VIEW_ENTER = "client_view_enter", - CLIENT_VIEW_LEAVE = "client_view_leave", - CLIENT_VIEW_MOVE = "client_view_move", - CLIENT_NICKNAME_CHANGED = "client_nickname_changed", - CLIENT_NICKNAME_CHANGE_FAILED = "client_nickname_change_failed", - CLIENT_SERVER_GROUP_ADD = "client_server_group_add", - CLIENT_SERVER_GROUP_REMOVE = "client_server_group_remove", - CLIENT_CHANNEL_GROUP_CHANGE = "client_channel_group_change", - CHANNEL_CREATE = "channel_create", - CHANNEL_DELETE = "channel_delete", - ERROR_CUSTOM = "error_custom", - ERROR_PERMISSION = "error_permission", - RECONNECT_SCHEDULED = "reconnect_scheduled", - RECONNECT_EXECUTE = "reconnect_execute", - RECONNECT_CANCELED = "reconnect_canceled" - } - export namespace base { - export type Client = { - client_unique_id: string; - client_name: string; - client_id: number; - }; - export type Channel = { - channel_id: number; - channel_name: string; - }; - export type Server = { - server_name: string; - server_unique_id: string; - }; - export type ServerAddress = { - server_hostname: string; - server_port: number; - }; - } - export namespace event { - export type GlobalMessage = { - sender: base.Client; - message: string; - }; - export type ConnectBegin = { - address: base.ServerAddress; - client_nickname: string; - }; - export type ErrorCustom = { - message: string; - }; - export type ReconnectScheduled = { - timeout: number; - }; - export type ReconnectCanceled = {}; - export type ReconnectExecute = {}; - export type ErrorPermission = { - permission: PermissionInfo; - }; - export type WelcomeMessage = { - message: string; - }; - export type HostMessageDisconnect = { - message: string; - }; - export type ClientMove = { - channel_from?: base.Channel; - channel_from_own: boolean; - channel_to?: base.Channel; - channel_to_own: boolean; - client: base.Client; - client_own: boolean; - invoker?: base.Client; - message?: string; - reason: ViewReasonId; - }; - export type ClientEnter = { - channel_from?: base.Channel; - channel_to?: base.Channel; - client: base.Client; - invoker?: base.Client; - message?: string; - own_channel: boolean; - reason: ViewReasonId; - ban_time?: number; - }; - export type ClientLeave = { - channel_from?: base.Channel; - channel_to?: base.Channel; - client: base.Client; - invoker?: base.Client; - message?: string; - own_channel: boolean; - reason: ViewReasonId; - ban_time?: number; - }; - export type ChannelCreate = { - creator: base.Client; - channel: base.Channel; - own_action: boolean; - }; - export type ChannelDelete = { - deleter: base.Client; - channel: base.Channel; - own_action: boolean; - }; - export type ConnectionConnected = { - own_client: base.Client; - }; - export type ConnectionFailed = {}; - export type ConnectionLogin = {}; - export type ConnectionHostnameResolve = {}; - export type ConnectionHostnameResolved = { - address: base.ServerAddress; - }; - export type ConnectionHostnameResolveError = { - message: string; - }; - export type ConnectionVoiceSetupFailed = { - reason: string; - reconnect_delay: number; /* if less or equal to 0 reconnect is prohibited */ - }; - export type ConnectionCommandError = { - error: any; - }; - export type ClientNicknameChanged = { - own_client: boolean; - client: base.Client; - old_name: string; - new_name: string; - }; - export type ClientNicknameChangeFailed = { - reason: string; - }; - export type ServerClosed = { - message: string; - }; - export type ServerRequiresPassword = {}; - export type ServerBanned = { - message: string; - time: number; - invoker: base.Client; - }; - } - export type LogMessage = { - type: Type; - timestamp: number; - data: any; - }; - export interface TypeInfo { - "connection_begin": event.ConnectBegin; - "global_message": event.GlobalMessage; - "error_custom": event.ErrorCustom; - "error_permission": event.ErrorPermission; - "connection_hostname_resolved": event.ConnectionHostnameResolved; - "connection_hostname_resolve": event.ConnectionHostnameResolve; - "connection_hostname_resolve_error": event.ConnectionHostnameResolveError; - "connection_failed": event.ConnectionFailed; - "connection_login": event.ConnectionLogin; - "connection_connected": event.ConnectionConnected; - "connection_voice_setup_failed": event.ConnectionVoiceSetupFailed; - "connection_command_error": event.ConnectionCommandError; - "reconnect_scheduled": event.ReconnectScheduled; - "reconnect_canceled": event.ReconnectCanceled; - "reconnect_execute": event.ReconnectExecute; - "server_welcome_message": event.WelcomeMessage; - "server_host_message": event.WelcomeMessage; - "server_host_message_disconnect": event.HostMessageDisconnect; - "server_closed": event.ServerClosed; - "server_requires_password": event.ServerRequiresPassword; - "server_banned": event.ServerBanned; - "client_view_enter": event.ClientEnter; - "client_view_move": event.ClientMove; - "client_view_leave": event.ClientLeave; - "client_nickname_change_failed": event.ClientNicknameChangeFailed; - "client_nickname_changed": event.ClientNicknameChanged; - "channel_create": event.ChannelCreate; - "channel_delete": event.ChannelDelete; - "disconnected": any; - } - export type MessageBuilderOptions = {}; - export type MessageBuilder = (data: TypeInfo[T], options: MessageBuilderOptions) => JQuery[] | undefined; - export const MessageBuilders: { - [key: string]: MessageBuilder; - }; - } - export class ServerLog { - private readonly handle: ConnectionHandler; - private history_length: number; - private _log: server.LogMessage[]; - private _html_tag: JQuery; - private _log_container: JQuery; - private auto_follow: boolean; - private _ignore_event: number; - constructor(handle: ConnectionHandler); - log(type: T, data: server.TypeInfo[T]); - html_tag(): JQuery; - destroy(); - private _scroll_task: number; - private append_log(message: server.LogMessage); - } -} -declare namespace log { - export namespace server { - namespace impl { } - } -} - -/* File: D:\TeaSpeak\web\shared\js\ui\frames\side\chat_box.ts */ -declare namespace chat { - export class ChatBox { - private _html_tag: JQuery; - private _html_input: JQuery; - private _enabled: boolean; - private __callback_text_changed; - private __callback_key_down; - private __callback_key_up; - private __callback_paste; - private _typing_timeout: number; - private _typing_last_event: number; - private _message_history: string[]; - private _message_history_length; - private _message_history_index; - typing_interval: number; - callback_typing: () => any; - callback_text: (text: string) => any; - constructor(); - html_tag(): JQuery; - destroy(); - private _initialize_listener(); - private _build_html_tag(); - private _callback_text_changed(event: Event); - private _text(element: HTMLElement); - private htmlEscape(message: string): string; - private _callback_paste(event: ClipboardEvent); - private test_message(message: string): boolean; - private _callback_key_down(event: KeyboardEvent); - private _callback_key_up(event: KeyboardEvent); - private _context_task: number; - set_enabled(flag: boolean); - is_enabled(); - focus_input(); - } -} - -/* File: D:\TeaSpeak\web\shared\js\ui\frames\side\chat_helper.ts */ -declare namespace chat { - export namespace helpers { - namespace md2bbc { - export type RemarkToken = { - type: string; - tight: boolean; - lines: number[]; - level: number; - /* img */ - alt?: string; - src?: string; - /* link */ - href?: string; - /* table */ - align?: string; - /* code */ - params?: string; - content?: string; - hLevel?: number; - children?: RemarkToken[]; - }; - export class Renderer { - private static renderers; - private _options; - last_paragraph: RemarkToken; - render(tokens: RemarkToken[], options: any, env: any); - private render_token(token: RemarkToken, index: number); - private render_inline(tokens: RemarkToken[], index: number); - options(): any; - maybe_escape_bb(text: string); - } - } - export function preprocess_chat_message(message: string): string; - export namespace history { - export function load_history(key: string): Promise; - export function save_history(key: string, value: any): Promise; - } - export namespace date { - export function same_day(a: number | Date, b: number | Date); - } - } - export namespace format { - export namespace date { - export enum ColloquialFormat { - YESTERDAY, - TODAY, - GENERAL - } - export function date_format(date: Date, now: Date, ignore_settings?: boolean): ColloquialFormat; - export function format_date_general(date: Date, hours?: boolean): string; - export function format_date_colloquial(date: Date, current_timestamp: Date): { - result: string; - format: ColloquialFormat; - }; - export function format_chat_time(date: Date): { - result: string; - next_update: number; /* in MS */ - }; - } - export namespace time { - export function format_online_time(secs: number): string; - } - } -} - -/* File: D:\TeaSpeak\web\shared\js\ui\frames\side\client_info.ts */ -declare namespace chat { - export class ClientInfo { - readonly handle: Frame; - private _html_tag: JQuery; - private _current_client: ClientEntry | undefined; - private _online_time_updater: number; - previous_frame_content: FrameContent; - constructor(handle: Frame); - html_tag(): JQuery; - destroy(); - private _build_html_tag(); - current_client(): ClientEntry; - set_current_client(client: ClientEntry | undefined, enforce?: boolean); - } -} - -/* File: D:\TeaSpeak\web\shared\js\ui\frames\side\conversations.ts */ -declare namespace chat { - export namespace channel { - export type ViewEntry = { - html_element: JQuery; - update_timer?: number; - }; - export type MessageData = { - timestamp: number; - message: string; - sender_name: string; - sender_unique_id: string; - sender_database_id: number; - }; - export type Message = MessageData & ViewEntry; - export class Conversation { - readonly handle: ConversationManager; - readonly channel_id: number; - private _flag_private: boolean; - private _html_tag: JQuery; - private _container_messages: JQuery; - private _container_new_message: JQuery; - private _container_no_permissions: JQuery; - private _container_no_permissions_shown: boolean; - private _container_is_private: JQuery; - private _container_is_private_shown: boolean; - private _container_no_support: JQuery; - private _container_no_support_shown: boolean; - private _view_max_messages; - private _view_older_messages: ViewEntry; - private _has_older_messages: boolean; - private _view_entries: ViewEntry[]; - private _last_messages: MessageData[]; - private _last_messages_timestamp: number; - private _first_unread_message: Message; - private _first_unread_message_pointer: ViewEntry; - private _scroll_position: number | undefined; - constructor(handle: ConversationManager, channel_id: number); - html_tag(): JQuery; - destroy(); - private _build_html_tag(); - is_unread(); - mark_read(); - private _mark_read(); - private _generate_view_message(data: MessageData): Message; - private _generate_view_spacer(message: string, type: "date" | "new" | "old" | "error"): ViewEntry; - last_messages_timestamp(): number; - fetch_last_messages(); - fetch_older_messages(); - register_new_message(message: MessageData, update_view?: boolean); - /* using a timeout here to not cause a force style recalculation */ - private _scroll_fix_timer: number; - private _scroll_animate: boolean; - fix_scroll(animate: boolean); - fix_view_size(); - chat_available(): boolean; - text_send_failed(error: CommandResult | any); - set_flag_private(flag: boolean); - update_private_state(); - delete_message(message: MessageData); - delete_messages(begin: number, end: number, sender: number, limit: number); - private _delete_message(message: Message); - } - export class ConversationManager { - readonly handle: Frame; - private _html_tag: JQuery; - private _chat_box: ChatBox; - private _container_conversation: JQuery; - private _conversations: Conversation[]; - private _current_conversation: Conversation | undefined; - private _needed_listener; - constructor(handle: Frame); - initialize_needed_listener(); - html_tag(): JQuery; - destroy(); - update_chat_box(); - private _build_html_tag(); - set_current_channel(channel_id: number, update_info_frame?: boolean); - current_channel(): number; - /* Used by notifychanneldeleted */ - delete_conversation(channel_id: number); - reset(); - conversation(channel_id: number, create?: boolean): Conversation; - on_show(); - update_input_format_helper(); - } - } -} - -/* File: D:\TeaSpeak\web\shared\js\ui\frames\side\music_info.ts */ -declare namespace chat { - export class MusicInfo { - readonly events: events.Registry; - readonly handle: Frame; - private _html_tag: JQuery; - private _container_playlist: JQuery; - private _current_bot: MusicClientEntry | undefined; - private update_song_info: number; - private time_select: { - active: boolean; - max_time: number; - current_select_time: number; - current_player_time: number; - }; - private song_reorder: { - active: boolean; - song_id: number; - previous_entry: number; - html: JQuery; - mouse?: { - x: number; - y: number; - }; - indicator: JQuery; - }; - previous_frame_content: FrameContent; - constructor(handle: Frame); - html_tag(): JQuery; - destroy(); - private format_time(value: number); - private _build_html_tag(); - private display_song_info(song: SongInfo); - private initialize_listener(); - set_current_bot(client: MusicClientEntry | undefined, enforce?: boolean); - current_bot(): MusicClientEntry | undefined; - private sort_songs(data: PlaylistSong[]); - /* playlist stuff */ - update_playlist(); - private _playlist_subscribed; - private playlist_subscribe(unsubscribe: boolean); - private build_playlist_entry(data: PlaylistSong, insert_effect: boolean): JQuery; - } -} - -/* File: D:\TeaSpeak\web\shared\js\ui\frames\side\private_conversations.ts */ -declare namespace chat { - export type PrivateConversationViewEntry = { - html_tag: JQuery; - }; - export type PrivateConversationMessageData = { - message_id: string; - message: string; - sender: "self" | "partner"; - sender_name: string; - sender_unique_id: string; - sender_client_id: number; - timestamp: number; - }; - export type PrivateConversationViewMessage = PrivateConversationMessageData & PrivateConversationViewEntry & { - time_update_id: number; - }; - export type PrivateConversationViewSpacer = PrivateConversationViewEntry; - export enum PrivateConversationState { - OPEN, - CLOSED, - DISCONNECTED, - DISCONNECTED_SELF - } - export type DisplayedMessage = { - timestamp: number; - message: PrivateConversationViewMessage | PrivateConversationViewEntry; - message_type: "spacer" | "message"; - /* structure as following - 1. time pointer - 2. unread - 3. message - */ - tag_message: JQuery; - tag_unread: PrivateConversationViewSpacer | undefined; - tag_timepointer: PrivateConversationViewSpacer | undefined; - }; - export class PrivateConveration { - readonly handle: PrivateConverations; - private _html_entry_tag: JQuery; - private _message_history: PrivateConversationMessageData[]; - private _callback_message: (text: string) => any; - private _state: PrivateConversationState; - private _last_message_updater_id: number; - private _last_typing: number; - private _typing_timeout: number; - private _typing_timeout_task: number; - _scroll_position: number | undefined; - _html_message_container: JQuery; - client_unique_id: string; - client_id: number; - client_name: string; - private _displayed_messages: DisplayedMessage[]; - private _displayed_messages_length: number; - private _spacer_unread_message: DisplayedMessage; - constructor(handle: PrivateConverations, client_unique_id: string, client_name: string, client_id: number); - private history_key(); - private load_history(); - private save_history(); - entry_tag(): JQuery; - destroy(); - private _2d_flat(array: T[][]): T[]; - messages_tags(): JQuery[]; - append_message(message: string, sender: { - type: "self" | "partner"; - name: string; - unique_id: string; - client_id: number; - }, timestamp?: Date, save_history?: boolean); - private _displayed_message_first_tag(message: DisplayedMessage); - private _destroy_displayed_message(message: DisplayedMessage, update_pointers: boolean); - clear_messages(save?: boolean); - fix_scroll(animate: boolean); - private _update_message_timestamp(); - private _destroy_message(message: PrivateConversationViewMessage); - private _build_message(message: PrivateConversationMessageData): PrivateConversationViewMessage; - private _build_spacer(message: string, type: "date" | "new" | "disconnect" | "disconnect_self" | "reconnect" | "closed" | "error"): PrivateConversationViewSpacer; - private _register_displayed_message(message: DisplayedMessage, update_new: boolean); - private _destroy_view_entry(entry: PrivateConversationViewEntry); - private _build_entry_tag(); - update_avatar(); - close_conversation(); - set_client_name(name: string); - set_unread_flag(flag: boolean, update_chat_counter?: boolean); - is_unread(): boolean; - private _append_state_change(state: "disconnect" | "disconnect_self" | "reconnect" | "closed"); - state(): PrivateConversationState; - set_state(state: PrivateConversationState); - set_text_callback(callback: (text: string) => any, update_enabled_state?: boolean); - chat_enabled(); - append_error(message: string, date?: number); - call_message(message: string); - private typing_expired(); - trigger_typing(); - typing_active(); - } - export class PrivateConverations { - readonly handle: Frame; - private _chat_box: ChatBox; - private _html_tag: JQuery; - private _container_conversation: JQuery; - private _container_conversation_messages: JQuery; - private _container_conversation_list: JQuery; - private _container_typing: JQuery; - private _html_no_chats: JQuery; - private _conversations: PrivateConveration[]; - private _current_conversation: PrivateConveration; - private _select_read_timer: number; - constructor(handle: Frame); - clear_client_ids(); - html_tag(): JQuery; - destroy(); - current_conversation(): PrivateConveration | undefined; - conversations(): PrivateConveration[]; - create_conversation(client_uid: string, client_name: string, client_id: number): PrivateConveration; - delete_conversation(conv: PrivateConveration, update_chat_couner?: boolean); - find_conversation(partner: { - name: string; - unique_id: string; - client_id: number; - }, mode: { - create: boolean; - attach: boolean; - }): PrivateConveration | undefined; - clear_conversations(); - set_selected_conversation(conv: PrivateConveration | undefined); - update_chatbox_state(); - update_typing_state(); - private _build_html_tag(); - try_input_focus(); - on_show(); - update_input_format_helper(); - } -} - -/* File: D:\TeaSpeak\web\shared\js\ui\htmltags.ts */ -declare namespace htmltags { - export interface ClientProperties { - client_id: number; - client_unique_id: string; - client_name: string; - add_braces?: boolean; - client_database_id?: number; - } - export interface ChannelProperties { - channel_id: number; - channel_name: string; - channel_display_name?: string; - add_braces?: boolean; - } - export function generate_client(properties: ClientProperties): string; - export function generate_client_object(properties: ClientProperties): JQuery; - export function generate_channel(properties: ChannelProperties): string; - export function generate_channel_object(properties: ChannelProperties): JQuery; - export namespace callbacks { - export function callback_context_client(element: JQuery); - export function callback_context_channel(element: JQuery); - } - namespace bbcodes { } -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalAbout.ts */ -declare namespace Modals { - export function spawnAbout(); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalAvatar.ts */ -declare namespace Modals { - //TODO: Test if we could render this image and not only the browser by knowing the type. - export function spawnAvatarUpload(callback_data: (data: ArrayBuffer | undefined | null) => any); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalAvatarList.ts */ -declare namespace Modals { - export const human_file_size; - export function spawnAvatarList(client: ConnectionHandler); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalBanClient.ts */ -declare namespace Modals { - export type BanEntry = { - name?: string; - unique_id: string; - }; - export function spawnBanClient(client: ConnectionHandler, entries: BanEntry | BanEntry[], callback: (data: { - length: number; - reason: string; - no_name: boolean; - no_ip: boolean; - no_hwid: boolean; - }) => void); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalBanList.ts */ -declare namespace Modals { - export function openBanList(client: ConnectionHandler); - //Note: This object must be sorted (from shortest to longest)! - export const duration_data; -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalBookmarks.ts */ -declare namespace Modals { - export function spawnBookmarkModal(); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalBotMenue.ts */ - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalChangeLatency.ts */ -declare namespace Modals { - export function spawnChangeLatency(client: ClientEntry, current: connection.voice.LatencySettings, reset: () => connection.voice.LatencySettings, apply: (settings: connection.voice.LatencySettings) => any, callback_flush?: () => any); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalChangeVolume.ts */ -declare namespace Modals { - export function spawnChangeVolume(client: ClientEntry, local: boolean, current: number, max: number | undefined, callback: (number) => void); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalChannelInfo.ts */ -declare namespace Modals { - export function openChannelInfo(channel: ChannelEntry); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalClientInfo.ts */ -declare namespace Modals { - export function openClientInfo(client: ClientEntry); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalConnect.ts */ -declare namespace connection_log { - //TODO: Save password data - export type ConnectionData = { - name: string; - icon_id: number; - country: string; - clients_online: number; - clients_total: number; - flag_password: boolean; - password_hash: string; - }; - export type ConnectionEntry = ConnectionData & { - address: { - hostname: string; - port: number; - }; - total_connection: number; - first_timestamp: number; - last_timestamp: number; - }; - export function log_connect(address: { - hostname: string; - port: number; - }); - export function update_address_info(address: { - hostname: string; - port: number; - }, data: ConnectionData); - export function update_address_password(address: { - hostname: string; - port: number; - }, password_hash: string); - export function history(): ConnectionEntry[]; - export function delete_entry(address: { - hostname: string; - port: number; - }); -} -declare namespace Modals { - export function spawnConnectModal(options: { - default_connect_new_tab?: boolean; /* default false */ - }, defaultHost?: { - url: string; - enforce: boolean; - }, connect_profile?: { - profile: profiles.ConnectionProfile; - enforce: boolean; - }); - export const Regex; -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalCreateChannel.ts */ -declare namespace Modals { - export function createChannelModal(connection: ConnectionHandler, channel: ChannelEntry | undefined, parent: ChannelEntry | undefined, permissions: PermissionManager, callback: (properties?: ChannelProperties, permissions?: PermissionValue[]) => any); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalGroupAssignment.ts */ -declare namespace Modals { - export function createServerGroupAssignmentModal(client: ClientEntry, callback: (groups: number[], flag: boolean) => Promise); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalIconSelect.ts */ -declare namespace Modals { - export function spawnIconSelect(client: ConnectionHandler, callback_icon?: (id: number) => any, selected_icon?: number); - export function spawnIconUpload(client: ConnectionHandler); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalIdentity.ts */ -declare namespace Modals { - export function spawnTeamSpeakIdentityImprove(identity: profiles.identities.TeaSpeakIdentity, name: string): Modal; - export function spawnTeamSpeakIdentityImport(callback: (identity: profiles.identities.TeaSpeakIdentity) => any): Modal; -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalInvite.ts */ -declare namespace Modals { - export function spawnInviteEditor(connection: ConnectionHandler); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalKeySelect.ts */ -declare namespace Modals { - export function spawnKeySelect(callback: (key?: ppt.KeyEvent) => void); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalMusicManage.ts */ -declare namespace Modals { - export function openMusicManage(client: ConnectionHandler, bot: MusicClientEntry); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalNewcomer.ts */ -declare namespace Modals { - export function openModalNewcomer(); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalPlaylistEdit.ts */ -declare namespace Modals { - export function spawnPlaylistSongInfo(song: PlaylistSong); - export function spawnSongAdd(playlist: Playlist, callback_add: (url: string, loader: string) => any); - export function spawnPlaylistEdit(client: ConnectionHandler, playlist: Playlist); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalPlaylistList.ts */ -declare namespace Modals { - export function spawnPlaylistManage(client: ConnectionHandler); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalPoke.ts */ -declare namespace Modals { - export class PokeModal { - private _handle: Modal; - private source_map: ServerEntry[]; - constructor(); - modal(); - add_poke(source: ConnectionHandler, invoker: PokeInvoker, message: string); - private _handle_close(); - } - export type PokeInvoker = { - name: string; - id: number; - unique_id: string; - }; - export function spawnPoke(source: ConnectionHandler, invoker: PokeInvoker, message: string); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalQuery.ts */ -declare namespace Modals { - export function spawnQueryCreate(connection: ConnectionHandler, callback_created?: (user, pass) => any); - export function spawnQueryCreated(credentials: { - username: string; - password: string; - }, just_created: boolean); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalQueryManage.ts */ -declare namespace Modals { - /* - export function spawnQueryManage(client: ConnectionHandler) { - let modal: Modal; - let selected_query: QueryListEntry; - - 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: 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(client, (user, pass) => update_list()); - }); - template.find(".button-query-rename").on('click', () => { - if(!selected_query) return; - - createInputModal(tr("Change account name"), tr("Enter the new name for the login:
"), 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(tr("Unable to rename account"), tr("Failed to rename account
Message: ") + error).open(); - }).then(() => { - createInfoModal(tr("Account successfully renamed"), tr("The query account has been renamed!")).open(); - update_list(); - }); - } - }).open(); - }); - template.find(".button-query-change-password").on('click', () => { - if(!selected_query) return; - - createInputModal(tr("Change account's password"), tr("Enter a new password (leave blank for auto generation):
"), text => true, result => { - if(result !== false) { - const single_handler: connection.SingleCommandHandler = { - 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(tr("Unable to change password"), tr("Failed to change password
Message: ") + error).open(); - }); - } - }).open(); - }); - template.find(".button-query-delete").on('click', () => { - if(!selected_query) return; - - Modals.spawnYesNo(tr("Are you sure?"), 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(tr("Unable to delete account"), tr("Failed to delete account
Message: ") + error).open(); - }).then(() => { - createInfoModal(tr("Account successfully deleted"), 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() as string || "").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(); - } - */ - //tmpl_query_manager - export function spawnQueryManage(client: ConnectionHandler); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalServerEdit.ts */ -declare namespace Modals { - export function createServerModal(server: ServerEntry, callback: (properties?: ServerProperties) => Promise); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalServerInfo.ts */ -declare namespace Modals { - export function openServerInfo(server: ServerEntry); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalServerInfoBandwidth.ts */ -declare namespace Modals { - export enum RequestInfoStatus { - SUCCESS, - UNKNOWN, - NO_PERMISSION - } - export type ServerBandwidthInfoUpdateCallback = (status: RequestInfoStatus, info?: ServerConnectionInfo) => any; - export function openServerInfoBandwidth(server: ServerEntry, update_callbacks?: ServerBandwidthInfoUpdateCallback[]): Modal; -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalSettings.ts */ -declare namespace Modals { - export function spawnSettingsModal(default_page?: string): Modal; -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\ModalYesNo.ts */ -declare namespace Modals { - export function spawnYesNo(header: BodyCreator, body: BodyCreator, callback: (_: boolean) => any, properties?: { - text_yes?: string; - text_no?: string; - closeable?: boolean; - }); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\permission\CanvasPermissionEditor.ts */ -declare namespace pe { - namespace ui { - export namespace scheme { - export interface CheckBox { - border: string; - checkmark: string; - checkmark_font: string; - background_checked: string; - background_checked_hovered: string; - background: string; - background_hovered: string; - } - export interface TextField { - color: string; - font: string; - background: string; - background_hovered: string; - } - export interface ColorScheme { - permission: { - background: string; - background_selected: string; - name: string; - name_unset: string; - name_font: string; - value: TextField; - value_b: CheckBox; - granted: TextField; - negate: CheckBox; - skip: CheckBox; - }; - group: { - name: string; - name_font: string; - }; - } - } - export enum RepaintMode { - NONE, - REPAINT, - REPAINT_OBJECT_FULL, - REPAINT_FULL - } - export interface AxisAlignedBoundingBox { - x: number; - y: number; - width: number; - height: number; - } - export enum ClickEventType { - SIGNLE, - DOUBLE, - CONTEXT_MENU - } - export interface InteractionClickEvent { - type: ClickEventType; - consumed: boolean; - offset_x: number; - offset_y: number; - } - export interface InteractionListener { - region: AxisAlignedBoundingBox; - region_weight: number; - /** - * @return true if a redraw is required - */ - on_mouse_enter?: () => RepaintMode; - /** - * @return true if a redraw is required - */ - on_mouse_leave?: () => RepaintMode; - /** - * @return true if a redraw is required - */ - on_click?: (event: InteractionClickEvent) => RepaintMode; - mouse_cursor?: string; - set_full_draw?: () => any; - disabled?: boolean; - } - export abstract class DrawableObject { - abstract draw(context: CanvasRenderingContext2D, full: boolean); - private _object_full_draw; - private _width: number; - set_width(value: number); - request_full_draw(); - pop_full_draw(); - width(); - abstract height(); - private _transforms: DOMMatrix[]; - protected push_transform(context: CanvasRenderingContext2D); - protected pop_transform(context: CanvasRenderingContext2D); - protected original_x(context: CanvasRenderingContext2D, x: number); - protected original_y(context: CanvasRenderingContext2D, y: number); - protected colors: scheme.ColorScheme; - set_color_scheme(scheme: scheme.ColorScheme); - protected manager: PermissionEditor; - set_manager(manager: PermissionEditor); - abstract initialize(); - abstract finalize(); - } - export class PermissionGroup extends DrawableObject { - public static readonly HEIGHT; - public static readonly ARROW_SIZE; - group: GroupedPermissions; - _sub_elements: PermissionGroup[]; - _element_permissions: PermissionList; - collapsed; - private _listener_colaps: InteractionListener; - constructor(group: GroupedPermissions); - draw(context: CanvasRenderingContext2D, full: boolean); - set_width(value: number); - set_color_scheme(scheme: scheme.ColorScheme); - set_manager(manager: PermissionEditor); - height(); - initialize(); - finalize(); - collapse_group(); - expend_group(); - } - export class PermissionList extends DrawableObject { - permissions: PermissionEntry[]; - constructor(permissions: PermissionInfo[]); - set_width(value: number); - draw(context: CanvasRenderingContext2D, full: boolean); - height(); - set_color_scheme(scheme: scheme.ColorScheme); - set_manager(manager: PermissionEditor); - initialize(); - finalize(); - handle_hide(); - } - export class PermissionEntry extends DrawableObject { - public static readonly HEIGHT; - public static readonly HALF_HEIGHT; - public static readonly CHECKBOX_HEIGHT; - public static readonly COLUMN_PADDING; - public static readonly COLUMN_VALUE; - public static readonly COLUMN_GRANTED; - //public static readonly COLUMN_NEGATE = 25; - //public static readonly COLUMN_SKIP = 25; - public static readonly COLUMN_NEGATE; - public static readonly COLUMN_SKIP; - private _permission: PermissionInfo; - hidden: boolean; - granted: number; - value: number; - flag_skip: boolean; - flag_negate: boolean; - private _prev_selected; - selected: boolean; - flag_skip_hovered; - flag_negate_hovered; - flag_value_hovered; - flag_grant_hovered; - private _listener_checkbox_skip: InteractionListener; - private _listener_checkbox_negate: InteractionListener; - private _listener_value: InteractionListener; - private _listener_grant: InteractionListener; - private _listener_general: InteractionListener; - private _icon_image: HTMLImageElement | undefined; - on_icon_select?: (current_id: number) => Promise; - on_context_menu?: (x: number, y: number) => any; - on_grant_change?: () => any; - on_change?: () => any; - constructor(permission: PermissionInfo); - set_icon_id_image(image: HTMLImageElement | undefined); - permission(); - draw(ctx: CanvasRenderingContext2D, full: boolean); - handle_hide(); - private _draw_icon_field(ctx: CanvasRenderingContext2D, scheme: scheme.CheckBox, x: number, y: number, width: number, hovered: boolean, image: HTMLImageElement); - private _draw_number_field(ctx: CanvasRenderingContext2D, scheme: scheme.TextField, x: number, y: number, width: number, value: number, hovered: boolean); - private _draw_checkbox_field(ctx: CanvasRenderingContext2D, scheme: scheme.CheckBox, x: number, y: number, height: number, checked: boolean, hovered: boolean); - height(); - set_width(value: number); - initialize(); - finalize(); - private _spawn_number_edit(x: number, y: number, width: number, height: number, color: scheme.TextField, value: number, callback: (new_value?: number) => any); - trigger_value_assign(); - trigger_grant_assign(); - } - export class InteractionManager { - private _listeners: InteractionListener[]; - private _entered_listeners: InteractionListener[]; - register_listener(listener: InteractionListener); - remove_listener(listener: InteractionListener); - process_mouse_move(new_x: number, new_y: number): { - repaint: RepaintMode; - cursor: string; - }; - private process_click_event(x: number, y: number, event: InteractionClickEvent): RepaintMode; - process_click(x: number, y: number): RepaintMode; - process_dblclick(x: number, y: number): RepaintMode; - process_context_menu(js_event: MouseEvent, x: number, y: number): RepaintMode; - } - export class PermissionEditor { - private static readonly PERMISSION_HEIGHT; - private static readonly PERMISSION_GROUP_HEIGHT; - readonly grouped_permissions: GroupedPermissions[]; - readonly canvas: HTMLCanvasElement; - readonly canvas_container: HTMLDivElement; - private _max_height: number; - private _permission_count: number; - private _permission_group_count: number; - private _canvas_context: CanvasRenderingContext2D; - private _selected_entry: PermissionEntry; - private _draw_requested: boolean; - private _draw_requested_full: boolean; - private _elements: PermissionGroup[]; - private _intersect_manager: InteractionManager; - private _permission_entry_map: { - [key: number]: PermissionEntry; - }; - mouse: { - x: number; - y: number; - }; - constructor(permissions: GroupedPermissions[]); - private _handle_repaint(mode: RepaintMode); - request_draw(full?: boolean); - draw(full?: boolean); - private initialize(); - intercept_manager(); - set_selected_entry(entry?: PermissionEntry); - permission_entries(): PermissionEntry[]; - collapse_all(); - expend_all(); - } - } - export class CanvasPermissionEditor extends Modals.AbstractPermissionEditor { - private container: JQuery; - private mode_container_permissions: JQuery; - private mode_container_error_permission: JQuery; - private mode_container_unset: JQuery; - /* references within the container tag */ - private permission_value_map: { - [key: number]: PermissionValue; - }; - private entry_editor: ui.PermissionEditor; - icon_resolver: (id: number) => Promise; - icon_selector: (current_id: number) => Promise; - constructor(); - initialize(permissions: GroupedPermissions[]); - html_tag(); - private build_tag(); - set_permissions(permissions?: PermissionValue[]); - set_mode(mode: Modals.PermissionEditorMode); - update_ui(); - set_toggle_button(callback: () => string, initial: string); - set_hidden_permissions(permissions: PermissionType[]); - } -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\permission\HTMLPermissionEditor.ts */ -declare namespace pe { - export class HTMLPermission { - readonly handle: HTMLPermissionEditor; - readonly group: HTMLPermissionGroup; - readonly permission: PermissionInfo; - readonly index: number; - tag: JQuery; - tag_name: JQuery; - tag_container_value: JQuery; - tag_container_granted: JQuery; - tag_container_skip: JQuery; - tag_container_negate: JQuery; - hidden: boolean; - /* the "actual" values */ - private _mask; - private _tag_value: JQuery; - private _tag_value_input: JQuery; - private _tag_granted: JQuery; - private _tag_granted_input: JQuery; - private _tag_skip: JQuery; - private _tag_skip_input: JQuery; - private _tag_negate: JQuery; - private _tag_negate_input: JQuery; - private _value: number | undefined; - private _grant: number | undefined; - private flags: number; - constructor(handle: HTMLPermissionEditor, group: HTMLPermissionGroup, permission: PermissionInfo, index: number); - private static build_checkbox(): { - tag: JQuery; - input: JQuery; - }; - private static number_filter_re; - private static number_filter; - private build_tag(); - private _trigger_value_assign(); - private _trigger_grant_assign(); - hide(); - show(); - is_filtered(): boolean; - set_filtered(flag: boolean); - is_set(): boolean; - get_value(); - value(value: number | undefined, skip?: boolean, negate?: boolean); - granted(value: number | undefined); - reset(); - private _reset_value(); - private _reset_grant(); - private _update_active_class(); - } - export class HTMLPermissionGroup { - readonly handle: HTMLPermissionEditor; - readonly group: PermissionGroup; - readonly index: number; - private _tag_arrow: JQuery; - permissions: HTMLPermission[]; - children: HTMLPermissionGroup[]; - tag: JQuery; - visible: boolean; - collapsed: boolean; - parent_collapsed: boolean; - constructor(handle: HTMLPermissionEditor, group: PermissionGroup, index: number); - private _build_tag(); - update_visibility(); - collapse(); - expend(); - } - export class HTMLPermissionEditor extends Modals.AbstractPermissionEditor { - container: JQuery; - private mode_container_permissions: JQuery; - private mode_container_error_permission: JQuery; - private mode_container_unset: JQuery; - private icon_shown: boolean; - private filter_input: JQuery; - private filter_grant: JQuery; - private hidden_permissions: PermissionType[]; - private button_toggle: JQuery; - private even_list: ({ - visible(): boolean; - set_even(flag: boolean); - })[]; - private permission_map: Array; - private permission_groups: HTMLPermissionGroup[]; - constructor(); - initialize(permissions: GroupedPermissions[]); - set_hidden_permissions(permissions: PermissionType[]); - private update_filter(); - private update_icon(); - private build_tag(); - html_tag(): JQuery; - set_permissions(u_permissions?: PermissionValue[]); - set_mode(mode: Modals.PermissionEditorMode); - trigger_change(permission: PermissionInfo, value?: Modals.PermissionEditor.PermissionValue, update_icon?: boolean): Promise; - collapse_all(); - expend_all(); - update_view(); - set_toggle_button(callback: () => string, initial: string); - } -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\permission\ModalPermissionEdit.ts */ -declare interface JQuery { - dropdown: any; -} -declare namespace Modals { - export namespace PermissionEditor { - export interface PermissionEntry { - tag: JQuery; - tag_value: JQuery; - tag_grant: JQuery; - tag_flag_negate: JQuery; - tag_flag_skip: JQuery; - id: number; - filter: string; - is_bool: boolean; - } - export interface PermissionValue { - remove: boolean; - granted?: number; - value?: number; - flag_skip?: boolean; - flag_negate?: boolean; - } - export type change_listener_t = (permission: PermissionInfo, value?: PermissionEditor.PermissionValue) => Promise; - } - export enum PermissionEditorMode { - VISIBLE, - NO_PERMISSION, - UNSET - } - export abstract class AbstractPermissionEditor { - protected _permissions: GroupedPermissions[]; - protected _listener_update: () => any; - protected _listener_change: PermissionEditor.change_listener_t; - protected _toggle_callback: () => string; - icon_resolver: (id: number) => Promise; - icon_selector: (current_id: number) => Promise; - protected constructor(); - abstract set_mode(mode: PermissionEditorMode); - abstract initialize(permissions: GroupedPermissions[]); - abstract html_tag(): JQuery; - abstract set_permissions(permissions?: PermissionValue[]); - abstract set_hidden_permissions(permissions: PermissionType[]); - set_listener(listener?: PermissionEditor.change_listener_t); - set_listener_update(listener?: () => any); - trigger_update(); - abstract set_toggle_button(callback: () => string, initial: string); - } - export type OptionsServerGroup = {}; - export type OptionsChannelGroup = {}; - export type OptionsClientPermissions = { - unique_id?: string; - }; - export type OptionsChannelPermissions = { - channel_id?: number; - }; - export type OptionsClientChannelPermissions = OptionsClientPermissions & OptionsChannelPermissions; - export interface OptionMap { - "sg": OptionsServerGroup; - "cg": OptionsChannelGroup; - "clp": OptionsClientPermissions; - "chp": OptionsChannelPermissions; - "clchp": OptionsClientChannelPermissions; - } - export function _space(); - export function spawnPermissionEdit(connection: ConnectionHandler, selected_tab?: T, options?: OptionMap[T]): Modal; -} - -/* File: D:\TeaSpeak\web\shared\js\ui\modal\permission\SenselessPermissions.ts */ -declare namespace permissions { - export const senseless_server_group_permissions: PermissionType[]; - export const senseless_channel_group_permissions: PermissionType[]; - export const senseless_channel_permissions: PermissionType[]; - export const senseless_client_permissions: PermissionType[]; - export const senseless_client_channel_permissions: PermissionType[]; -} - -/* File: D:\TeaSpeak\web\shared\js\ui\server.ts */ -declare class ServerProperties { - virtualserver_host: string; - virtualserver_port: number; - virtualserver_name: string; - virtualserver_name_phonetic: string; - virtualserver_icon_id: number; - virtualserver_version: string; - virtualserver_platform: string; - virtualserver_unique_identifier: string; - virtualserver_clientsonline: number; - virtualserver_queryclientsonline: number; - virtualserver_channelsonline: number; - virtualserver_uptime: number; - virtualserver_created: number; - virtualserver_maxclients: number; - virtualserver_reserved_slots: number; - virtualserver_password: string; - virtualserver_flag_password: boolean; - virtualserver_ask_for_privilegekey: boolean; - virtualserver_welcomemessage: string; - virtualserver_hostmessage: string; - virtualserver_hostmessage_mode: number; - virtualserver_hostbanner_url: string; - virtualserver_hostbanner_gfx_url: string; - virtualserver_hostbanner_gfx_interval: number; - virtualserver_hostbanner_mode: number; - virtualserver_hostbutton_tooltip: string; - virtualserver_hostbutton_url: string; - virtualserver_hostbutton_gfx_url: string; - virtualserver_codec_encryption_mode: number; - virtualserver_default_music_group: number; - virtualserver_default_server_group: number; - virtualserver_default_channel_group: number; - virtualserver_default_channel_admin_group: number; - //Special requested properties - virtualserver_default_client_description: string; - virtualserver_default_channel_description: string; - virtualserver_default_channel_topic: string; - virtualserver_antiflood_points_tick_reduce: number; - virtualserver_antiflood_points_needed_command_block: number; - virtualserver_antiflood_points_needed_ip_block: number; - virtualserver_country_code: string; - virtualserver_complain_autoban_count: number; - virtualserver_complain_autoban_time: number; - virtualserver_complain_remove_time: number; - virtualserver_needed_identity_security_level: number; - virtualserver_weblist_enabled: boolean; - virtualserver_min_clients_in_channel_before_forced_silence: number; - virtualserver_channel_temp_delete_delay_default: number; - virtualserver_priority_speaker_dimm_modificator: number; - virtualserver_max_upload_total_bandwidth: number; - virtualserver_upload_quota: number; - virtualserver_max_download_total_bandwidth: number; - virtualserver_download_quota: number; - virtualserver_month_bytes_downloaded: number; - virtualserver_month_bytes_uploaded: number; - virtualserver_total_bytes_downloaded: number; - virtualserver_total_bytes_uploaded: number; -} -declare interface ServerConnectionInfo { - connection_filetransfer_bandwidth_sent: number; - connection_filetransfer_bandwidth_received: number; - connection_filetransfer_bytes_sent_total: number; - connection_filetransfer_bytes_received_total: number; - connection_filetransfer_bytes_sent_month: number; - connection_filetransfer_bytes_received_month: number; - connection_packets_sent_total: number; - connection_bytes_sent_total: number; - connection_packets_received_total: number; - connection_bytes_received_total: number; - connection_bandwidth_sent_last_second_total: number; - connection_bandwidth_sent_last_minute_total: number; - connection_bandwidth_received_last_second_total: number; - connection_bandwidth_received_last_minute_total: number; - connection_connected_time: number; - connection_packetloss_total: number; - connection_ping: number; -} -declare interface ServerAddress { - host: string; - port: number; -} -declare class ServerEntry { - remote_address: ServerAddress; - channelTree: ChannelTree; - properties: ServerProperties; - private info_request_promise: Promise; - private info_request_promise_resolve: any; - private info_request_promise_reject: any; - private _info_connection_promise: Promise; - private _info_connection_promise_timestamp: number; - private _info_connection_promise_resolve: any; - private _info_connection_promise_reject: any; - lastInfoRequest: number; - nextInfoRequest: number; - private _htmlTag: JQuery; - private _destroyed; - constructor(tree, name, address: ServerAddress); - // @ts-ignore - get htmlTag(); - destroy(); - initializeListener(); - spawnContextMenu(x: number, y: number, on_close?: () => void); - updateVariables(is_self_notify: boolean, ...variables: { - key: string; - value: string; - }[]); - /* this result !must! be cached for at least a second */ - updateProperties(): Promise; - /* max 1s ago, so we could update every second */ - request_connection_info(): Promise; - set_connection_info(info: ServerConnectionInfo); - shouldUpdateProperties(): boolean; - calculateUptime(): number; - // @ts-ignore - set flag_text_unread(flag: boolean); -} - -/* File: D:\TeaSpeak\web\shared\js\ui\view.ts */ -declare class ChannelTree { - client: ConnectionHandler; - server: ServerEntry; - channels: ChannelEntry[]; - clients: ClientEntry[]; - currently_selected: ClientEntry | ServerEntry | ChannelEntry | (ClientEntry | ServerEntry)[]; - currently_selected_context_callback: (event) => any; - readonly client_mover: ClientMover; - private _tag_container: JQuery; - private _tag_entries: JQuery; - private _tree_detached: boolean; - private _show_queries: boolean; - private channel_last?: ChannelEntry; - private channel_first?: ChannelEntry; - private _focused; - private _listener_document_click; - private _listener_document_key; - constructor(client); - tag_tree(): JQuery; - destroy(); - hide_channel_tree(); - show_channel_tree(); - showContextMenu(x: number, y: number, on_close?: () => void); - initialiseHead(serverName: string, address: ServerAddress); - private __deleteAnimation(element: ChannelEntry | ClientEntry); - rootChannel(): ChannelEntry[]; - deleteChannel(channel: ChannelEntry); - insertChannel(channel: ChannelEntry); - findChannel(channelId: number): ChannelEntry | undefined; - find_channel_by_name(name: string, parent?: ChannelEntry, force_parent?: boolean): ChannelEntry | undefined; - moveChannel(channel: ChannelEntry, channel_previous: ChannelEntry, parent: ChannelEntry); - deleteClient(client: ClientEntry, animate_tag?: boolean); - registerClient(client: ClientEntry); - unregisterClient(client: ClientEntry); - private _update_timer: number; - private _reorder_channels; - insertClient(client: ClientEntry, channel: ChannelEntry): ClientEntry; - moveClient(client: ClientEntry, channel: ChannelEntry); - findClient?(clientId: number): ClientEntry; - find_client_by_dbid?(client_dbid: number): ClientEntry; - find_client_by_unique_id?(unique_id: string): ClientEntry; - private static same_selected_type(a, b); - onSelect(entry?: ChannelEntry | ClientEntry | ServerEntry, enforce_single?: boolean, flag_shift?: boolean); - private callback_multiselect_channel(event); - private callback_multiselect_client(event); - clientsByGroup(group: Group): ClientEntry[]; - clientsByChannel(channel: ChannelEntry): ClientEntry[]; - reset(); - spawnCreateChannel(parent?: ChannelEntry); - handle_resized(); - private select_next_channel(channel: ChannelEntry, select_client: boolean); - handle_key_press(event: KeyboardEvent); - toggle_server_queries(flag: boolean); - get_first_channel?(): ChannelEntry; - unsubscribe_all_channels(subscribe_specified?: boolean); - subscribe_all_channels(); -} - -/* File: D:\TeaSpeak\web\shared\js\utils\helpers.ts */ -declare namespace helpers { - export function hashPassword(password: string): Promise; -} -declare class LaterPromise extends Promise { - private _handle: Promise; - private _resolve: ($: T) => any; - private _reject: ($: any) => any; - private _time: number; - constructor(); - resolved(object: T); - rejected(reason); - function_rejected(); - 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?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): Promise; - /** - * 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?: ((reason: any) => TResult | PromiseLike) | undefined | null): Promise; -} -declare const copy_to_clipboard; - -/* File: D:\TeaSpeak\web\shared\js\voice\RecorderBase.ts */ -declare namespace audio { - export namespace recorder { - export interface InputDevice { - unique_id: string; - driver: string; - name: string; - default_input: boolean; - supported: boolean; - sample_rate: number; - channels: number; - } - export enum InputConsumerType { - CALLBACK, - NODE, - NATIVE - } - export interface InputConsumer { - type: InputConsumerType; - } - export interface CallbackInputConsumer extends InputConsumer { - callback_audio?: (buffer: AudioBuffer) => any; - callback_buffer?: (buffer: Float32Array, samples: number, channels: number) => any; - } - export interface NodeInputConsumer extends InputConsumer { - callback_node: (source_node: AudioNode) => any; - callback_disconnect: (source_node: AudioNode) => any; - } - export namespace filter { - export enum Type { - THRESHOLD, - VOICE_LEVEL, - STATE - } - export interface Filter { - type: Type; - is_enabled(): boolean; - } - export interface MarginedFilter { - get_margin_frames(): number; - set_margin_frames(value: number); - } - export interface ThresholdFilter extends Filter, MarginedFilter { - get_threshold(): number; - set_threshold(value: number): Promise; - get_attack_smooth(): number; - get_release_smooth(): number; - set_attack_smooth(value: number); - set_release_smooth(value: number); - callback_level?: (value: number) => any; - } - export interface VoiceLevelFilter extends Filter, MarginedFilter { - get_level(): number; - } - export interface StateFilter extends Filter { - set_state(state: boolean): Promise; - is_active(): boolean; /* if true the the filter allows data to pass */ - } - } - export enum InputState { - PAUSED, - INITIALIZING, - RECORDING, - DRY - } - export enum InputStartResult { - EOK = "eok", - EUNKNOWN = "eunknown", - EBUSY = "ebusy", - ENOTALLOWED = "enotallowed", - ENOTSUPPORTED = "enotsupported" - } - export interface AbstractInput { - callback_begin: () => any; - callback_end: () => any; - current_state(): InputState; - start(): Promise; - stop(): Promise; - current_device(): InputDevice | undefined; - set_device(device: InputDevice | undefined): Promise; - current_consumer(): InputConsumer | undefined; - set_consumer(consumer: InputConsumer): Promise; - get_filter(type: filter.Type): filter.Filter | undefined; - supports_filter(type: audio.recorder.filter.Type): boolean; - clear_filter(); - disable_filter(type: filter.Type); - enable_filter(type: filter.Type); - get_volume(): number; - set_volume(volume: number); - } - export interface LevelMeter { - device(): InputDevice; - set_observer(callback: (value: number) => any); - destory(); - } - } -} - -/* File: D:\TeaSpeak\web\shared\js\voice\RecorderProfile.ts */ -declare type VadType = "threshold" | "push_to_talk" | "active"; -declare interface RecorderProfileConfig { - version: number; - /* devices unique id */ - device_id: string | undefined; - volume: number; - vad_type: VadType; - vad_threshold: { - threshold: number; - }; - vad_push_to_talk: { - delay: number; - key_code: string; - key_ctrl: boolean; - key_windows: boolean; - key_shift: boolean; - key_alt: boolean; - }; -} -declare let default_recorder: RecorderProfile; -declare class RecorderProfile { - readonly name; - readonly volatile; - config: RecorderProfileConfig; - input: audio.recorder.AbstractInput; - current_handler: ConnectionHandler; - callback_support_change: () => any; - callback_start: () => any; - callback_stop: () => any; - callback_unmount: () => any; - record_supported: boolean; - private _ppt_hook: ppt.KeyHook; - private _ppt_timeout: NodeJS.Timer; - private _ppt_hook_registered: boolean; - constructor(name: string, volatile?: boolean); - initialize(): Promise; - private initialize_input(); - private load(); - private save(enforce?: boolean); - private reinitialize_filter(); - unmount(): Promise; - get_vad_type(); - set_vad_type(type: VadType); - get_vad_threshold(); - set_vad_threshold(value: number); - get_vad_ppt_key(): ppt.KeyDescriptor; - set_vad_ppt_key(key: ppt.KeyDescriptor); - get_vad_ppt_delay(); - set_vad_ppt_delay(value: number); - current_device(): audio.recorder.InputDevice | undefined; - set_device(device: audio.recorder.InputDevice | undefined): Promise; - get_volume(): number; - set_volume(volume: number); -} diff --git a/modules/renderer/imports/.copy_imports_shared_loader.d.ts b/modules/renderer/imports/.copy_imports_shared_loader.d.ts deleted file mode 100644 index 80b4757..0000000 --- a/modules/renderer/imports/.copy_imports_shared_loader.d.ts +++ /dev/null @@ -1,97 +0,0 @@ - -/* File: /home/wolverindev/TeaSpeak/Web-Client/shared/loader/loader.ts */ -declare interface Window { - tr(message: string): string; -} -declare namespace loader { - export namespace config { - export const loader_groups; - export const verbose; - export const error; - } - export type Task = { - name: string; - priority: number; /* tasks with the same priority will be executed in sync */ - function: () => Promise; - }; - export enum Stage { - /* - loading loader required files (incl this) - */ - INITIALIZING, - /* - setting up the loading process - */ - SETUP, - /* - loading all style sheet files - */ - STYLE, - /* - loading all javascript files - */ - JAVASCRIPT, - /* - loading all template files - */ - TEMPLATES, - /* - initializing static/global stuff - */ - JAVASCRIPT_INITIALIZING, - /* - finalizing load process - */ - FINALIZING, - /* - invoking main task - */ - LOADED, - DONE - } - export function get_cache_version(); - export function finished(); - export function running(); - export function register_task(stage: Stage, task: Task); - export function execute(): Promise; - export function execute_managed(); - export type DependSource = { - url: string; - depends: string[]; - }; - export type SourcePath = string | DependSource | string[]; - export class SyntaxError { - source: any; - constructor(source: any); - } - export function load_script(path: SourcePath): Promise; - export function load_scripts(paths: SourcePath[]): Promise; - export function load_style(path: SourcePath): Promise; - export function load_styles(paths: SourcePath[]): Promise; - export type ErrorHandler = (message: string, detail: string) => void; - export function critical_error(message: string, detail?: string); - export function critical_error_handler(handler?: ErrorHandler, override?: boolean): ErrorHandler; -} -declare let _fadeout_warned; -declare function fadeoutLoader(duration?, minAge?, ignoreAge?); - -/* File: /home/wolverindev/TeaSpeak/Web-Client/shared/loader/app.ts */ -declare interface Window { - $: JQuery; -} -declare namespace app { - export enum Type { - UNKNOWN, - CLIENT_RELEASE, - CLIENT_DEBUG, - WEB_DEBUG, - WEB_RELEASE - } - export let type: Type; - export function is_web(); - export function ui_version(); -} -declare const loader_javascript; -declare const loader_webassembly; -declare const loader_style; -declare function load_templates(): Promise; diff --git a/modules/renderer/imports/.gitignore b/modules/renderer/imports/.gitignore deleted file mode 100644 index 303120f..0000000 --- a/modules/renderer/imports/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -imports_shared.d.ts -imports_shared_loader.d.ts \ No newline at end of file diff --git a/modules/renderer/index.ts b/modules/renderer/index.ts index 4c4b3e5..c779169 100644 --- a/modules/renderer/index.ts +++ b/modules/renderer/index.ts @@ -1,12 +1,7 @@ -/// - -import {Arguments, parse_arguments, process_args} from "../shared/process-arguments"; -import * as electron from "electron"; -import {remote} from "electron"; +/* --------------- bootstrap --------------- */ +import * as rh from "./require-handler"; import * as crash_handler from "../crash_handler"; import * as path from "path"; -import * as os from "os"; -import ipcRenderer = electron.ipcRenderer; /* first of all setup crash handler */ { @@ -14,266 +9,155 @@ import ipcRenderer = electron.ipcRenderer; crash_handler.initialize_handler("renderer", is_electron_run); } -interface Window { - $: any; - jQuery: any; - jsrender: any; +/* some decls */ +declare global { + interface Window { + $: any; + jQuery: any; + jsrender: any; - impl_display_critical_error: any; - displayCriticalError: any; - teaclient_initialize: any; + impl_display_critical_error: any; + displayCriticalError: any; + teaclient_initialize: any; - open_connected_question: () => Promise; + open_connected_question: () => Promise; + } } +rh.initialize(path.join(__dirname, "backend-impl")); +/* --------------- main initialize --------------- */ +import {Arguments, parse_arguments, process_args} from "../shared/process-arguments"; +import * as electron from "electron"; +import {remote} from "electron"; +import * as os from "os"; +import * as loader from "tc-loader"; +import ipcRenderer = electron.ipcRenderer; -declare const window: Window; -export const require_native: NodeRequireFunction = id => require(id); -export const initialize = async () => { - /* we use out own jquery resource */ - loader.register_task(loader.Stage.JAVASCRIPT, { - name: "teaclient jquery", - function: jquery_initialize, - priority: 80 - }); +/* we use out own jquery resource */ +loader.register_task(loader.Stage.JAVASCRIPT, { + name: "teaclient jquery", + function: async () => { + window.$ = require("jquery"); + window.jQuery = window.$; + Object.assign(window.$, window.jsrender = require('jsrender')); + }, + priority: 80 +}); - loader.register_task(loader.Stage.JAVASCRIPT, { - name: "teaclient general", - function: load_basic_modules, - priority: 10 - }); +loader.register_task(loader.Stage.INITIALIZING, { + name: "teaclient initialize persistent storage", + function: async () => { + const storage = require("./PersistentLocalStorage"); + await storage.initialize(); + }, + priority: 90 +}); - loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, { - name: "teaclient javascript init", - function: load_modules, - priority: 50 - }); +loader.register_task(loader.Stage.INITIALIZING, { + name: "teaclient initialize logging", + function: async () => { + const logger = require("./logger"); + logger.setup(); + }, + priority: 80 +}); - loader.register_task(loader.Stage.INITIALIZING, { - name: "teaclient initialize modules", - function: module_loader_setup, - priority: 60 - }); - - loader.register_task(loader.Stage.INITIALIZING, { - name: "teaclient initialize persistent storage", - function: async () => { - const storage = require("./PersistentLocalStorage"); - await storage.initialize(); - }, - priority: 90 - }); - - loader.register_task(loader.Stage.INITIALIZING, { - name: "teaclient initialize logging", - function: initialize_logging, - priority: 80 - }); - - loader.register_task(loader.Stage.INITIALIZING, { - name: "teaclient initialize error", - function: initialize_error_handler, - priority: 100 - }); - - loader.register_task(loader.Stage.INITIALIZING, { - name: "teaclient initialize arguments", - function: async () => { - parse_arguments(); - if(process_args.has_value(Arguments.DUMMY_CRASH_RENDERER)) - crash_handler.handler.crash(); +loader.register_task(loader.Stage.INITIALIZING, { + name: "teaclient initialize error", + function: async () => { + const _impl = message => { if(!process_args.has_flag(Arguments.DEBUG)) { - window.open_connected_question = () => remote.dialog.showMessageBox(remote.getCurrentWindow(), { - type: 'question', - buttons: ['Yes', 'No'], - title: 'Confirm', - message: 'Are you really sure?\nYou\'re still connected!' - }).then(result => result.response === 0); - } - }, - priority: 110 - }); + console.error("Displaying critical error: %o", message); + message = message.replace(/
/i, "\n"); - loader.register_task(loader.Stage.INITIALIZING, { - name: 'gdb-waiter', - function: async () => { - if(process_args.has_flag(Arguments.DEV_TOOLS_GDB)) { - console.log("Process ID: %d", process.pid); - await new Promise(resolve => { - console.log("Waiting for continue!"); - - const listener = () => { - console.log("Continue"); - document.removeEventListener('click', listener); - resolve(); - }; - document.addEventListener('click', listener); + const win = remote.getCurrentWindow(); + remote.dialog.showMessageBox({ + type: "error", + buttons: ["exit"], + title: "A critical error happened!", + message: message }); + + win.close(); + } else { + console.error("Received critical error: %o", message); + console.error("Ignoring error due to the debug mode"); } - }, - priority: 100 - }); + }; - loader.register_task(loader.Stage.LOADED, { - name: "argv connect", - function: async () => { - ipcRenderer.send('basic-action', "parse-connect-arguments"); - }, - priority: 0 - }) -}; + if(window.impl_display_critical_error) + window.impl_display_critical_error = _impl; + else + window.displayCriticalError = _impl; + }, + priority: 100 +}); -const jquery_initialize = async () => { - window.$ = require("jquery"); - window.jQuery = window.$; - Object.assign(window.$, window.jsrender = require('jsrender')); -}; - -const initialize_logging = async () => { - const logger = require("./logger"); - logger.setup(); -}; - -const initialize_error_handler = async () => { - const _impl = message => { +loader.register_task(loader.Stage.INITIALIZING, { + name: "teaclient initialize arguments", + function: async () => { + parse_arguments(); + if(process_args.has_value(Arguments.DUMMY_CRASH_RENDERER)) + crash_handler.handler.crash(); if(!process_args.has_flag(Arguments.DEBUG)) { - console.error("Displaying critical error: %o", message); - message = message.replace(/
/i, "\n"); + window.open_connected_question = () => remote.dialog.showMessageBox(remote.getCurrentWindow(), { + type: 'question', + buttons: ['Yes', 'No'], + title: 'Confirm', + message: 'Are you really sure?\nYou\'re still connected!' + }).then(result => result.response === 0); + } + }, + priority: 110 +}); - const win = remote.getCurrentWindow(); - remote.dialog.showMessageBox({ - type: "error", - buttons: ["exit"], - title: "A critical error happened!", - message: message +loader.register_task(loader.Stage.INITIALIZING, { + name: 'gdb-waiter', + function: async () => { + if(process_args.has_flag(Arguments.DEV_TOOLS_GDB)) { + console.log("Process ID: %d", process.pid); + await new Promise(resolve => { + console.log("Waiting for continue!"); + + const listener = () => { + console.log("Continue"); + document.removeEventListener('click', listener); + resolve(); + }; + document.addEventListener('click', listener); }); - - win.close(); - } else { - console.error("Received critical error: %o", message); - console.error("Ignoring error due to the debug mode"); } - }; + }, + priority: 100 +}); - if(window.impl_display_critical_error) - window.impl_display_critical_error = _impl; - else - window.displayCriticalError = _impl; -}; +loader.register_task(loader.Stage.LOADED, { + name: "argv connect", + function: async () => { + ipcRenderer.send('basic-action', "parse-connect-arguments"); + }, + priority: 0 +}); -const module_loader_setup = async () => { - const native_paths = (() => { - const app_path = (remote || electron).app.getAppPath(); - const result = []; - result.push(app_path + "/native/build/" + os.platform() + "_" + os.arch() + "/"); - if(app_path.endsWith(".asar")) - result.push(path.join(path.dirname(app_path), "natives")); - return result; - })(); - window["require_setup"] = _mod => { - if(!_mod || !_mod.paths) return; - _mod.paths.push(...native_paths); - const original_require = _mod.__proto__.require; - if(!_mod.proxied) { - _mod.require = (path: string) => { - if(path.endsWith("imports/imports_shared")) { - console.log("Proxy require for %s. Using 'window' as result.", path); - return window; - } - return original_require.apply(_mod, [path]); - }; - _mod.proxied = true; - } - }; -}; - -const load_basic_modules = async () => { - require("./logger"); - - require("./audio/AudioPlayer"); /* setup audio */ - require("./audio/AudioRecorder"); /* setup audio */ - require("./audio/sounds"); /* setup audio */ -}; - -const load_modules = async () => { - window["require_setup"](this); - - console.log(module.paths); - console.log("Loading native extensions..."); - try { +loader.register_task(loader.Stage.JAVASCRIPT_INITIALIZING, { + name: "teaclient load adapters", + function: async () => { + /* all files which replaces a native driver */ try { require("./version"); - } catch(error) { - console.error("Failed to load version extension"); - console.dir(error); - throw error; - } - try { - require("./app_backend"); - } catch(error) { - console.error("Failed to load renderer app backend"); - console.dir(error); - throw error; - } - - try { - const helper = require("./icon-helper"); - await helper.initialize(); - } catch(error) { - console.error("Failed to load the icon helper extension"); - console.dir(error); - throw error; - } - try { - require("./ppt"); - } catch(error) { - console.error("Failed to load ppt"); - console.dir(error); - throw error; - } - try { - require("./connection/ServerConnection"); - } catch(error) { - console.error("Failed to load server connection extension"); - console.dir(error); - throw error; - } - try { - require("./connection/FileTransfer"); - } catch(error) { - console.error("Failed to load file transfer extension"); - console.dir(error); - throw error; - } - try { - require("./dns/dns_resolver"); - } catch(error) { - console.error("Failed to load dns extension"); - console.dir(error); - throw error; - } - try { require("./menu"); - } catch(error) { - console.error("Failed to load menu extension"); - console.dir(error); - throw error; - } - try { require("./context-menu"); - } catch(error) { - console.error("Failed to load context menu extension"); - console.dir(error); + require("./app_backend"); + require("./icon-helper").initialize(); + } catch (error) { + console.log(error); + window.displayCriticalError("Failed to load native extensions: " + error); throw error; } - } catch(error){ - console.log(error); - window.displayCriticalError("Failed to load native extensions: " + error); - throw error; - } - console.log("Loaded native extensions"); + remote.getCurrentWindow().on('focus', () => remote.getCurrentWindow().flashFrame(false)); + }, + priority: 60 +}); - remote.getCurrentWindow().on('focus', () => remote.getCurrentWindow().flashFrame(false)); - // remote.getCurrentWindow().flashFrame(true); -}; \ No newline at end of file +export async function initialize() { } \ No newline at end of file diff --git a/modules/renderer/menu.ts b/modules/renderer/menu.ts index a011ae8..e6bf27b 100644 --- a/modules/renderer/menu.ts +++ b/modules/renderer/menu.ts @@ -1,257 +1,246 @@ import {class_to_image} from "./icon-helper"; - -window["require_setup"](module); - import * as electron from "electron"; -//import {top_menu as dtop_menu, Icon} from "./imports/imports_shared"; - -/// -import dtop_menu = top_menu; +import * as mbar from "tc-shared/ui/frames/MenuBar"; import {Arguments, process_args} from "../shared/process-arguments"; -namespace _top_menu { +import ipcRenderer = electron.ipcRenderer; +import {Icon} from "tc-shared/FileManager"; +namespace native { import ipcRenderer = electron.ipcRenderer; - namespace native { - import ipcRenderer = electron.ipcRenderer; - let _item_index = 1; + let _item_index = 1; - abstract class NativeMenuBase { - protected _handle: NativeMenuBar; - protected _click: () => any; - id: string; + abstract class NativeMenuBase { + protected _handle: NativeMenuBar; + protected _click: () => any; + id: string; - protected constructor(handle: NativeMenuBar, id?: string) { - this._handle = handle; - this.id = id || ("item_" + (_item_index++)); - } - - abstract build() : electron.MenuItemConstructorOptions; - abstract items(): (dtop_menu.MenuItem | dtop_menu.HRItem)[]; - - trigger_click() { - if(this._click) - this._click(); - } + protected constructor(handle: NativeMenuBar, id?: string) { + this._handle = handle; + this.id = id || ("item_" + (_item_index++)); } - class NativeMenuItem extends NativeMenuBase implements dtop_menu.MenuItem { - private _items: (NativeMenuItem | NativeHrItem)[] = []; - private _label: string; - private _enabled: boolean = true; - private _visible: boolean = true; + abstract build() : electron.MenuItemConstructorOptions; + abstract items(): (mbar.MenuItem | mbar.HRItem)[]; - private _icon_data: string; + trigger_click() { + if(this._click) + this._click(); + } + } - constructor(handle: NativeMenuBar) { - super(handle); + class NativeMenuItem extends NativeMenuBase implements mbar.MenuItem { + private _items: (NativeMenuItem | NativeHrItem)[] = []; + private _label: string; + private _enabled: boolean = true; + private _visible: boolean = true; - } + private _icon_data: string; - append_hr(): dtop_menu.HRItem { - const item = new NativeHrItem(this._handle); - this._items.push(item); - return item; - } + constructor(handle: NativeMenuBar) { + super(handle); - append_item(label: string): dtop_menu.MenuItem { - const item = new NativeMenuItem(this._handle); - item.label(label); - this._items.push(item); - return item; - } - - click(callback: () => any): this { - this._click = callback; - return this; - } - - delete_item(item: dtop_menu.MenuItem | dtop_menu.HRItem) { - const i_index = this._items.indexOf(item as any); - if(i_index < 0) return; - this._items.splice(i_index, 1); - } - - disabled(value?: boolean): boolean { - if(typeof(value) === "boolean") - this._enabled = !value; - return !this._enabled; - } - - icon(klass?: string | Promise | Icon): string { - if(typeof(klass) === "string") { - const buffer = class_to_image(klass); - if(buffer) - this._icon_data = buffer.toDataURL(); - } - return ""; - } - - items(): (dtop_menu.MenuItem | dtop_menu.HRItem)[] { - return this._items; - } - - label(value?: string): string { - if(typeof(value) === "string") - this._label = value; - return this._label; - } - - visible(value?: boolean): boolean { - if(typeof(value) === "boolean") - this._visible = value; - return this._visible; - } - - build(): Electron.MenuItemConstructorOptions { - return { - id: this.id, - - label: this._label || "", - - submenu: this._items.length > 0 ? this._items.map(e => e.build()) : undefined, - enabled: this._enabled, - visible: this._visible, - - icon: this._icon_data - } - } } - class NativeHrItem extends NativeMenuBase implements dtop_menu.HRItem { - constructor(handle: NativeMenuBar) { - super(handle); - } - - build(): Electron.MenuItemConstructorOptions { - return { - type: 'separator', - id: this.id - } - } - - items(): (dtop_menu.MenuItem | dtop_menu.HRItem)[] { - return []; - } + append_hr(): mbar.HRItem { + const item = new NativeHrItem(this._handle); + this._items.push(item); + return item; } - function is_similar_deep(a, b) { - if(typeof(a) !== typeof(b)) - return false; - if(typeof(a) !== "object") - return a === b; - - const aProps = Object.keys(a); - const bProps = Object.keys(b); - - if (aProps.length != bProps.length) - return false; - - for (let i = 0; i < aProps.length; i++) { - const propName = aProps[i]; - - if(!is_similar_deep(a[propName], b[propName])) - return false; - } - - return true; + append_item(label: string): mbar.MenuItem { + const item = new NativeMenuItem(this._handle); + item.label(label); + this._items.push(item); + return item; } + click(callback: () => any): this { + this._click = callback; + return this; + } - export class NativeMenuBar implements dtop_menu.MenuBarDriver { - private static _instance: NativeMenuBar; + delete_item(item: mbar.MenuItem | mbar.HRItem) { + const i_index = this._items.indexOf(item as any); + if(i_index < 0) return; + this._items.splice(i_index, 1); + } - private menu: electron.Menu; - private _items: NativeMenuItem[] = []; - private _current_menu: electron.MenuItemConstructorOptions[]; + disabled(value?: boolean): boolean { + if(typeof(value) === "boolean") + this._enabled = !value; + return !this._enabled; + } - public static instance() : NativeMenuBar { - if(!this._instance) - this._instance = new NativeMenuBar(); - return this._instance; + icon(klass?: string | Promise | Icon): string { + if(typeof(klass) === "string") { + const buffer = class_to_image(klass); + if(buffer) + this._icon_data = buffer.toDataURL(); } + return ""; + } - append_item(label: string): dtop_menu.MenuItem { - const item = new NativeMenuItem(this); - item.label(label); - this._items.push(item); - return item; - } + items(): (mbar.MenuItem | mbar.HRItem)[] { + return this._items; + } - delete_item(item: dtop_menu.MenuItem) { - const i_index = this._items.indexOf(item as any); - if(i_index < 0) return; - this._items.splice(i_index, 1); - } + label(value?: string): string { + if(typeof(value) === "string") + this._label = value; + return this._label; + } - flush_changes() { - const target_menu = this.build_menu(); - if(is_similar_deep(target_menu, this._current_menu)) - return; + visible(value?: boolean): boolean { + if(typeof(value) === "boolean") + this._visible = value; + return this._visible; + } - this._current_menu = target_menu; - ipcRenderer.send('top-menu', target_menu); - } + build(): Electron.MenuItemConstructorOptions { + return { + id: this.id, - private build_menu() : electron.MenuItemConstructorOptions[] { - return this._items.map(e => e.build()); - } + label: this._label || "", - items(): dtop_menu.MenuItem[] { - return this._items; - } + submenu: this._items.length > 0 ? this._items.map(e => e.build()) : undefined, + enabled: this._enabled, + visible: this._visible, - initialize() { - this.menu = new electron.remote.Menu(); - ipcRenderer.on('top-menu', (event, clicked_item) => { - console.log("Item %o clicked", clicked_item); - const check_item = (item: NativeMenuBase) => { - if(item.id == clicked_item) { - item.trigger_click(); - return true; - } - for(const child of item.items()) - if(check_item(child as NativeMenuBase)) - return true; - }; - - for(const item of this._items) - if(check_item(item)) - return; - }); + icon: this._icon_data } } } - //Global variable - // @ts-ignore - top_menu.set_driver(native.NativeMenuBar.instance()); + class NativeHrItem extends NativeMenuBase implements mbar.HRItem { + constructor(handle: NativeMenuBar) { + super(handle); + } + + build(): Electron.MenuItemConstructorOptions { + return { + type: 'separator', + id: this.id + } + } + + items(): (mbar.MenuItem | mbar.HRItem)[] { + return []; + } + } + + function is_similar_deep(a, b) { + if(typeof(a) !== typeof(b)) + return false; + if(typeof(a) !== "object") + return a === b; + + const aProps = Object.keys(a); + const bProps = Object.keys(b); + + if (aProps.length != bProps.length) + return false; + + for (let i = 0; i < aProps.length; i++) { + const propName = aProps[i]; + + if(!is_similar_deep(a[propName], b[propName])) + return false; + } + + return true; + } - const call_basic_action = (name: string, ...args: any[]) => ipcRenderer.send('basic-action', name, ...args); - top_menu.native_actions = { - open_change_log() { - call_basic_action("open-changelog"); - }, + export class NativeMenuBar implements mbar.MenuBarDriver { + private static _instance: NativeMenuBar; - check_native_update() { - call_basic_action("check-native-update"); - }, + private menu: electron.Menu; + private _items: NativeMenuItem[] = []; + private _current_menu: electron.MenuItemConstructorOptions[]; - quit() { - call_basic_action("quit"); - }, + public static instance() : NativeMenuBar { + if(!this._instance) + this._instance = new NativeMenuBar(); + return this._instance; + } - open_dev_tools() { - call_basic_action("open-dev-tools"); - }, + append_item(label: string): mbar.MenuItem { + const item = new NativeMenuItem(this); + item.label(label); + this._items.push(item); + return item; + } - reload_page() { - call_basic_action("reload-window") - }, + delete_item(item: mbar.MenuItem) { + const i_index = this._items.indexOf(item as any); + if(i_index < 0) return; + this._items.splice(i_index, 1); + } - show_dev_tools() { return process_args.has_flag(Arguments.DEV_TOOLS); } - }; + flush_changes() { + const target_menu = this.build_menu(); + if(is_similar_deep(target_menu, this._current_menu)) + return; + + this._current_menu = target_menu; + ipcRenderer.send('top-menu', target_menu); + } + + private build_menu() : electron.MenuItemConstructorOptions[] { + return this._items.map(e => e.build()); + } + + items(): mbar.MenuItem[] { + return this._items; + } + + initialize() { + this.menu = new electron.remote.Menu(); + ipcRenderer.on('top-menu', (event, clicked_item) => { + console.log("Item %o clicked", clicked_item); + const check_item = (item: NativeMenuBase) => { + if(item.id == clicked_item) { + item.trigger_click(); + return true; + } + for(const child of item.items()) + if(check_item(child as NativeMenuBase)) + return true; + }; + + for(const item of this._items) + if(check_item(item)) + return; + }); + } + } } +mbar.set_driver(native.NativeMenuBar.instance()); +// @ts-ignore +mbar.native_actions = { + open_change_log() { + call_basic_action("open-changelog"); + }, -export {}; \ No newline at end of file + check_native_update() { + call_basic_action("check-native-update"); + }, + + quit() { + call_basic_action("quit"); + }, + + open_dev_tools() { + call_basic_action("open-dev-tools"); + }, + + reload_page() { + call_basic_action("reload-window") + }, + + show_dev_tools() { return process_args.has_flag(Arguments.DEV_TOOLS); } +}; + + +const call_basic_action = (name: string, ...args: any[]) => ipcRenderer.send('basic-action', name, ...args); \ No newline at end of file diff --git a/modules/renderer/ppt.ts b/modules/renderer/ppt.ts index cdfd1af..82d8df2 100644 --- a/modules/renderer/ppt.ts +++ b/modules/renderer/ppt.ts @@ -1,137 +1,141 @@ -window["require_setup"](module); +import {KeyEvent as NKeyEvent, RegisterCallback, UnregisterCallback} from "tc-native/ppt"; +import {EventType, KeyEvent, KeyHook, SpecialKey} from "tc-shared/PPTListener"; +import {tr} from "tc-shared/i18n/localize"; +import {LogCategory} from "tc-shared/log"; +import * as log from "tc-shared/log"; -import {KeyEvent as NKeyEvent} from "teaclient_ppt"; -namespace _ppt { - let key_listener: ((_: ppt.KeyEvent) => any)[] = []; +let key_listener: ((_: KeyEvent) => any)[] = []; - let native_ppt; - function listener_key(type: ppt.EventType, nevent: NKeyEvent) { - if(nevent.key_code === 'VoidSymbol' || nevent.key_code === 'error') - nevent.key_code = undefined; /* trigger event for state update */ +function listener_key(type: EventType, nevent: NKeyEvent) { + if(nevent.key_code === 'VoidSymbol' || nevent.key_code === 'error') + nevent.key_code = undefined; /* trigger event for state update */ - let event: ppt.KeyEvent = { - type: type, + let event: KeyEvent = { + type: type, - key: nevent.key_code, - key_code: nevent.key_code, + key: nevent.key_code, + key_code: nevent.key_code, - key_ctrl: nevent.key_ctrl, - key_shift: nevent.key_shift, - key_alt: nevent.key_alt, - key_windows: nevent.key_windows - } as any; - //console.debug("Trigger key event %o", type); - - for (const listener of key_listener) - listener && listener(event); - } - - function native_keyhook(event: NKeyEvent) { - //console.log("Native event!: %o", event); - - if(event.type == 0) - listener_key(ppt.EventType.KEY_PRESS, event); - else if(event.type == 1) - listener_key(ppt.EventType.KEY_RELEASE, event); - else if(event.type == 2) - listener_key(ppt.EventType.KEY_TYPED, event); - else - console.warn(tr("Received unknown native event: %o"), event); - } - - export async function initialize() : Promise { - native_ppt = require("teaclient_ppt"); - - register_key_listener(listener_hook); - native_ppt.RegisterCallback(native_keyhook); - } - - export function finalize() { - unregister_key_listener(listener_hook); - native_ppt.UnregisterCallback(native_keyhook); - } - - export function register_key_listener(listener: (_: ppt.KeyEvent) => any) { - key_listener.push(listener); - } - - export function unregister_key_listener(listener: (_: ppt.KeyEvent) => any) { - key_listener.remove(listener); - } - - let key_hooks: ppt.KeyHook[] = []; - - interface CurrentState { - keys: {[code: string]:ppt.KeyEvent}; - special: { [key:number]:boolean }; - } - let current_state: CurrentState = { - special: [] + key_ctrl: nevent.key_ctrl, + key_shift: nevent.key_shift, + key_alt: nevent.key_alt, + key_windows: nevent.key_windows } as any; + //console.debug("Trigger key event %o", type); - let key_hooks_active: ppt.KeyHook[] = []; - - function listener_hook(event: ppt.KeyEvent) { - 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[event.key_code] = undefined; - if(event.type == ppt.EventType.KEY_PRESS) { - current_state[event.key_code] = event; - - 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(); - log.trace(LogCategory.GENERAL, tr("Trigger key press for %o!"), hook); - } - } - } - - //We have a new situation - for(const hook of old_hooks) { - //Do not test for meta key states because they could differ in a key release event - if(hook.key_code === event.key_code) { - if(hook.callback_release) { - hook.callback_release(); - log.trace(LogCategory.GENERAL, tr("Trigger key release for %o!"), hook); - } - } else { - new_hooks.push(hook); - } - } - key_hooks_active = new_hooks; - } - - - export function register_key_hook(hook: ppt.KeyHook) { - key_hooks.push(hook); - } - - export function unregister_key_hook(hook: ppt.KeyHook) { - key_hooks.remove(hook); - key_hooks_active.remove(hook); - } - - export function key_pressed(code: string | ppt.SpecialKey) : boolean { - if(typeof(code) === 'string') - return typeof(current_state[code]) === "object"; - return current_state.special[code]; - } + for (const listener of key_listener) + listener && listener(event); } -Object.assign(window["ppt"] || (window["ppt"] = {} as any), _ppt); -console.dir(_ppt); \ No newline at end of file + +function native_keyhook(event: NKeyEvent) { + //console.log("Native event!: %o", event); + + if(event.type == 0) + listener_key(EventType.KEY_PRESS, event); + else if(event.type == 1) + listener_key(EventType.KEY_RELEASE, event); + else if(event.type == 2) + listener_key(EventType.KEY_TYPED, event); + else + console.warn(tr("Received unknown native event: %o"), event); +} + +export async function initialize() : Promise { + register_key_listener(listener_hook); + RegisterCallback(native_keyhook); +} + +export function finalize() { + unregister_key_listener(listener_hook); + UnregisterCallback(native_keyhook); +} + +export function register_key_listener(listener: (_: KeyEvent) => any) { + key_listener.push(listener); +} + +export function unregister_key_listener(listener: (_: KeyEvent) => any) { + const index = key_listener.findIndex(e => e === listener); + if(index !== -1) key_listener.splice(index, 1); +} + +let key_hooks: KeyHook[] = []; + +interface CurrentState { + keys: {[code: string]:KeyEvent}; + special: { [key:number]:boolean }; +} +let current_state: CurrentState = { + special: [] +} as any; + +let key_hooks_active: KeyHook[] = []; + +function listener_hook(event: KeyEvent) { + if(event.type == EventType.KEY_TYPED) + return; + + let old_hooks = [...key_hooks_active]; + let new_hooks = []; + + current_state.special[SpecialKey.ALT] = event.key_alt; + current_state.special[SpecialKey.CTRL] = event.key_ctrl; + current_state.special[SpecialKey.SHIFT] = event.key_shift; + current_state.special[SpecialKey.WINDOWS] = event.key_windows; + + current_state[event.key_code] = undefined; + if(event.type == EventType.KEY_PRESS) { + current_state[event.key_code] = event; + + 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); + const index = old_hooks.findIndex(e => e === hook); + if(index !== -1 && hook.callback_press) { + old_hooks.splice(index, 1); + hook.callback_press(); + log.trace(LogCategory.GENERAL, tr("Trigger key press for %o!"), hook); + } + } + } + + //We have a new situation + for(const hook of old_hooks) { + //Do not test for meta key states because they could differ in a key release event + if(hook.key_code === event.key_code) { + if(hook.callback_release) { + hook.callback_release(); + log.trace(LogCategory.GENERAL, tr("Trigger key release for %o!"), hook); + } + } else { + new_hooks.push(hook); + } + } + key_hooks_active = new_hooks; +} + + +export function register_key_hook(hook: KeyHook) { + key_hooks.push(hook); +} + +export function unregister_key_hook(hook: KeyHook) { + let index; + + index = key_hooks.findIndex(e => e === hook); + if(index !== -1) key_hooks.splice(index, 1); + + index = key_hooks_active.findIndex(e => e === hook); + if(index !== -1) key_hooks_active.splice(index, 1); +} + +export function key_pressed(code: string | SpecialKey) : boolean { + if(typeof(code) === 'string') + return typeof(current_state[code]) === "object"; + return current_state.special[code]; +} \ No newline at end of file diff --git a/modules/renderer/require-handler.ts b/modules/renderer/require-handler.ts new file mode 100644 index 0000000..29aa6d6 --- /dev/null +++ b/modules/renderer/require-handler.ts @@ -0,0 +1,106 @@ +import * as path from "path"; +import {remote} from "electron"; +import * as electron from "electron"; +import * as os from "os"; + +const Module = require("module"); + +interface ModuleOverride { + name?: string, + test: string | RegExp | ((request: string) => boolean); + callback: (this: string, request: string, parent?: NodeJS.Module) => any; +} +const overrides: ModuleOverride[] = []; + +function proxied_load(request: string, parent?: NodeJS.Module) { + for(const override of overrides) { + let test_satisfied = false; + if(typeof override.test === "string") { + test_satisfied = override.test === request; + } else if(typeof override.test === "function") { + test_satisfied = override.test(request); + } else if(typeof override === "object") { + if(override.test instanceof RegExp) + test_satisfied = !!request.match(override.test); + } + + if(test_satisfied) { + //console.log("Using override %s for %s", override.name || "unnamed", request); + return override.callback.apply(this, arguments); + } + } + //console.log("No override found for %s", request); + return proxied_load.original_load.apply(this, arguments); +} + +function shared_backend_loader(request: string) { + if(!request.startsWith("tc-backend/")) throw "invalid target"; + const target = request.substr(11); + + return require(path.join(backend_root, target)); +} + +namespace proxied_load { + export let original_load: typeof Module.require; +} + +let backend_root: string; +export function initialize(backend_root_: string) { + backend_root = backend_root_; + + proxied_load.original_load = Module._load; + Module._load = proxied_load; + + window["backend-loader"] = { + require: shared_backend_loader + }; +} + + +overrides.push({ + name: "tc-loader", + test: "tc-loader", + callback: () => window["loader"] +}); + +overrides.push({ + name: "native loader", + test: /^tc-native\/[a-zA-Z_-]+$/, + callback: request => { + const name = request.substr(10); + + const file_mapping = { + connection: "teaclient_connection.node", + ppt: "teaclient_ppt.node", + dns: "teaclient_dns.node" + }; + + if(typeof file_mapping[name] !== "string") + throw "unknown native module"; + + const app_path = (remote || electron).app.getAppPath(); + const target_path = path.join(app_path, "native", "build", os.platform() + "_" + os.arch(), file_mapping[name]); + return require(target_path); + } +}); + +overrides.push({ + name: "shared loader", + test: /^tc-shared\/.*/, + callback: request => { + const webpack_path = path.dirname("shared/js/" + request.substr(10)); //FIXME: Get the prefix from a variable! + const loader = require("tc-loader"); + + const mapping = loader.module_mapping().find(e => e.application === "client-app"); //FIXME: Variable name! + if(!mapping) throw "missing mapping"; + + const entries = mapping.modules.filter(e => e.context === webpack_path); + if(!entries.length) throw "unknown target path"; + + const basename = path.basename(request, path.extname(request)); + const entry = entries.find(e => path.basename(e.resource, path.extname(e.resource)) === basename); + if(!entry) throw "unknown import"; + + return window["shared-require"](entry.id); + } +}); \ No newline at end of file diff --git a/modules/renderer/version.ts b/modules/renderer/version.ts index b720eee..db314ea 100644 --- a/modules/renderer/version.ts +++ b/modules/renderer/version.ts @@ -1,3 +1,4 @@ +//FIXME! namespace native { const remote = require('electron').remote; export async function client_version() : Promise { diff --git a/native/dns/exports/exports.d.ts b/native/dns/exports/exports.d.ts index 80b69a6..811cf94 100644 --- a/native/dns/exports/exports.d.ts +++ b/native/dns/exports/exports.d.ts @@ -1,4 +1,4 @@ -declare module "teaclient_dns" { +declare module "tc-native/dns" { export function resolve_cr(host: string, port: number, callback: (result: string | {host: string, port: number}) => any); export function initialize(); } \ No newline at end of file diff --git a/native/ppt/exports/exports.d.ts b/native/ppt/exports/exports.d.ts index d8d442f..fd339d4 100644 --- a/native/ppt/exports/exports.d.ts +++ b/native/ppt/exports/exports.d.ts @@ -1,4 +1,4 @@ -declare module "teaclient_ppt" { +declare module "tc-native/ppt" { enum KeyEventType { PRESS = 0, RELEASE = 1, diff --git a/native/serverconnection/exports/exports.d.ts b/native/serverconnection/exports/exports.d.ts index 3f270e6..c01dcbb 100644 --- a/native/serverconnection/exports/exports.d.ts +++ b/native/serverconnection/exports/exports.d.ts @@ -1,4 +1,4 @@ -declare module "teaclient_connection" { +declare module "tc-native/connection" { export enum ServerType { UNKNOWN, TEASPEAK, diff --git a/native/serverconnection/src/connection/ProtocolHandler.cpp b/native/serverconnection/src/connection/ProtocolHandler.cpp index 2fe370d..46141fe 100644 --- a/native/serverconnection/src/connection/ProtocolHandler.cpp +++ b/native/serverconnection/src/connection/ProtocolHandler.cpp @@ -139,6 +139,7 @@ void ProtocolHandler::execute_resend() { this->handle->close_connection(); return; } + log_trace(category::connection, tr("Resended {}"), resended); auto socket = this->handle->get_socket(); if(socket) { @@ -164,6 +165,7 @@ void ProtocolHandler::progress_packet(const pipes::buffer_view &buffer) { auto packet_type = packet->type(); auto packet_id = packet->packetId(); auto ordered = packet_type.type() == protocol::COMMAND || packet_type.type() == protocol::COMMAND_LOW; + log_trace(category::connection, tr("Received packet {} with id {}"), packet->type().name(), packet->packetId()); /* special handling */ if(packet_type.type() == protocol::INIT1) { @@ -253,6 +255,7 @@ void ProtocolHandler::progress_packet(const pipes::buffer_view &buffer) { unique_lock queue_lock(read_queue.buffer_lock); if(ordered) { /* ordered */ + log_trace(category::connection, tr("Inserting packet {} with id {}"), packet->type().name(), packet->packetId()); if(!read_queue.insert_index(packet_id, std::forward>(packet))) { log_warn(category::connection, tr("Failed to insert ordered packet into queue. ({} | {} | {})"), packet_type.name(), read_queue.current_index(), packet_id); } @@ -519,7 +522,7 @@ bool ProtocolHandler::create_datagram_packets(std::vector &result void ProtocolHandler::send_command(const ts::Command &cmd, const std::function &ack_callback) { auto data = cmd.build(); auto packet = make_shared(PacketTypeInfo::Command, pipes::buffer_view{data.data(), data.size()}); - if(ack_callback) { + if(ack_callback || true) { auto begin = chrono::system_clock::now(); packet->setListener(make_unique>()); packet->getListener()->waitAndGetLater([ack_callback, begin](bool f) { @@ -527,7 +530,7 @@ void ProtocolHandler::send_command(const ts::Command &cmd, const std::function(end - begin).count()); + log_trace(category::connection, tr("Time needed for command: {}ms. Success: {}"), chrono::duration_cast(end - begin).count(), f); }); } packet->enable_flag(PacketFlag::NewProtocol); @@ -541,6 +544,18 @@ void ProtocolHandler::send_packet(const std::shared_ptrtype() == protocol::PacketTypeInfo::Command && this->connection_state == connection_state::CONNECTED && false) { + ts::Command cmd{"whoami"}; + auto data = cmd.build(); + auto p1 = make_shared(PacketTypeInfo::Command, pipes::buffer_view{data.data(), data.size()}); + if(!this->create_datagram_packets(result, p1)) + log_error(category::connection, tr("failed to encode trap")); + std::reverse(result.begin(), result.end()); + } + } + + log_trace(category::connection, tr("Split up {} {} to {} packets. Ack waiting: {}"), packet->packetId(), packet->type().name(), result.size(), this->acknowledge_handler.awaiting_acknowledge()); auto socket = this->handle->get_socket(); if(!socket) { log_error(category::connection, tr("Failed to get socket!")); diff --git a/native/serverconnection/src/connection/ProtocolHandlerPackets.cpp b/native/serverconnection/src/connection/ProtocolHandlerPackets.cpp index 83c1cc2..bb28407 100644 --- a/native/serverconnection/src/connection/ProtocolHandlerPackets.cpp +++ b/native/serverconnection/src/connection/ProtocolHandlerPackets.cpp @@ -1,7 +1,5 @@ #include "ProtocolHandler.h" -#include "ServerConnection.h" #include "Socket.h" -#include #include #include #include @@ -21,7 +19,9 @@ using namespace ts; void ProtocolHandler::handlePacketAck(const std::shared_ptr &ack) { string error; log_trace(category::connection, tr("Handle packet acknowledge for {}"), be2le16(&ack->data()[0])); - this->acknowledge_handler.process_acknowledge(ack->type().type(), ack->data(), error); + if(!this->acknowledge_handler.process_acknowledge(ack->type().type(), ack->data(), error)) { + log_warn(category::connection, tr("Failed to handle acknowledge {}: {}"), be2le16(&ack->data()[0]) ,error); + } } void ProtocolHandler::handlePacketCommand(const std::shared_ptr &packet) { diff --git a/native/serverconnection/src/connection/ServerConnection.cpp b/native/serverconnection/src/connection/ServerConnection.cpp index a2a044d..ab6eb6a 100644 --- a/native/serverconnection/src/connection/ServerConnection.cpp +++ b/native/serverconnection/src/connection/ServerConnection.cpp @@ -496,6 +496,7 @@ NAN_METHOD(ServerConnection::send_command) { cmd[strobf("hwid").string()] = system_uuid(); /* we dont want anybody to patch this out */ } } + log_trace(category::audio, tr("Sending data {}"), cmd.command()); this->protocol_handler->send_command(cmd); auto end = chrono::system_clock::now(); } diff --git a/package-lock.json b/package-lock.json index d1a4d5d..579b64a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "TeaClient", - "version": "1.4.3-2", + "version": "1.4.4", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -17,6 +17,18 @@ "got": "^9.6.0", "sanitize-filename": "^1.6.2", "sumchecker": "^3.0.1" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } } }, "@sindresorhus/is": { @@ -383,6 +395,11 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -777,23 +794,104 @@ } }, "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", + "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", "dev": true, "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.3.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "readdirp": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", + "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", + "dev": true, + "requires": { + "picomatch": "^2.0.7" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } } }, "chownr": { @@ -1489,9 +1587,9 @@ } }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "ms": { "version": "2.0.0", @@ -1868,9 +1966,9 @@ } }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, "ms": { @@ -2026,9 +2124,9 @@ } }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, "ms": { @@ -2089,6 +2187,18 @@ "ora": "^3.4.0", "spawn-rx": "^3.0.0", "yargs": "^14.2.0" + }, + "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + } } }, "electron-winstaller": { @@ -2188,6 +2298,17 @@ "uuid": "^3.3.3" }, "dependencies": { + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "klaw": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", @@ -2553,13 +2674,30 @@ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", + "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", "requires": { + "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + }, + "dependencies": { + "jsonfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", + "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^1.0.0" + } + }, + "universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==" + } } }, "fs-minipass": { @@ -4232,9 +4370,9 @@ }, "dependencies": { "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" } } }, @@ -4502,6 +4640,26 @@ "update-notifier": "^2.5.0" }, "dependencies": { + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -4628,9 +4786,9 @@ } }, "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "ms": { "version": "2.0.0", @@ -4981,6 +5139,12 @@ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", @@ -5143,9 +5307,9 @@ }, "dependencies": { "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" } } }, @@ -6607,6 +6771,11 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, + "v8-callsites": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/v8-callsites/-/v8-callsites-1.2.1.tgz", + "integrity": "sha1-PKTi3t9Q60ieNwVu1ksCVele84Y=" + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", diff --git a/package.json b/package.json index 92889e6..5ba9953 100644 --- a/package.json +++ b/package.json @@ -38,14 +38,14 @@ "asar": "^2.0.1", "cmake-js": "^4.0.1", "ejs": "^2.7.1", - "electron-installer-windows": "^1.1.1", + "electron-installer-windows": "^1.1.0", "electron-packager": "8.7.2", "electron-winstaller": "^2.7.0", - "electron-wix-msi": "^2.2.0", + "electron-wix-msi": "^2.1.1", "nodemon": "^1.19.4", "platform-dependent-modules": "0.0.14", "rc": "^1.2.8", - "rcedit": "^1.1.2", + "rcedit": "^1.1.1", "sass": "^1.23.2", "typescript": "^3.7.2" }, @@ -62,7 +62,7 @@ "electron-rebuild": "^1.8.6", "extend": "^3.0.2", "extsprintf": "^1.4.0", - "fs-extra": "^8.1.0", + "fs-extra": "^9.0.0", "http-signature": "^1.3.1", "jquery": "^3.4.1", "json-stringify-safe": "^5.0.1", @@ -80,7 +80,8 @@ "safer-buffer": "^2.1.2", "sshpk": "^1.16.1", "tar-stream": "^2.1.0", - "tough-cookie": "^3.0.1" + "tough-cookie": "^3.0.1", + "v8-callsites": "latest" }, "config": { "platformDependentModules": { diff --git a/tsconfig.json b/tsconfig.json index 0c38435..b5985f0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,12 @@ "moduleResolution": "node", "rootDirs": [ "modules" - ] + ], + "baseUrl": ".", + "paths": { + "tc-shared/*": ["imports/shared-app/*"], + "tc-loader": ["imports/loader"] + } }, "exclude": [ "node_modules",