Added opus script again

canary
WolverinDEV 2019-02-17 16:41:26 +01:00
parent 1c024ad483
commit fb7edd32b8
3 changed files with 285 additions and 0 deletions

11
asm/make_opus.sh Executable file
View File

@ -0,0 +1,11 @@
#!/usr/bin/env bash
base_dir=`pwd`
cd "$(dirname $0)/libraries/opus/"
git checkout v1.1.2
./autogen.sh
emconfigure ./configure --disable-extra-programs --disable-doc --disable-rtcd
emmake make
cd ${base_dir}

View File

@ -0,0 +1,42 @@
# File structure
The TeaSpeak web client is separated into 2 different parts.
## I) Application files
Application files are all files which directly belong to the app itself.
Like the javascript files who handle the UI stuff or even translation templates.
Theses files are separated into two type of files.
1. [Shared application files](#1-shared-application-files)
2. [Web application files](#2-web-application-files)
### 1. Shared application files
Containing all files used by the TeaSpeak client and the Web client.
All of these files will be found within the folder `shared`.
This folder follows the general application file structure.
More information could be found [here](#application-file-structure)
### 2. Web application files
All files which only belong to a browser only instance.
All of these files will be found within the folder `web`.
This folder follows the general application file structure.
More information could be found [here](#application-file-structure)
### application file structure
Every application root contains several subfolders.
In the following list will be listed which files belong to which folder
| Folder | Description |
| --- | --- |
| `audio` | This folder contains all audio files used by the application. More information could be found [here](). |
| `css` | This folder contains all style sheets used by the application. More information could be found [here](). |
| `js` | This folder contains all javascript files used by the application. More information could be found [here](). |
| `html` | This folder contains all HTML and PHP files used by the application. More information could be found [here](). |
| `i18n` | This folder contains all default translations. Information about the translation system could be found [here](). |
| `img` | This folder contains all image files. |
## I) Additional tools
## Environment builder
The environment builder is one of the most important tools of the entire project.
This tool, basically implemented in the file `files.php`, will be your helper while live developing.
What this tool does is, it creates a final environment where you could navigate to with your browser.
It merges all the type separated files, which had been listed above ([here](#application-file-structure)).

232
shared/js/stats.ts Normal file
View File

@ -0,0 +1,232 @@
namespace stats {
const LOG_PREFIX = "[Statistics] ";
export enum CloseCodes {
UNSET = 3000,
RECONNECT = 3001,
INTERNAL_ERROR = 3002,
BANNED = 3100,
}
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;
let reconnect_timer: NodeJS.Timer;
let current_config: Config;
let last_user_count_update: number;
let user_count_listener: UserCountListener[] = [];
const DEFAULT_CONFIG: Config = {
verbose: true,
reconnect_interval: 5000,
anonymize_ip_addresses: true,
volatile_collection_only: false
};
function initialize_config_object(target_object: any, source_object: any) : any {
for(const key of Object.keys(source_object)) {
if(typeof(source_object[key]) === 'object')
initialize_config_object(target_object[key] || (target_object[key] = {}), source_object[key]);
if(typeof(target_object[key]) !== 'undefined')
continue;
target_object[key] = source_object[key];
}
return target_object;
}
export function initialize(config: Config) {
current_config = initialize_config_object(config || {}, DEFAULT_CONFIG);
if(current_config.verbose)
console.log(LOG_PREFIX + tr("Initializing statistics with this config: %o"), current_config);
connection.start_connection();
}
export function register_user_count_listener(listener: UserCountListener) {
user_count_listener.push(listener);
}
export function all_user_count_listener() : UserCountListener[] {
return user_count_listener;
}
export function deregister_user_count_listener(listener: UserCountListener) {
user_count_listener.remove(listener);
}
namespace connection {
let connection: WebSocket;
export let connection_state: ConnectionState = ConnectionState.UNSET;
export function start_connection() {
cancel_reconnect();
if(connection) {
const connection_copy = connection;
connection = undefined;
connection_copy.close(3001);
}
connection_state = ConnectionState.CONNECTING;
connection = new WebSocket('wss://web-stats.teaspeak.de:1774');
{
const connection_copy = connection;
connection.onclose = (event: CloseEvent) => {
if(connection_copy !== connection) return;
if(current_config.verbose)
console.log(LOG_PREFIX + tr("Lost connection to statistics server (Connection closed). Reason: %o. Event object: %o"), CloseCodes[event.code] || event.code, event);
if(event.code != CloseCodes.BANNED)
invoke_reconnect();
};
connection.onopen = () => {
if(connection_copy !== connection) return;
if(current_config.verbose)
console.log(LOG_PREFIX + tr("Successfully connected to server. Initializing session."));
connection_state = ConnectionState.INITIALIZING;
initialize_session();
};
connection.onerror = (event: ErrorEvent) => {
if(connection_copy !== connection) return;
if(current_config.verbose)
console.log(LOG_PREFIX + tr("Received an error. Closing connection. Object: %o"), event);
connection.close(CloseCodes.INTERNAL_ERROR);
this.invoke_reconnect();
};
connection.onmessage = (event: MessageEvent) => {
if(connection_copy !== connection) return;
if(typeof(event.data) !== 'string') {
if(current_config.verbose)
console.warn(LOG_PREFIX + tr("Received an message which isn't a string. Event object: %o"), event);
return;
}
handle_message(event.data as string);
};
}
}
function invoke_reconnect() {
if(reconnect_timer) {
clearTimeout(reconnect_timer);
reconnect_timer = undefined;
}
if(current_config.verbose)
console.log(LOG_PREFIX + tr("Scheduled reconnect in %dms"), current_config.reconnect_interval);
reconnect_timer = setTimeout(() => {
if(current_config.verbose)
console.log(LOG_PREFIX + tr("Reconnecting"));
start_connection();
}, current_config.reconnect_interval);
}
export function cancel_reconnect() {
if(reconnect_timer) {
clearTimeout(reconnect_timer);
reconnect_timer = undefined;
}
}
function send_message(type: string, data: any) {
connection.send(JSON.stringify({
type: type,
data: data
}));
}
function initialize_session() {
const config_object = {};
for(const key in SessionConfig) {
if(SessionConfig.hasOwnProperty(key))
config_object[key] = current_config[key];
}
send_message('initialize', {
config: config_object
})
}
function handle_message(message: string) {
const data_object = JSON.parse(message);
const type = data_object.type as string;
const data = data_object.data;
if(typeof(handler[type]) === 'function') {
if(current_config.verbose)
console.debug(LOG_PREFIX + tr("Handling message of type %s"), type);
handler[type](data);
} else if(current_config.verbose) {
console.warn(LOG_PREFIX + tr("Received message with an unknown type (%s). Dropping message. Full message: %o"), type, data_object);
}
}
namespace handler {
interface NotifyUserCount extends UserCountData { }
function handle_notify_user_count(data: NotifyUserCount) {
last_user_count_update = Date.now();
for(const listener of [...user_count_listener])
listener(data);
}
interface NotifyInitialized {}
function handle_notify_initialized(json: NotifyInitialized) {
if(current_config.verbose)
console.log(LOG_PREFIX + tr("Session successfully initialized."));
connection_state = ConnectionState.CONNECTED;
}
handler["notifyinitialized"] = handle_notify_initialized;
handler["notifyusercount"] = handle_notify_user_count;
}
}
}