Added opus script again
parent
1c024ad483
commit
fb7edd32b8
|
@ -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}
|
|
@ -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)).
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue