Restructuring of the connection part
parent
fbf820377c
commit
e75bbeabef
|
@ -20,8 +20,5 @@ jobs:
|
|||
- "ls -lah /tmp/build/"
|
||||
- "ls -lah /tmp/build/logs/"
|
||||
- "ls -lah /tmp/build/packages/"
|
||||
- >
|
||||
mkdir -p /tmp/build/packages/;
|
||||
echo "XXXX" > /tmp/build/packages/xxxxx;
|
||||
./scripts/travis_deploy.sh
|
||||
- "./scripts/travis_deploy.sh"
|
||||
if: branch = master
|
|
@ -109,7 +109,7 @@ class DownloadFileTransfer {
|
|||
}
|
||||
}
|
||||
|
||||
class FileManager {
|
||||
class FileManager extends connection.AbstractCommandHandler {
|
||||
handle: TSClient;
|
||||
icons: IconManager;
|
||||
avatars: AvatarManager;
|
||||
|
@ -119,13 +119,28 @@ class FileManager {
|
|||
private downloadCounter : number = 0;
|
||||
|
||||
constructor(client: TSClient) {
|
||||
super(client.serverConnection);
|
||||
|
||||
this.handle = client;
|
||||
this.icons = new IconManager(this);
|
||||
this.avatars = new AvatarManager(this);
|
||||
|
||||
this.handle.serverConnection.commandHandler["notifyfilelist"] = this.notifyFileList.bind(this);
|
||||
this.handle.serverConnection.commandHandler["notifyfilelistfinished"] = this.notifyFileListFinished.bind(this);
|
||||
this.handle.serverConnection.commandHandler["notifystartdownload"] = this.notifyStartDownload.bind(this);
|
||||
this.connection.command_handler_boss().register_handler(this);
|
||||
}
|
||||
|
||||
handle_command(command: connection.ServerCommand): boolean {
|
||||
switch (command.command) {
|
||||
case "notifyfilelist":
|
||||
this.notifyFileList(command.arguments);
|
||||
return true;
|
||||
case "notifyfilelistfinished":
|
||||
this.notifyFileListFinished(command.arguments);
|
||||
return true;
|
||||
case "notifystartdownload":
|
||||
this.notifyStartDownload(command.arguments);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -140,7 +155,7 @@ class FileManager {
|
|||
req.callback = accept;
|
||||
_this.listRequests.push(req);
|
||||
|
||||
_this.handle.serverConnection.sendCommand("ftgetfilelist", {"path": path, "cid": (channel ? channel.channelId : "0"), "cpw": (password ? password : "")}).then(() => {}).catch(reason => {
|
||||
_this.handle.serverConnection.send_command("ftgetfilelist", {"path": path, "cid": (channel ? channel.channelId : "0"), "cpw": (password ? password : "")}).then(() => {}).catch(reason => {
|
||||
_this.listRequests.remove(req);
|
||||
if(reason instanceof CommandResult) {
|
||||
if(reason.id == 0x0501) {
|
||||
|
@ -197,7 +212,7 @@ class FileManager {
|
|||
this.pendingDownloadTransfers.push(transfer);
|
||||
return new Promise<DownloadFileTransfer>((resolve, reject) => {
|
||||
transfer["_promiseCallback"] = resolve;
|
||||
_this.handle.serverConnection.sendCommand("ftinitdownload", {
|
||||
_this.handle.serverConnection.send_command("ftinitdownload", {
|
||||
"path": path,
|
||||
"name": file,
|
||||
"cid": (channel ? channel.channelId : "0"),
|
||||
|
|
|
@ -354,7 +354,13 @@ class ChatBox {
|
|||
chat.serverChat().appendError(tr("Could not send chant message (Not connected)"));
|
||||
return;
|
||||
}
|
||||
globalClient.serverConnection.sendMessage(text, ChatType.SERVER);
|
||||
globalClient.serverConnection.command_helper.sendMessage(text, ChatType.SERVER).catch(error => {
|
||||
if(error instanceof CommandResult)
|
||||
return;
|
||||
|
||||
chat.serverChat().appendMessage(tr("Failed to send text message."));
|
||||
console.error(tr("Failed to send server text message: %o"), error);
|
||||
});
|
||||
};
|
||||
this.serverChat().name = tr("Server chat");
|
||||
|
||||
|
@ -364,7 +370,10 @@ class ChatBox {
|
|||
return;
|
||||
}
|
||||
|
||||
globalClient.serverConnection.sendMessage(text, ChatType.CHANNEL, globalClient.getClient().currentChannel());
|
||||
globalClient.serverConnection.command_helper.sendMessage(text, ChatType.CHANNEL, globalClient.getClient().currentChannel()).catch(error => {
|
||||
chat.channelChat().appendMessage(tr("Failed to send text message."));
|
||||
console.error(tr("Failed to send channel text message: %o"), error);
|
||||
});
|
||||
};
|
||||
this.channelChat().name = tr("Channel chat");
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
/// <reference path="voice/AudioController.ts" />
|
||||
/// <reference path="proto.ts" />
|
||||
/// <reference path="ui/view.ts" />
|
||||
/// <reference path="connection.ts" />
|
||||
/// <reference path="settings.ts" />
|
||||
/// <reference path="ui/frames/SelectedItemInfo.ts" />
|
||||
/// <reference path="FileManager.ts" />
|
||||
|
@ -49,7 +48,7 @@ enum ViewReasonId {
|
|||
|
||||
class TSClient {
|
||||
channelTree: ChannelTree;
|
||||
serverConnection: ServerConnection;
|
||||
serverConnection: connection.ServerConnection;
|
||||
voiceConnection: VoiceConnection;
|
||||
fileManager: FileManager;
|
||||
selectInfo: InfoBar;
|
||||
|
@ -65,7 +64,7 @@ class TSClient {
|
|||
constructor() {
|
||||
this.selectInfo = new InfoBar(this, $("#select_info"));
|
||||
this.channelTree = new ChannelTree(this, $("#channelTree"));
|
||||
this.serverConnection = new ServerConnection(this);
|
||||
this.serverConnection = new connection.ServerConnection(this);
|
||||
this.fileManager = new FileManager(this);
|
||||
this.permissions = new PermissionManager(this);
|
||||
this.groups = new GroupManager(this);
|
||||
|
@ -101,12 +100,15 @@ class TSClient {
|
|||
|
||||
if(password && !password.hashed) {
|
||||
helpers.hashPassword(password.password).then(password => {
|
||||
this.serverConnection.startConnection({host, port}, new HandshakeHandler(profile, name, password));
|
||||
/* errors will be already handled via the handle disconnect thing */
|
||||
this.serverConnection.connect({host, port}, new connection.HandshakeHandler(profile, name, password));
|
||||
}).catch(error => {
|
||||
createErrorModal(tr("Error while hashing password"), tr("Failed to hash server password!<br>") + error).open();
|
||||
})
|
||||
} else
|
||||
this.serverConnection.startConnection({host, port}, new HandshakeHandler(profile, name, password ? password.password : undefined));
|
||||
} else {
|
||||
/* errors will be already handled via the handle disconnect thing */
|
||||
this.serverConnection.connect({host, port}, new connection.HandshakeHandler(profile, name, password ? password.password : undefined));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -122,7 +124,7 @@ class TSClient {
|
|||
return this._clientId;
|
||||
}
|
||||
|
||||
getServerConnection() : ServerConnection { return this.serverConnection; }
|
||||
getServerConnection() : connection.ServerConnection { return this.serverConnection; }
|
||||
|
||||
|
||||
/**
|
||||
|
@ -133,7 +135,7 @@ class TSClient {
|
|||
this.channelTree.registerClient(this._ownEntry);
|
||||
settings.setServer(this.channelTree.server);
|
||||
this.permissions.requestPermissionList();
|
||||
this.serverConnection.sendCommand("channelsubscribeall");
|
||||
this.serverConnection.send_command("channelsubscribeall");
|
||||
if(this.groups.serverGroups.length == 0)
|
||||
this.groups.requestGroups();
|
||||
this.controlBar.updateProperties();
|
||||
|
@ -142,7 +144,7 @@ class TSClient {
|
|||
}
|
||||
|
||||
get connected() : boolean {
|
||||
return !!this.serverConnection && this.serverConnection.connected;
|
||||
return this.serverConnection && this.serverConnection.connected();
|
||||
}
|
||||
|
||||
private certAcceptUrl() {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,649 @@
|
|||
namespace connection {
|
||||
export class ServerConnectionCommandBoss extends AbstractCommandHandlerBoss {
|
||||
constructor(connection: AbstractServerConnection) {
|
||||
super(connection);
|
||||
}
|
||||
}
|
||||
|
||||
export class ConnectionCommandHandler extends AbstractCommandHandler {
|
||||
readonly connection: ServerConnection;
|
||||
|
||||
constructor(connection: ServerConnection) {
|
||||
super(connection);
|
||||
|
||||
this["error"] = this.handleCommandResult;
|
||||
this["channellist"] = this.handleCommandChannelList;
|
||||
this["channellistfinished"] = this.handleCommandChannelListFinished;
|
||||
this["notifychannelcreated"] = this.handleCommandChannelCreate;
|
||||
this["notifychanneldeleted"] = this.handleCommandChannelDelete;
|
||||
this["notifychannelhide"] = this.handleCommandChannelHide;
|
||||
this["notifychannelshow"] = this.handleCommandChannelShow;
|
||||
|
||||
this["notifycliententerview"] = this.handleCommandClientEnterView;
|
||||
this["notifyclientleftview"] = this.handleCommandClientLeftView;
|
||||
this["notifyclientmoved"] = this.handleNotifyClientMoved;
|
||||
this["initserver"] = this.handleCommandServerInit;
|
||||
this["notifychannelmoved"] = this.handleNotifyChannelMoved;
|
||||
this["notifychanneledited"] = this.handleNotifyChannelEdited;
|
||||
this["notifytextmessage"] = this.handleNotifyTextMessage;
|
||||
this["notifyclientupdated"] = this.handleNotifyClientUpdated;
|
||||
this["notifyserveredited"] = this.handleNotifyServerEdited;
|
||||
this["notifyserverupdated"] = this.handleNotifyServerUpdated;
|
||||
|
||||
this["notifyclientpoke"] = this.handleNotifyClientPoke;
|
||||
|
||||
this["notifymusicplayerinfo"] = this.handleNotifyMusicPlayerInfo;
|
||||
|
||||
this["notifyservergroupclientadded"] = this.handleNotifyServerGroupClientAdd;
|
||||
this["notifyservergroupclientdeleted"] = this.handleNotifyServerGroupClientRemove;
|
||||
this["notifyclientchannelgroupchanged"] = this.handleNotifyClientChannelGroupChanged;
|
||||
}
|
||||
|
||||
handle_command(command: ServerCommand) : boolean {
|
||||
if(this[command.command]) {
|
||||
this[command.command](command.arguments);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
set_handler(command: string, handler: any) {
|
||||
this[command] = handler;
|
||||
}
|
||||
|
||||
unset_handler(command: string, handler?: any) {
|
||||
if(handler && this[command] != handler) return;
|
||||
this[command] = undefined;
|
||||
}
|
||||
|
||||
handleCommandResult(json) {
|
||||
json = json[0]; //Only one bulk
|
||||
|
||||
let code : string = json["return_code"];
|
||||
if(code.length == 0) {
|
||||
console.log(tr("Invalid return code! (%o)"), json);
|
||||
return;
|
||||
}
|
||||
let retListeners = this.connection["_retListener"];
|
||||
|
||||
for(let e of retListeners) {
|
||||
if(e.code != code) continue;
|
||||
retListeners.remove(e);
|
||||
let result = new CommandResult(json);
|
||||
if(result.success)
|
||||
e.resolve(result);
|
||||
else
|
||||
e.reject(result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handleCommandServerInit(json){
|
||||
//We could setup the voice channel
|
||||
console.log(tr("Setting up voice"));
|
||||
this.connection.client.voiceConnection.createSession();
|
||||
|
||||
|
||||
json = json[0]; //Only one bulk
|
||||
|
||||
this.connection.client.clientId = parseInt(json["aclid"]);
|
||||
this.connection.client.getClient().updateVariables({key: "client_nickname", value: json["acn"]});
|
||||
|
||||
let updates: {
|
||||
key: string,
|
||||
value: string
|
||||
}[] = [];
|
||||
for(let key in json) {
|
||||
if(key === "aclid") continue;
|
||||
if(key === "acn") continue;
|
||||
|
||||
updates.push({key: key, value: json[key]});
|
||||
}
|
||||
this.connection.client.channelTree.server.updateVariables(false, ...updates);
|
||||
|
||||
|
||||
chat.serverChat().name = this.connection.client.channelTree.server.properties["virtualserver_name"];
|
||||
chat.serverChat().appendMessage(tr("Connected as {0}"), true, this.connection.client.getClient().createChatTag(true));
|
||||
sound.play(Sound.CONNECTION_CONNECTED);
|
||||
globalClient.onConnected();
|
||||
}
|
||||
|
||||
private createChannelFromJson(json, ignoreOrder: boolean = false) {
|
||||
let tree = this.connection.client.channelTree;
|
||||
|
||||
let channel = new ChannelEntry(parseInt(json["cid"]), json["channel_name"], tree.findChannel(json["cpid"]));
|
||||
tree.insertChannel(channel);
|
||||
if(json["channel_order"] !== "0") {
|
||||
let prev = tree.findChannel(json["channel_order"]);
|
||||
if(!prev && json["channel_order"] != 0) {
|
||||
if(!ignoreOrder) {
|
||||
console.error(tr("Invalid channel order id!"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let parent = tree.findChannel(json["cpid"]);
|
||||
if(!parent && json["cpid"] != 0) {
|
||||
console.error(tr("Invalid channel parent"));
|
||||
return;
|
||||
}
|
||||
tree.moveChannel(channel, prev, parent); //TODO test if channel exists!
|
||||
}
|
||||
if(ignoreOrder) {
|
||||
for(let ch of tree.channels) {
|
||||
if(ch.properties.channel_order == channel.channelId) {
|
||||
tree.moveChannel(ch, channel, channel.parent); //Corrent the order :)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let updates: {
|
||||
key: string,
|
||||
value: string
|
||||
}[] = [];
|
||||
for(let key in json) {
|
||||
if(key === "cid") continue;
|
||||
if(key === "cpid") continue;
|
||||
if(key === "invokerid") continue;
|
||||
if(key === "invokername") continue;
|
||||
if(key === "invokeruid") continue;
|
||||
if(key === "reasonid") continue;
|
||||
|
||||
updates.push({key: key, value: json[key]});
|
||||
}
|
||||
channel.updateVariables(...updates);
|
||||
}
|
||||
|
||||
handleCommandChannelList(json) {
|
||||
this.connection.client.channelTree.hide_channel_tree(); /* dont perform channel inserts on the dom to prevent style recalculations */
|
||||
console.log(tr("Got %d new channels"), json.length);
|
||||
for(let index = 0; index < json.length; index++)
|
||||
this.createChannelFromJson(json[index], true);
|
||||
}
|
||||
|
||||
|
||||
handleCommandChannelListFinished(json) {
|
||||
this.connection.client.channelTree.show_channel_tree();
|
||||
}
|
||||
|
||||
handleCommandChannelCreate(json) {
|
||||
this.createChannelFromJson(json[0]);
|
||||
}
|
||||
|
||||
handleCommandChannelShow(json) {
|
||||
this.createChannelFromJson(json[0]); //TODO may chat?
|
||||
}
|
||||
|
||||
handleCommandChannelDelete(json) {
|
||||
let tree = this.connection.client.channelTree;
|
||||
|
||||
console.log(tr("Got %d channel deletions"), json.length);
|
||||
for(let index = 0; index < json.length; index++) {
|
||||
let channel = tree.findChannel(json[index]["cid"]);
|
||||
if(!channel) {
|
||||
console.error(tr("Invalid channel onDelete (Unknown channel)"));
|
||||
continue;
|
||||
}
|
||||
tree.deleteChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
handleCommandChannelHide(json) {
|
||||
let tree = this.connection.client.channelTree;
|
||||
|
||||
console.log(tr("Got %d channel hides"), json.length);
|
||||
for(let index = 0; index < json.length; index++) {
|
||||
let channel = tree.findChannel(json[index]["cid"]);
|
||||
if(!channel) {
|
||||
console.error(tr("Invalid channel on hide (Unknown channel)"));
|
||||
continue;
|
||||
}
|
||||
tree.deleteChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
handleCommandClientEnterView(json) {
|
||||
json = json[0]; //Only one bulk
|
||||
let tree = this.connection.client.channelTree;
|
||||
|
||||
let client: ClientEntry;
|
||||
let channel = tree.findChannel(json["ctid"]);
|
||||
let old_channel = tree.findChannel(json["cfid"]);
|
||||
|
||||
client = tree.findClient(json["clid"]);
|
||||
|
||||
if(!client) {
|
||||
if(parseInt(json["client_type_exact"]) == ClientType.CLIENT_MUSIC) {
|
||||
client = new MusicClientEntry(parseInt(json["clid"]), json["client_nickname"]);
|
||||
} else {
|
||||
client = new ClientEntry(parseInt(json["clid"]), json["client_nickname"]);
|
||||
}
|
||||
|
||||
client.properties.client_type = parseInt(json["client_type"]);
|
||||
client = tree.insertClient(client, channel);
|
||||
} else {
|
||||
if(client == this.connection.client.getClient())
|
||||
chat.channelChat().name = channel.channelName();
|
||||
tree.moveClient(client, channel);
|
||||
}
|
||||
|
||||
if(this.connection.client.controlBar.query_visible || client.properties.client_type != ClientType.CLIENT_QUERY) {
|
||||
const own_channel = this.connection.client.getClient().currentChannel();
|
||||
if(json["reasonid"] == ViewReasonId.VREASON_USER_ACTION) {
|
||||
if(own_channel == channel)
|
||||
if(old_channel)
|
||||
sound.play(Sound.USER_ENTERED);
|
||||
else
|
||||
sound.play(Sound.USER_ENTERED_CONNECT);
|
||||
if(old_channel) {
|
||||
chat.serverChat().appendMessage(tr("{0} appeared from {1} to {2}"), true, client.createChatTag(true), old_channel.generate_tag(true), channel.generate_tag(true));
|
||||
} else {
|
||||
chat.serverChat().appendMessage(tr("{0} connected to channel {1}"), true, client.createChatTag(true), channel.generate_tag(true));
|
||||
}
|
||||
} else if(json["reasonid"] == ViewReasonId.VREASON_MOVED) {
|
||||
if(own_channel == channel)
|
||||
sound.play(Sound.USER_ENTERED_MOVED);
|
||||
|
||||
chat.serverChat().appendMessage(tr("{0} appeared from {1} to {2}, moved by {3}"), true,
|
||||
client.createChatTag(true),
|
||||
old_channel ? old_channel.generate_tag(true) : undefined,
|
||||
channel.generate_tag(true),
|
||||
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]),
|
||||
);
|
||||
} else if(json["reasonid"] == ViewReasonId.VREASON_CHANNEL_KICK) {
|
||||
if(own_channel == channel)
|
||||
sound.play(Sound.USER_ENTERED_KICKED);
|
||||
|
||||
chat.serverChat().appendMessage(tr("{0} appeared from {1} to {2}, kicked by {3}{4}"), true,
|
||||
client.createChatTag(true),
|
||||
old_channel ? old_channel.generate_tag(true) : undefined,
|
||||
channel.generate_tag(true),
|
||||
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]),
|
||||
json["reasonmsg"] > 0 ? " (" + json["msg"] + ")" : ""
|
||||
);
|
||||
} else {
|
||||
console.warn(tr("Unknown reasonid for %o"), json["reasonid"]);
|
||||
}
|
||||
}
|
||||
|
||||
let updates: {
|
||||
key: string,
|
||||
value: string
|
||||
}[] = [];
|
||||
|
||||
for(let key in json) {
|
||||
if(key == "cfid") continue;
|
||||
if(key == "ctid") continue;
|
||||
if(key === "invokerid") continue;
|
||||
if(key === "invokername") continue;
|
||||
if(key === "invokeruid") continue;
|
||||
if(key === "reasonid") continue;
|
||||
|
||||
updates.push({key: key, value: json[key]});
|
||||
}
|
||||
|
||||
client.updateVariables(...updates);
|
||||
|
||||
if(client instanceof LocalClientEntry)
|
||||
this.connection.client.controlBar.updateVoice();
|
||||
}
|
||||
|
||||
handleCommandClientLeftView(json) {
|
||||
json = json[0]; //Only one bulk
|
||||
let tree = this.connection.client.channelTree;
|
||||
let client = tree.findClient(json["clid"]);
|
||||
if(!client) {
|
||||
console.error(tr("Unknown client left!"));
|
||||
return 0;
|
||||
}
|
||||
if(client == this.connection.client.getClient()) {
|
||||
if(json["reasonid"] == ViewReasonId.VREASON_BAN) {
|
||||
this.connection.client.handleDisconnect(DisconnectReason.CLIENT_BANNED, json);
|
||||
} else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_KICK) {
|
||||
this.connection.client.handleDisconnect(DisconnectReason.CLIENT_KICKED, json);
|
||||
} else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_SHUTDOWN) {
|
||||
this.connection.client.handleDisconnect(DisconnectReason.SERVER_CLOSED, json);
|
||||
} else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_STOPPED) {
|
||||
this.connection.client.handleDisconnect(DisconnectReason.SERVER_CLOSED, json);
|
||||
} else
|
||||
this.connection.client.handleDisconnect(DisconnectReason.UNKNOWN, json);
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.connection.client.controlBar.query_visible || client.properties.client_type != ClientType.CLIENT_QUERY) {
|
||||
const own_channel = this.connection.client.getClient().currentChannel();
|
||||
let channel_from = tree.findChannel(json["cfid"]);
|
||||
let channel_to = tree.findChannel(json["ctid"]);
|
||||
|
||||
if(json["reasonid"] == ViewReasonId.VREASON_USER_ACTION) {
|
||||
chat.serverChat().appendMessage(tr("{0} disappeared from {1} to {2}"), true, client.createChatTag(true), channel_from.generate_tag(true), channel_to.generate_tag(true));
|
||||
|
||||
if(channel_from == own_channel)
|
||||
sound.play(Sound.USER_LEFT);
|
||||
} else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_LEFT) {
|
||||
chat.serverChat().appendMessage(tr("{0} left the server{1}"), true,
|
||||
client.createChatTag(true),
|
||||
json["reasonmsg"] ? " (" + json["reasonmsg"] + ")" : ""
|
||||
);
|
||||
|
||||
if(channel_from == own_channel)
|
||||
sound.play(Sound.USER_LEFT_DISCONNECT);
|
||||
} else if(json["reasonid"] == ViewReasonId.VREASON_SERVER_KICK) {
|
||||
chat.serverChat().appendError(tr("{0} was kicked from the server by {1}.{2}"),
|
||||
client.createChatTag(true),
|
||||
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]),
|
||||
json["reasonmsg"] ? " (" + json["reasonmsg"] + ")" : ""
|
||||
);
|
||||
if(channel_from == own_channel)
|
||||
sound.play(Sound.USER_LEFT_KICKED_SERVER);
|
||||
} else if(json["reasonid"] == ViewReasonId.VREASON_CHANNEL_KICK) {
|
||||
chat.serverChat().appendError(tr("{0} was kicked from your channel by {1}.{2}"),
|
||||
client.createChatTag(true),
|
||||
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]),
|
||||
json["reasonmsg"] ? " (" + json["reasonmsg"] + ")" : ""
|
||||
);
|
||||
|
||||
if(channel_from == own_channel)
|
||||
sound.play(Sound.USER_LEFT_KICKED_CHANNEL);
|
||||
} else if(json["reasonid"] == ViewReasonId.VREASON_BAN) {
|
||||
//"Mulus" was banned for 1 second from the server by "WolverinDEV" (Sry brauchte kurz ein opfer :P <3 (Nohomo))
|
||||
let duration = "permanently";
|
||||
if(json["bantime"])
|
||||
duration = "for " + formatDate(Number.parseInt(json["bantime"]));
|
||||
|
||||
chat.serverChat().appendError(tr("{0} was banned {1} by {2}.{3}"),
|
||||
client.createChatTag(true),
|
||||
duration,
|
||||
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]),
|
||||
json["reasonmsg"] ? " (" + json["reasonmsg"] + ")" : ""
|
||||
);
|
||||
|
||||
if(channel_from == own_channel)
|
||||
sound.play(Sound.USER_LEFT_BANNED);
|
||||
} else {
|
||||
console.error(tr("Unknown client left reason!"));
|
||||
}
|
||||
}
|
||||
|
||||
tree.deleteClient(client);
|
||||
}
|
||||
|
||||
handleNotifyClientMoved(json) {
|
||||
json = json[0]; //Only one bulk
|
||||
let tree = this.connection.client.channelTree;
|
||||
let client = tree.findClient(json["clid"]);
|
||||
let channel_to = tree.findChannel(json["ctid"]);
|
||||
let channel_from = tree.findChannel(json["cfid"]);
|
||||
|
||||
if(!client) {
|
||||
console.error(tr("Unknown client move (Client)!"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!channel_to) {
|
||||
console.error(tr("Unknown client move (Channel to)!"));
|
||||
return 0;
|
||||
}
|
||||
if(!channel_from) //Not critical
|
||||
console.error(tr("Unknown client move (Channel from)!"));
|
||||
|
||||
let self = client instanceof LocalClientEntry;
|
||||
let current_clients;
|
||||
if(self) {
|
||||
chat.channelChat().name = channel_to.channelName();
|
||||
current_clients = client.channelTree.clientsByChannel(client.currentChannel())
|
||||
this.connection.client.controlBar.updateVoice(channel_to);
|
||||
}
|
||||
|
||||
tree.moveClient(client, channel_to);
|
||||
for(const entry of current_clients || [])
|
||||
if(entry !== client) entry.getAudioController().stopAudio(true);
|
||||
|
||||
const own_channel = this.connection.client.getClient().currentChannel();
|
||||
if(json["reasonid"] == ViewReasonId.VREASON_MOVED) {
|
||||
chat.serverChat().appendMessage(self ? tr("You was moved by {3} from channel {1} to {2}") : tr("{0} was moved from channel {1} to {2} by {3}"), true,
|
||||
client.createChatTag(true),
|
||||
channel_from ? channel_from.generate_tag(true) : undefined,
|
||||
channel_to.generate_tag(true),
|
||||
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"])
|
||||
);
|
||||
if(self)
|
||||
sound.play(Sound.USER_MOVED_SELF);
|
||||
else if(own_channel == channel_to)
|
||||
sound.play(Sound.USER_ENTERED_MOVED);
|
||||
else if(own_channel == channel_from)
|
||||
sound.play(Sound.USER_LEFT_MOVED);
|
||||
} else if(json["reasonid"] == ViewReasonId.VREASON_USER_ACTION) {
|
||||
chat.serverChat().appendMessage(self ? tr("You switched from channel {1} to {2}") : tr("{0} switched from channel {1} to {2}"), true,
|
||||
client.createChatTag(true),
|
||||
channel_from ? channel_from.generate_tag(true) : undefined,
|
||||
channel_to.generate_tag(true)
|
||||
);
|
||||
if(self) {} //If we do an action we wait for the error response
|
||||
else if(own_channel == channel_to)
|
||||
sound.play(Sound.USER_ENTERED);
|
||||
else if(own_channel == channel_from)
|
||||
sound.play(Sound.USER_LEFT);
|
||||
} else if(json["reasonid"] == ViewReasonId.VREASON_CHANNEL_KICK) {
|
||||
chat.serverChat().appendMessage(self ? tr("You got kicked out of the channel {1} to channel {2} by {3}{4}") : tr("{0} got kicked from channel {1} to {2} by {3}{4}"), true,
|
||||
client.createChatTag(true),
|
||||
channel_from ? channel_from.generate_tag(true) : undefined,
|
||||
channel_to.generate_tag(true),
|
||||
ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"]),
|
||||
json["reasonmsg"] ? " (" + json["reasonmsg"] + ")" : ""
|
||||
);
|
||||
if(self) {
|
||||
sound.play(Sound.CHANNEL_KICKED);
|
||||
} else if(own_channel == channel_to)
|
||||
sound.play(Sound.USER_ENTERED_KICKED);
|
||||
else if(own_channel == channel_from)
|
||||
sound.play(Sound.USER_LEFT_KICKED_CHANNEL);
|
||||
} else {
|
||||
console.warn(tr("Unknown reason id %o"), json["reasonid"]);
|
||||
}
|
||||
}
|
||||
|
||||
handleNotifyChannelMoved(json) {
|
||||
json = json[0]; //Only one bulk
|
||||
for(let key in json)
|
||||
console.log("Key: " + key + " Value: " + json[key]);
|
||||
|
||||
let tree = this.connection.client.channelTree;
|
||||
let channel = tree.findChannel(json["cid"]);
|
||||
if(!channel) {
|
||||
console.error(tr("Unknown channel move (Channel)!"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
let prev = tree.findChannel(json["order"]);
|
||||
if(!prev && json["order"] != 0) {
|
||||
console.error(tr("Unknown channel move (prev)!"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
let parent = tree.findChannel(json["cpid"]);
|
||||
if(!parent && json["cpid"] != 0) {
|
||||
console.error(tr("Unknown channel move (parent)!"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
tree.moveChannel(channel, prev, parent);
|
||||
}
|
||||
|
||||
handleNotifyChannelEdited(json) {
|
||||
json = json[0]; //Only one bulk
|
||||
|
||||
let tree = this.connection.client.channelTree;
|
||||
let channel = tree.findChannel(json["cid"]);
|
||||
if(!channel) {
|
||||
console.error(tr("Unknown channel edit (Channel)!"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
let updates: {
|
||||
key: string,
|
||||
value: string
|
||||
}[] = [];
|
||||
for(let key in json) {
|
||||
if(key === "cid") continue;
|
||||
if(key === "invokerid") continue;
|
||||
if(key === "invokername") continue;
|
||||
if(key === "invokeruid") continue;
|
||||
if(key === "reasonid") continue;
|
||||
updates.push({key: key, value: json[key]});
|
||||
}
|
||||
channel.updateVariables(...updates);
|
||||
}
|
||||
|
||||
handleNotifyTextMessage(json) {
|
||||
json = json[0]; //Only one bulk
|
||||
|
||||
//TODO chat format?
|
||||
let mode = json["targetmode"];
|
||||
if(mode == 1){
|
||||
let invoker = this.connection.client.channelTree.findClient(json["invokerid"]);
|
||||
let target = this.connection.client.channelTree.findClient(json["target"]);
|
||||
if(!invoker) { //TODO spawn chat (Client is may invisible)
|
||||
console.error(tr("Got private message from invalid client!"));
|
||||
return;
|
||||
}
|
||||
if(!target) { //TODO spawn chat (Client is may invisible)
|
||||
console.error(tr("Got private message from invalid client!"));
|
||||
return;
|
||||
}
|
||||
if(invoker == this.connection.client.getClient()) {
|
||||
sound.play(Sound.MESSAGE_SEND, {default_volume: .5});
|
||||
target.chat(true).appendMessage("{0}: {1}", true, this.connection.client.getClient().createChatTag(true), MessageHelper.bbcode_chat(json["msg"]));
|
||||
} else {
|
||||
sound.play(Sound.MESSAGE_RECEIVED, {default_volume: .5});
|
||||
invoker.chat(true).appendMessage("{0}: {1}", true, ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"], true), MessageHelper.bbcode_chat(json["msg"]));
|
||||
}
|
||||
} else if(mode == 2) {
|
||||
if(json["invokerid"] == this.connection.client.clientId)
|
||||
sound.play(Sound.MESSAGE_SEND, {default_volume: .5});
|
||||
else
|
||||
sound.play(Sound.MESSAGE_RECEIVED, {default_volume: .5});
|
||||
chat.channelChat().appendMessage("{0}: {1}", true, ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"], true), MessageHelper.bbcode_chat(json["msg"]))
|
||||
} else if(mode == 3) {
|
||||
chat.serverChat().appendMessage("{0}: {1}", true, ClientEntry.chatTag(json["invokerid"], json["invokername"], json["invokeruid"], true), MessageHelper.bbcode_chat(json["msg"]));
|
||||
}
|
||||
}
|
||||
|
||||
handleNotifyClientUpdated(json) {
|
||||
json = json[0]; //Only one bulk
|
||||
|
||||
let client = this.connection.client.channelTree.findClient(json["clid"]);
|
||||
if(!client) {
|
||||
console.error(tr("Tried to update an non existing client"));
|
||||
return;
|
||||
}
|
||||
|
||||
let updates: {
|
||||
key: string,
|
||||
value: string
|
||||
}[] = [];
|
||||
for(let key in json) {
|
||||
if(key == "clid") continue;
|
||||
updates.push({key: key, value: json[key]});
|
||||
}
|
||||
client.updateVariables(...updates);
|
||||
if(this.connection.client.selectInfo.currentSelected == client)
|
||||
this.connection.client.selectInfo.update();
|
||||
}
|
||||
|
||||
handleNotifyServerEdited(json) {
|
||||
json = json[0];
|
||||
|
||||
let updates: {
|
||||
key: string,
|
||||
value: string
|
||||
}[] = [];
|
||||
for(let key in json) {
|
||||
if(key === "invokerid") continue;
|
||||
if(key === "invokername") continue;
|
||||
if(key === "invokeruid") continue;
|
||||
if(key === "reasonid") continue;
|
||||
|
||||
updates.push({key: key, value: json[key]});
|
||||
}
|
||||
this.connection.client.channelTree.server.updateVariables(false, ...updates);
|
||||
if(this.connection.client.selectInfo.currentSelected == this.connection.client.channelTree.server)
|
||||
this.connection.client.selectInfo.update();
|
||||
}
|
||||
|
||||
handleNotifyServerUpdated(json) {
|
||||
json = json[0];
|
||||
|
||||
let updates: {
|
||||
key: string,
|
||||
value: string
|
||||
}[] = [];
|
||||
for(let key in json) {
|
||||
if(key === "invokerid") continue;
|
||||
if(key === "invokername") continue;
|
||||
if(key === "invokeruid") continue;
|
||||
if(key === "reasonid") continue;
|
||||
|
||||
updates.push({key: key, value: json[key]});
|
||||
}
|
||||
this.connection.client.channelTree.server.updateVariables(true, ...updates);
|
||||
let info = this.connection.client.selectInfo;
|
||||
if(info.currentSelected instanceof ServerEntry)
|
||||
info.update();
|
||||
}
|
||||
|
||||
handleNotifyMusicPlayerInfo(json) {
|
||||
json = json[0];
|
||||
|
||||
let bot = this.connection.client.channelTree.find_client_by_dbid(json["bot_id"]);
|
||||
if(!bot || !(bot instanceof MusicClientEntry)) {
|
||||
log.warn(LogCategory.CLIENT, tr("Got music player info for unknown or invalid bot! (ID: %i, Entry: %o)"), json["bot_id"], bot);
|
||||
return;
|
||||
}
|
||||
|
||||
bot.handlePlayerInfo(json);
|
||||
}
|
||||
|
||||
handleNotifyClientPoke(json) {
|
||||
json = json[0];
|
||||
Modals.spawnPoke({
|
||||
id: parseInt(json["invokerid"]),
|
||||
name: json["invokername"],
|
||||
unique_id: json["invokeruid"]
|
||||
}, json["msg"]);
|
||||
|
||||
sound.play(Sound.USER_POKED_SELF);
|
||||
}
|
||||
|
||||
//TODO server chat message
|
||||
handleNotifyServerGroupClientAdd(json) {
|
||||
json = json[0];
|
||||
|
||||
const self = this.connection.client.getClient();
|
||||
if(json["clid"] == self.clientId())
|
||||
sound.play(Sound.GROUP_SERVER_ASSIGNED_SELF);
|
||||
}
|
||||
|
||||
//TODO server chat message
|
||||
handleNotifyServerGroupClientRemove(json) {
|
||||
json = json[0];
|
||||
|
||||
const self = this.connection.client.getClient();
|
||||
if(json["clid"] == self.clientId()) {
|
||||
sound.play(Sound.GROUP_SERVER_REVOKED_SELF);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO server chat message
|
||||
handleNotifyClientChannelGroupChanged(json) {
|
||||
json = json[0];
|
||||
|
||||
const self = this.connection.client.getClient();
|
||||
if(json["clid"] == self.clientId()) {
|
||||
sound.play(Sound.GROUP_CHANNEL_CHANGED_SELF);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,311 @@
|
|||
namespace connection {
|
||||
export class CommandHelper extends AbstractCommandHandler {
|
||||
private _callbacks_namefromuid: ClientNameFromUid[] = [];
|
||||
private _who_am_i: any;
|
||||
|
||||
constructor(connection) {
|
||||
super(connection);
|
||||
|
||||
this.volatile_handler_boss = false;
|
||||
this.ignore_consumed = true;
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this.connection.command_handler_boss().register_handler(this);
|
||||
/* notifyquerylist */
|
||||
}
|
||||
|
||||
handle_command(command: connection.ServerCommand): boolean {
|
||||
if(command.command == "notifyclientnamefromuid")
|
||||
this.handle_notifyclientnamefromuid(command.arguments);
|
||||
else
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
joinChannel(channel: ChannelEntry, password?: string) : Promise<CommandResult> {
|
||||
return this.connection.send_command("clientmove", {
|
||||
"clid": this.connection.client.getClientId(),
|
||||
"cid": channel.getChannelId(),
|
||||
"cpw": password || ""
|
||||
});
|
||||
}
|
||||
|
||||
sendMessage(message: string, type: ChatType, target?: ChannelEntry | ClientEntry) : Promise<CommandResult> {
|
||||
if(type == ChatType.SERVER)
|
||||
return this.connection.send_command("sendtextmessage", {"targetmode": 3, "target": 0, "msg": message});
|
||||
else if(type == ChatType.CHANNEL)
|
||||
return this.connection.send_command("sendtextmessage", {"targetmode": 2, "target": (target as ChannelEntry).getChannelId(), "msg": message});
|
||||
else if(type == ChatType.CLIENT)
|
||||
return this.connection.send_command("sendtextmessage", {"targetmode": 1, "target": (target as ClientEntry).clientId(), "msg": message});
|
||||
}
|
||||
|
||||
updateClient(key: string, value: string) : Promise<CommandResult> {
|
||||
let data = {};
|
||||
data[key] = value;
|
||||
return this.connection.send_command("clientupdate", data);
|
||||
}
|
||||
|
||||
info_from_uid(...uid: string[]) : Promise<ClientNameInfo[]> {
|
||||
let uids = [...uid];
|
||||
for(let p of this._callbacks_namefromuid)
|
||||
if(p.keys == uids) return p.promise;
|
||||
|
||||
let req: ClientNameFromUid = {} as any;
|
||||
req.keys = uids;
|
||||
req.response = new Array(uids.length);
|
||||
req.promise = new LaterPromise<ClientNameInfo[]>();
|
||||
|
||||
for(let uid of uids) {
|
||||
this.connection.send_command("clientgetnamefromuid", {
|
||||
cluid: uid
|
||||
}).catch(req.promise.function_rejected());
|
||||
}
|
||||
|
||||
this._callbacks_namefromuid.push(req);
|
||||
return req.promise;
|
||||
}
|
||||
|
||||
request_query_list(server_id: number = undefined) : Promise<QueryList> {
|
||||
return new Promise<QueryList>((resolve, reject) => {
|
||||
const single_handler = {
|
||||
command: "notifyquerylist",
|
||||
function: command => {
|
||||
const json = command.arguments;
|
||||
|
||||
const result = {} as QueryList;
|
||||
|
||||
result.flag_all = json[0]["flag_all"];
|
||||
result.flag_own = json[0]["flag_own"];
|
||||
result.queries = [];
|
||||
|
||||
for(const entry of json) {
|
||||
const rentry = {} as QueryListEntry;
|
||||
rentry.bounded_server = entry["client_bounded_server"];
|
||||
rentry.username = entry["client_login_name"];
|
||||
rentry.unique_id = entry["client_unique_identifier"];
|
||||
|
||||
result.queries.push(rentry);
|
||||
}
|
||||
|
||||
resolve(result);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
this.handler_boss.register_single_handler(single_handler);
|
||||
|
||||
let data = {};
|
||||
if(server_id !== undefined)
|
||||
data["server_id"] = server_id;
|
||||
|
||||
this.connection.send_command("querylist", data).catch(error => {
|
||||
this.handler_boss.remove_single_handler(single_handler);
|
||||
|
||||
if(error instanceof CommandResult) {
|
||||
if(error.id == ErrorID.EMPTY_RESULT) {
|
||||
resolve(undefined);
|
||||
return;
|
||||
}
|
||||
}
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
request_playlist_list() : Promise<Playlist[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const single_handler: SingleCommandHandler = {
|
||||
command: "notifyplaylistlist",
|
||||
function: command => {
|
||||
const json = command.arguments;
|
||||
const result: Playlist[] = [];
|
||||
|
||||
for(const entry of json) {
|
||||
try {
|
||||
result.push({
|
||||
playlist_id: parseInt(entry["playlist_id"]),
|
||||
playlist_bot_id: parseInt(entry["playlist_bot_id"]),
|
||||
playlist_title: entry["playlist_title"],
|
||||
playlist_type: parseInt(entry["playlist_type"]),
|
||||
playlist_owner_dbid: parseInt(entry["playlist_owner_dbid"]),
|
||||
playlist_owner_name: entry["playlist_owner_name"],
|
||||
|
||||
needed_power_modify: parseInt(entry["needed_power_modify"]),
|
||||
needed_power_permission_modify: parseInt(entry["needed_power_permission_modify"]),
|
||||
needed_power_delete: parseInt(entry["needed_power_delete"]),
|
||||
needed_power_song_add: parseInt(entry["needed_power_song_add"]),
|
||||
needed_power_song_move: parseInt(entry["needed_power_song_move"]),
|
||||
needed_power_song_remove: parseInt(entry["needed_power_song_remove"])
|
||||
});
|
||||
} catch(error) {
|
||||
log.error(LogCategory.NETWORKING, tr("Failed to parse playlist entry: %o"), error);
|
||||
}
|
||||
}
|
||||
|
||||
resolve(result);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
this.handler_boss.register_single_handler(single_handler);
|
||||
|
||||
this.connection.send_command("playlistlist").catch(error => {
|
||||
this.handler_boss.remove_single_handler(single_handler);
|
||||
|
||||
if(error instanceof CommandResult) {
|
||||
if(error.id == ErrorID.EMPTY_RESULT) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
reject(error);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
request_playlist_songs(playlist_id: number) : Promise<PlaylistSong[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const single_handler: SingleCommandHandler = {
|
||||
command: "notifyplaylistsonglist",
|
||||
function: command => {
|
||||
const json = command.arguments;
|
||||
|
||||
if(json[0]["playlist_id"] != playlist_id) {
|
||||
log.error(LogCategory.NETWORKING, tr("Received invalid notification for playlist songs"));
|
||||
return false;
|
||||
}
|
||||
|
||||
const result: PlaylistSong[] = [];
|
||||
|
||||
for(const entry of json) {
|
||||
try {
|
||||
result.push({
|
||||
song_id: parseInt(entry["song_id"]),
|
||||
song_invoker: entry["song_invoker"],
|
||||
song_previous_song_id: parseInt(entry["song_previous_song_id"]),
|
||||
song_url: entry["song_url"],
|
||||
song_url_loader: entry["song_url_loader"],
|
||||
|
||||
song_loaded: entry["song_loaded"] == true || entry["song_loaded"] == "1",
|
||||
song_metadata: entry["song_metadata"]
|
||||
});
|
||||
} catch(error) {
|
||||
log.error(LogCategory.NETWORKING, tr("Failed to parse playlist song entry: %o"), error);
|
||||
}
|
||||
}
|
||||
|
||||
resolve(result);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
this.handler_boss.register_single_handler(single_handler);
|
||||
|
||||
this.connection.send_command("playlistsonglist", {playlist_id: playlist_id}).catch(error => {
|
||||
this.handler_boss.remove_single_handler(single_handler);
|
||||
if(error instanceof CommandResult) {
|
||||
if(error.id == ErrorID.EMPTY_RESULT) {
|
||||
resolve([]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
reject(error);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
request_playlist_info(playlist_id: number) : Promise<PlaylistInfo> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const single_handler: SingleCommandHandler = {
|
||||
command: "notifyplaylistinfo",
|
||||
function: command => {
|
||||
const json = command.arguments[0];
|
||||
if (json["playlist_id"] != playlist_id) {
|
||||
log.error(LogCategory.NETWORKING, tr("Received invalid notification for playlist info"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
//resolve
|
||||
resolve({
|
||||
playlist_id: parseInt(json["playlist_id"]),
|
||||
playlist_title: json["playlist_title"],
|
||||
playlist_description: json["playlist_description"],
|
||||
playlist_type: parseInt(json["playlist_type"]),
|
||||
|
||||
playlist_owner_dbid: parseInt(json["playlist_owner_dbid"]),
|
||||
playlist_owner_name: json["playlist_owner_name"],
|
||||
|
||||
playlist_flag_delete_played: json["playlist_flag_delete_played"] == true || json["playlist_flag_delete_played"] == "1",
|
||||
playlist_flag_finished: json["playlist_flag_finished"] == true || json["playlist_flag_finished"] == "1",
|
||||
playlist_replay_mode: parseInt(json["playlist_replay_mode"]),
|
||||
playlist_current_song_id: parseInt(json["playlist_current_song_id"]),
|
||||
});
|
||||
} catch (error) {
|
||||
log.error(LogCategory.NETWORKING, tr("Failed to parse playlist info: %o"), error);
|
||||
reject("failed to parse info");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
this.handler_boss.register_single_handler(single_handler);
|
||||
|
||||
this.connection.send_command("playlistinfo", {playlist_id: playlist_id}).catch(error => {
|
||||
this.handler_boss.remove_single_handler(single_handler);
|
||||
reject(error);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* Its just a workaround for the query management.
|
||||
* There is no garante that the whoami trick will work forever
|
||||
*/
|
||||
current_virtual_server_id() : Promise<number> {
|
||||
if(this._who_am_i)
|
||||
return Promise.resolve(parseInt(this._who_am_i["virtualserver_id"]));
|
||||
|
||||
return new Promise<number>((resolve, reject) => {
|
||||
const single_handler: SingleCommandHandler = {
|
||||
function: command => {
|
||||
if(command.command != "")
|
||||
return false;
|
||||
|
||||
this._who_am_i = command.arguments[0];
|
||||
resolve(parseInt(this._who_am_i["virtualserver_id"]));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
this.handler_boss.register_single_handler(single_handler);
|
||||
|
||||
this.connection.send_command("whoami").catch(error => {
|
||||
this.handler_boss.remove_single_handler(single_handler);
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private handle_notifyclientnamefromuid(json: any[]) {
|
||||
for(let entry of json) {
|
||||
let info: ClientNameInfo = {} as any;
|
||||
info.client_unique_id = entry["cluid"];
|
||||
info.client_nickname = entry["clname"];
|
||||
info.client_database_id = parseInt(entry["cldbid"]);
|
||||
|
||||
for(let elm of this._callbacks_namefromuid.slice(0)) {
|
||||
let unset = 0;
|
||||
for(let index = 0; index < elm.keys.length; index++) {
|
||||
if(elm.keys[index] == info.client_unique_id) {
|
||||
elm.response[index] = info;
|
||||
}
|
||||
if(elm.response[index] == undefined) unset++;
|
||||
}
|
||||
if(unset == 0) {
|
||||
this._callbacks_namefromuid.remove(elm);
|
||||
elm.promise.resolved(elm.response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,148 @@
|
|||
namespace connection {
|
||||
export interface CommandOptions {
|
||||
flagset?: string[]; /* default: [] */
|
||||
process_result?: boolean; /* default: true */
|
||||
|
||||
timeout?: number /* default: 1000 */;
|
||||
}
|
||||
export const CommandOptionDefaults: CommandOptions = {
|
||||
flagset: [],
|
||||
process_result: true,
|
||||
timeout: 1000
|
||||
};
|
||||
|
||||
export abstract class AbstractServerConnection {
|
||||
readonly client: TSClient;
|
||||
readonly command_helper: CommandHelper;
|
||||
|
||||
protected constructor(client: TSClient) {
|
||||
this.client = client;
|
||||
|
||||
this.command_helper = new CommandHelper(this);
|
||||
}
|
||||
|
||||
/* 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<void>;
|
||||
|
||||
abstract connected() : boolean;
|
||||
abstract disconnect(reason?: string) : Promise<void>;
|
||||
|
||||
abstract support_voice() : boolean;
|
||||
abstract voice_connection() : AbstractVoiceConnection | undefined;
|
||||
|
||||
abstract command_handler_boss() : AbstractCommandHandlerBoss;
|
||||
abstract send_command(command: string, data?: any | any[], options?: CommandOptions) : Promise<CommandResult>;
|
||||
}
|
||||
|
||||
export abstract class AbstractVoiceConnection {
|
||||
readonly connection: AbstractServerConnection;
|
||||
|
||||
protected constructor(connection: AbstractServerConnection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
abstract connected() : boolean;
|
||||
}
|
||||
|
||||
export class ServerCommand {
|
||||
command: string;
|
||||
arguments: any[];
|
||||
}
|
||||
|
||||
export abstract class AbstractCommandHandler {
|
||||
readonly connection: AbstractServerConnection;
|
||||
|
||||
handler_boss: AbstractCommandHandlerBoss | undefined;
|
||||
volatile_handler_boss: boolean = false; /* if true than the command handler could be registered twice to two or more handlers */
|
||||
|
||||
ignore_consumed: boolean = false;
|
||||
|
||||
protected constructor(connection: AbstractServerConnection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
register_handler(handler: AbstractCommandHandler) {
|
||||
if(!handler.volatile_handler_boss && handler.handler_boss)
|
||||
throw "handler already registered";
|
||||
|
||||
this.command_handlers.remove(handler); /* just to be sure */
|
||||
this.command_handlers.push(handler);
|
||||
handler.handler_boss = this;
|
||||
}
|
||||
|
||||
unregister_handler(handler: AbstractCommandHandler) {
|
||||
if(!handler.volatile_handler_boss && handler.handler_boss !== this) {
|
||||
console.warn(tr("Tried to unregister command handler which does not belong to the handler boss"));
|
||||
return;
|
||||
}
|
||||
|
||||
this.command_handlers.remove(handler);
|
||||
handler.handler_boss = undefined;
|
||||
}
|
||||
|
||||
|
||||
register_single_handler(handler: SingleCommandHandler) {
|
||||
this.single_command_handler.push(handler);
|
||||
}
|
||||
|
||||
remove_single_handler(handler: SingleCommandHandler) {
|
||||
this.single_command_handler.remove(handler);
|
||||
}
|
||||
|
||||
handlers() : AbstractCommandHandler[] {
|
||||
return this.command_handlers;
|
||||
}
|
||||
|
||||
invoke_handle(command: ServerCommand) : boolean {
|
||||
let flag_consumed = false;
|
||||
|
||||
for(const handler of this.command_handlers) {
|
||||
try {
|
||||
if(!flag_consumed || handler.ignore_consumed)
|
||||
flag_consumed = flag_consumed || handler.handle_command(command);
|
||||
} catch(error) {
|
||||
console.error(tr("Failed to invoke command handler. Invocation results in an exception: %o"), error);
|
||||
}
|
||||
}
|
||||
|
||||
for(const handler of [...this.single_command_handler]) {
|
||||
if(handler.command && handler.command != command.command)
|
||||
continue;
|
||||
|
||||
try {
|
||||
if(handler.function(command))
|
||||
this.single_command_handler.remove(handler);
|
||||
} catch(error) {
|
||||
console.error(tr("Failed to invoke single command handler. Invocation results in an exception: %o"), error);
|
||||
}
|
||||
}
|
||||
|
||||
return flag_consumed;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
namespace connection {
|
||||
export interface HandshakeIdentityHandler {
|
||||
connection: AbstractServerConnection;
|
||||
|
||||
start_handshake();
|
||||
register_callback(callback: (success: boolean, message?: string) => any);
|
||||
}
|
||||
|
||||
export class HandshakeHandler {
|
||||
private connection: ServerConnection;
|
||||
private handshake_handler: HandshakeIdentityHandler;
|
||||
private failed = false;
|
||||
|
||||
readonly profile: profiles.ConnectionProfile;
|
||||
readonly name: string;
|
||||
readonly server_password: string;
|
||||
|
||||
constructor(profile: profiles.ConnectionProfile, name: string, password: string) {
|
||||
this.profile = profile;
|
||||
this.server_password = password;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
setConnection(con: ServerConnection) {
|
||||
this.connection = con;
|
||||
}
|
||||
|
||||
startHandshake() {
|
||||
this.handshake_handler = this.profile.spawn_identity_handshake_handler(this.connection);
|
||||
if(!this.handshake_handler) {
|
||||
this.handshake_failed("failed to create identity handler");
|
||||
return;
|
||||
}
|
||||
|
||||
this.handshake_handler.register_callback((flag, message) => {
|
||||
if(flag)
|
||||
this.handshake_finished();
|
||||
else
|
||||
this.handshake_failed(message);
|
||||
});
|
||||
|
||||
this.handshake_handler.start_handshake();
|
||||
}
|
||||
|
||||
private handshake_failed(message: string) {
|
||||
if(this.failed) return;
|
||||
|
||||
this.failed = true;
|
||||
this.connection.client.handleDisconnect(DisconnectReason.HANDSHAKE_FAILED, message);
|
||||
}
|
||||
|
||||
private handshake_finished(version?: string) {
|
||||
if(native_client && window["native"] && native.client_version && !version) {
|
||||
native.client_version()
|
||||
.then( this.handshake_finished.bind(this))
|
||||
.catch(error => {
|
||||
console.error(tr("Failed to get version:"));
|
||||
console.error(error);
|
||||
this.handshake_finished("?.?.?");
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const git_version = settings.static_global("version", "unknown");
|
||||
const browser_name = (navigator.browserSpecs || {})["name"] || " ";
|
||||
let data = {
|
||||
//TODO variables!
|
||||
client_nickname: this.name,
|
||||
client_platform: (browser_name ? browser_name + " " : "") + navigator.platform,
|
||||
client_version: "TeaWeb " + git_version + " (" + navigator.userAgent + ")",
|
||||
|
||||
client_server_password: this.server_password,
|
||||
client_browser_engine: navigator.product
|
||||
};
|
||||
|
||||
if(version) {
|
||||
data.client_version = "TeaClient ";
|
||||
data.client_version += " " + version;
|
||||
|
||||
const os = require("os");
|
||||
const arch_mapping = {
|
||||
"x32": "32bit",
|
||||
"x64": "64bit"
|
||||
};
|
||||
|
||||
data.client_version += " " + (arch_mapping[os.arch()] || os.arch());
|
||||
|
||||
const os_mapping = {
|
||||
"win32": "Windows",
|
||||
"linux": "Linux"
|
||||
};
|
||||
data.client_platform = (os_mapping[os.platform()] || os.platform());
|
||||
}
|
||||
|
||||
this.connection.send_command("clientinit", data).catch(error => {
|
||||
this.connection.disconnect();
|
||||
if(error instanceof CommandResult) {
|
||||
if(error.id == 1028) {
|
||||
this.connection.client.handleDisconnect(DisconnectReason.SERVER_REQUIRES_PASSWORD);
|
||||
} else {
|
||||
|
||||
this.connection.client.handleDisconnect(DisconnectReason.CLIENT_KICKED, error);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,377 @@
|
|||
enum ErrorID {
|
||||
PERMISSION_ERROR = 2568,
|
||||
EMPTY_RESULT = 0x0501,
|
||||
PLAYLIST_IS_IN_USE = 0x2103
|
||||
}
|
||||
|
||||
class CommandResult {
|
||||
success: boolean;
|
||||
id: number;
|
||||
message: string;
|
||||
extra_message: string;
|
||||
|
||||
json: any;
|
||||
|
||||
constructor(json) {
|
||||
this.json = json;
|
||||
this.id = json["id"];
|
||||
this.message = json["msg"];
|
||||
|
||||
this.extra_message = "";
|
||||
if(json["extra_msg"]) this.extra_message = json["extra_msg"];
|
||||
|
||||
this.success = this.id == 0;
|
||||
}
|
||||
}
|
||||
|
||||
class ReturnListener<T> {
|
||||
resolve: (value?: T | PromiseLike<T>) => void;
|
||||
reject: (reason?: any) => void;
|
||||
code: string;
|
||||
|
||||
timeout: NodeJS.Timer;
|
||||
}
|
||||
|
||||
namespace connection {
|
||||
export class ServerConnection extends AbstractServerConnection {
|
||||
_remote_address: ServerAddress;
|
||||
_socket: WebSocket;
|
||||
_connectionState: ConnectionState = ConnectionState.UNCONNECTED;
|
||||
_handshakeHandler: HandshakeHandler;
|
||||
|
||||
private _command_boss: ServerConnectionCommandBoss;
|
||||
private _command_handler_default: ConnectionCommandHandler;
|
||||
private _command_handler_handshake: AbstractCommandHandler; //The new handshake handler :)
|
||||
|
||||
private _connect_timeout_timer: NodeJS.Timer = undefined;
|
||||
private _connected: boolean = false;
|
||||
private _retCodeIdx: number;
|
||||
private _retListener: ReturnListener<CommandResult>[];
|
||||
|
||||
constructor(client : TSClient) {
|
||||
super(client);
|
||||
|
||||
this._socket = null;
|
||||
this._retCodeIdx = 0;
|
||||
this._retListener = [];
|
||||
|
||||
this._command_boss = new ServerConnectionCommandBoss(this);
|
||||
this._command_handler_default = new ConnectionCommandHandler(this);
|
||||
|
||||
this._command_boss.register_handler(this._command_handler_default);
|
||||
this.command_helper.initialize();
|
||||
}
|
||||
|
||||
on_connect: () => void = () => {
|
||||
console.log(tr("Socket connected"));
|
||||
chat.serverChat().appendMessage(tr("Logging in..."));
|
||||
this._handshakeHandler.startHandshake();
|
||||
};
|
||||
|
||||
private generateReturnCode() : string {
|
||||
return (this._retCodeIdx++).toString();
|
||||
}
|
||||
|
||||
async connect(address : ServerAddress, handshake: HandshakeHandler, timeout?: number) : Promise<void> {
|
||||
timeout = typeof(timeout) === "number" ? timeout : 0;
|
||||
|
||||
if(this._connect_timeout_timer) {
|
||||
clearTimeout(this._connect_timeout_timer);
|
||||
this._connect_timeout_timer = null;
|
||||
try {
|
||||
await this.disconnect()
|
||||
} catch(error) {
|
||||
console.error(tr("Failed to close old connection properly. Error: %o"), error);
|
||||
throw "failed to cleanup old connection";
|
||||
}
|
||||
}
|
||||
this.updateConnectionState(ConnectionState.CONNECTING);
|
||||
this._remote_address = address;
|
||||
this._handshakeHandler = handshake;
|
||||
this._handshakeHandler.setConnection(this);
|
||||
this._connected = false;
|
||||
chat.serverChat().appendMessage(tr("Connecting to {0}:{1}"), true, address.host, address.port);
|
||||
|
||||
const self = this;
|
||||
try {
|
||||
let local_socket: WebSocket;
|
||||
let local_timeout_timer: NodeJS.Timer;
|
||||
|
||||
local_timeout_timer = setTimeout(async () => {
|
||||
console.log(tr("Connect timeout triggered!"));
|
||||
try {
|
||||
await this.disconnect();
|
||||
} catch(error) {
|
||||
log.warn(LogCategory.NETWORKING, tr("Failed to close connection after timeout had been triggered! (%o)"), error);
|
||||
}
|
||||
this.client.handleDisconnect(DisconnectReason.CONNECT_FAILURE);
|
||||
}, timeout);
|
||||
this._connect_timeout_timer = local_timeout_timer;
|
||||
|
||||
this._socket = (local_socket = new WebSocket('wss://' + address.host + ":" + address.port)); /* this may hangs */
|
||||
clearTimeout(local_timeout_timer);
|
||||
if(this._connect_timeout_timer == local_timeout_timer)
|
||||
this._connect_timeout_timer = undefined;
|
||||
|
||||
if(this._socket != local_socket) return; /* something had changed and we dont use this connection anymore! */
|
||||
local_socket.onopen = () => {
|
||||
if(this._socket != local_socket) return; /* this socket isn't from interest anymore */
|
||||
|
||||
this._connected = true;
|
||||
this.on_connect();
|
||||
};
|
||||
|
||||
local_socket.onclose = event => {
|
||||
if(this._socket != local_socket) return; /* this socket isn't from interest anymore */
|
||||
|
||||
this.client.handleDisconnect(this._connected ? DisconnectReason.CONNECTION_CLOSED : DisconnectReason.CONNECT_FAILURE, {
|
||||
code: event.code,
|
||||
reason: event.reason,
|
||||
event: event
|
||||
});
|
||||
};
|
||||
|
||||
local_socket.onerror = e => {
|
||||
if(this._socket != local_socket) return; /* this socket isn't from interest anymore */
|
||||
|
||||
console.log(tr("Received web socket error: (%o)"), e);
|
||||
};
|
||||
|
||||
local_socket.onmessage = msg => {
|
||||
if(this._socket != local_socket) return; /* this socket isn't from interest anymore */
|
||||
|
||||
self.handle_socket_message(msg.data);
|
||||
};
|
||||
this.updateConnectionState(ConnectionState.INITIALISING);
|
||||
} catch (e) {
|
||||
try {
|
||||
await this.disconnect();
|
||||
} catch(error) {
|
||||
log.warn(LogCategory.NETWORKING, tr("Failed to close connection after connect attempt failed (%o)"), error);
|
||||
}
|
||||
this.client.handleDisconnect(DisconnectReason.CONNECT_FAILURE, e);
|
||||
}
|
||||
}
|
||||
|
||||
updateConnectionState(state: ConnectionState) {
|
||||
this._connectionState = state;
|
||||
this.client.controlBar.update_connection_state();
|
||||
}
|
||||
|
||||
async disconnect(reason?: string) : Promise<void> {
|
||||
if(typeof(reason) === "string") {
|
||||
//TODO send disconnect reason
|
||||
}
|
||||
|
||||
if(this._connectionState == ConnectionState.UNCONNECTED)
|
||||
return;
|
||||
|
||||
this.updateConnectionState(ConnectionState.UNCONNECTED);
|
||||
|
||||
if(this._socket)
|
||||
this._socket.close(3000 + 0xFF, tr("request disconnect"));
|
||||
this._socket = null;
|
||||
for(let future of this._retListener)
|
||||
future.reject(tr("Connection closed"));
|
||||
this._retListener = [];
|
||||
this._retCodeIdx = 0;
|
||||
this._connected = false;
|
||||
}
|
||||
|
||||
private handle_socket_message(data) {
|
||||
if(typeof(data) === "string") {
|
||||
let json;
|
||||
try {
|
||||
json = JSON.parse(data);
|
||||
} catch(e) {
|
||||
console.error(tr("Could not parse message json!"));
|
||||
alert(e); // error in the above string (in this case, yes)!
|
||||
return;
|
||||
}
|
||||
if(json["type"] === undefined) {
|
||||
console.log(tr("Missing data type!"));
|
||||
return;
|
||||
}
|
||||
if(json["type"] === "command") {
|
||||
let group = log.group(log.LogType.DEBUG, LogCategory.NETWORKING, tr("Handling command '%s'"), json["command"]);
|
||||
group.log(tr("Handling command '%s'"), json["command"]);
|
||||
group.group(log.LogType.TRACE, tr("Json:")).collapsed(true).log("%o", json).end();
|
||||
|
||||
this._command_boss.invoke_handle({
|
||||
command: json["command"],
|
||||
arguments: json["data"]
|
||||
});
|
||||
group.end();
|
||||
} else if(json["type"] === "WebRTC") this.client.voiceConnection.handleControlPacket(json);
|
||||
else {
|
||||
console.log(tr("Unknown command type %o"), json["type"]);
|
||||
}
|
||||
} else {
|
||||
log.warn(LogCategory.NETWORKING, tr("Received unknown message of type %s. Dropping message"), typeof(data));
|
||||
}
|
||||
}
|
||||
|
||||
sendData(data: any) {
|
||||
if(!this._socket || this._socket.readyState != 1) {
|
||||
log.warn(LogCategory.NETWORKING, tr("Tried to send on a invalid socket (%s)"), this._socket ? "invalid state (" + this._socket.readyState + ")" : "invalid socket");
|
||||
return;
|
||||
}
|
||||
this._socket.send(data);
|
||||
}
|
||||
|
||||
private commandiefy(input: any) : string {
|
||||
return JSON.stringify(input, (key, value) => {
|
||||
switch (typeof value) {
|
||||
case "boolean": return value == true ? "1" : "0";
|
||||
case "function": return value();
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
send_command(command: string, data?: any | any[], _options?: CommandOptions) : Promise<CommandResult> {
|
||||
if(!this._socket || !this.connected()) {
|
||||
console.warn(tr("Tried to send a command without a valid connection."));
|
||||
return;
|
||||
}
|
||||
|
||||
const options: CommandOptions = {};
|
||||
Object.assign(options, CommandOptionDefaults);
|
||||
Object.assign(options, _options);
|
||||
|
||||
data = $.isArray(data) ? data : [data || {}];
|
||||
|
||||
const _this = this;
|
||||
let result = new Promise<CommandResult>((resolve, failed) => {
|
||||
let _data = $.isArray(data) ? data : [data];
|
||||
let retCode = _data[0]["return_code"] !== undefined ? _data[0].return_code : _this.generateReturnCode();
|
||||
_data[0].return_code = retCode;
|
||||
|
||||
let listener = new ReturnListener<CommandResult>();
|
||||
listener.resolve = resolve;
|
||||
listener.reject = failed;
|
||||
listener.code = retCode;
|
||||
listener.timeout = setTimeout(() => {
|
||||
_this._retListener.remove(listener);
|
||||
listener.reject("timeout");
|
||||
}, 1500);
|
||||
this._retListener.push(listener);
|
||||
|
||||
this._socket.send(this.commandiefy({
|
||||
"type": "command",
|
||||
"command": command,
|
||||
"data": _data,
|
||||
"flags": options.flagset.filter(entry => entry.length != 0)
|
||||
}));
|
||||
});
|
||||
return new Promise<CommandResult>((resolve, failed) => {
|
||||
result.then(resolve).catch(ex => {
|
||||
if(options.process_result) {
|
||||
if(ex instanceof CommandResult) {
|
||||
let res = ex;
|
||||
if(!res.success) {
|
||||
if(res.id == 2568) { //Permission error
|
||||
res.message = tr("Insufficient client permissions. Failed on permission ") + this.client.permissions.resolveInfo(res.json["failed_permid"] as number).name;
|
||||
chat.serverChat().appendError(tr("Insufficient client permissions. Failed on permission {}"), this.client.permissions.resolveInfo(res.json["failed_permid"] as number).name);
|
||||
sound.play(Sound.ERROR_INSUFFICIENT_PERMISSIONS);
|
||||
} else {
|
||||
chat.serverChat().appendError(res.extra_message.length == 0 ? res.message : res.extra_message);
|
||||
}
|
||||
}
|
||||
} else if(typeof(ex) === "string") {
|
||||
chat.serverChat().appendError(tr("Command execution results in ") + ex);
|
||||
} else {
|
||||
console.error(tr("Invalid promise result type: %o. Result:"), typeof (ex));
|
||||
console.error(ex);
|
||||
}
|
||||
}
|
||||
failed(ex);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
connected() : boolean {
|
||||
return this._socket && this._socket.readyState == WebSocket.OPEN;
|
||||
}
|
||||
|
||||
support_voice(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
voice_connection(): connection.AbstractVoiceConnection | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
command_handler_boss(): connection.AbstractCommandHandlerBoss {
|
||||
return this._command_boss;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface ClientNameInfo {
|
||||
//cluid=tYzKUryn\/\/Y8VBMf8PHUT6B1eiE= name=Exp clname=Exp cldbid=9
|
||||
client_unique_id: string;
|
||||
client_nickname: string;
|
||||
client_database_id: number;
|
||||
}
|
||||
|
||||
interface ClientNameFromUid {
|
||||
promise: LaterPromise<ClientNameInfo[]>,
|
||||
keys: string[],
|
||||
response: ClientNameInfo[]
|
||||
}
|
||||
|
||||
interface QueryListEntry {
|
||||
username: string;
|
||||
unique_id: string;
|
||||
bounded_server: number;
|
||||
}
|
||||
|
||||
interface QueryList {
|
||||
flag_own: boolean;
|
||||
flag_all: boolean;
|
||||
|
||||
queries: QueryListEntry[];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -470,6 +470,11 @@ const loader_javascript = {
|
|||
})
|
||||
}
|
||||
|
||||
/* load some extends classes */
|
||||
await loader.load_scripts([
|
||||
["js/connection/ConnectionBase.js"]
|
||||
]);
|
||||
|
||||
/* load the main app */
|
||||
await loader.load_scripts([
|
||||
//Load general API's
|
||||
|
@ -539,11 +544,16 @@ const loader_javascript = {
|
|||
"js/settings.js",
|
||||
"js/bookmarks.js",
|
||||
"js/contextMenu.js",
|
||||
"js/connection.js",
|
||||
"js/FileManager.js",
|
||||
"js/client.js",
|
||||
"js/chat.js",
|
||||
|
||||
//Connection
|
||||
"js/connection/CommandHandler.js",
|
||||
"js/connection/CommandHelper.js",
|
||||
"js/connection/HandshakeHandler.js",
|
||||
"js/connection/ServerConnection.js",
|
||||
|
||||
"js/PPTListener.js",
|
||||
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ class Group {
|
|||
}
|
||||
}
|
||||
|
||||
class GroupManager {
|
||||
class GroupManager extends connection.AbstractCommandHandler {
|
||||
readonly handle: TSClient;
|
||||
|
||||
serverGroups: Group[] = [];
|
||||
|
@ -66,18 +66,29 @@ class GroupManager {
|
|||
|
||||
private requests_group_permissions: GroupPermissionRequest[] = [];
|
||||
constructor(client: TSClient) {
|
||||
super(client.serverConnection);
|
||||
|
||||
client.serverConnection.command_handler_boss().register_handler(this);
|
||||
this.handle = client;
|
||||
}
|
||||
|
||||
this.handle.serverConnection.commandHandler["notifyservergrouplist"] = this.onServerGroupList.bind(this);
|
||||
this.handle.serverConnection.commandHandler["notifychannelgrouplist"] = this.onServerGroupList.bind(this);
|
||||
|
||||
this.handle.serverConnection.commandHandler["notifyservergrouppermlist"] = this.onPermissionList.bind(this);
|
||||
this.handle.serverConnection.commandHandler["notifychannelgrouppermlist"] = this.onPermissionList.bind(this);
|
||||
handle_command(command: connection.ServerCommand): boolean {
|
||||
switch (command.command) {
|
||||
case "notifyservergrouplist":
|
||||
case "notifychannelgrouplist":
|
||||
this.handle_grouplist(command.arguments);
|
||||
return true;
|
||||
case "notifyservergrouppermlist":
|
||||
case "notifychannelgrouppermlist":
|
||||
this.handle_group_permission_list(command.arguments);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
requestGroups(){
|
||||
this.handle.serverConnection.sendCommand("servergrouplist");
|
||||
this.handle.serverConnection.sendCommand("channelgrouplist");
|
||||
this.handle.serverConnection.send_command("servergrouplist");
|
||||
this.handle.serverConnection.send_command("channelgrouplist");
|
||||
}
|
||||
|
||||
static sorter() : (a: Group, b: Group) => number {
|
||||
|
@ -107,7 +118,7 @@ class GroupManager {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
private onServerGroupList(json) {
|
||||
private handle_grouplist(json) {
|
||||
let target : GroupTarget;
|
||||
if(json[0]["sgid"]) target = GroupTarget.SERVER;
|
||||
else if(json[0]["cgid"]) target = GroupTarget.CHANNEL;
|
||||
|
@ -167,7 +178,7 @@ class GroupManager {
|
|||
req.promise = new LaterPromise<PermissionValue[]>();
|
||||
this.requests_group_permissions.push(req);
|
||||
|
||||
this.handle.serverConnection.sendCommand(group.target == GroupTarget.SERVER ? "servergrouppermlist" : "channelgrouppermlist", {
|
||||
this.handle.serverConnection.send_command(group.target == GroupTarget.SERVER ? "servergrouppermlist" : "channelgrouppermlist", {
|
||||
cgid: group.id,
|
||||
sgid: group.id
|
||||
}).catch(error => {
|
||||
|
@ -179,7 +190,7 @@ class GroupManager {
|
|||
return req.promise;
|
||||
}
|
||||
|
||||
private onPermissionList(json: any[]) {
|
||||
private handle_group_permission_list(json: any[]) {
|
||||
let group = json[0]["sgid"] ? this.serverGroup(parseInt(json[0]["sgid"])) : this.channelGroup(parseInt(json[0]["cgid"]));
|
||||
if(!group) {
|
||||
log.error(LogCategory.PERMISSIONS, tr("Got group permissions for group %o/%o, but its not a registered group!"), json[0]["sgid"], json[0]["cgid"]);
|
||||
|
|
|
@ -416,7 +416,7 @@ class TeaPermissionRequest {
|
|||
promise: LaterPromise<PermissionValue[]>;
|
||||
}
|
||||
|
||||
class PermissionManager {
|
||||
class PermissionManager extends connection.AbstractCommandHandler {
|
||||
readonly handle: TSClient;
|
||||
|
||||
permissionList: PermissionInfo[] = [];
|
||||
|
@ -505,14 +505,34 @@ class PermissionManager {
|
|||
}
|
||||
|
||||
constructor(client: TSClient) {
|
||||
super(client.serverConnection);
|
||||
|
||||
//FIXME? Dont register the handler like this?
|
||||
this.volatile_handler_boss = true;
|
||||
client.serverConnection.command_handler_boss().register_handler(this);
|
||||
|
||||
this.handle = client;
|
||||
}
|
||||
|
||||
this.handle.serverConnection.commandHandler["notifyclientneededpermissions"] = this.onNeededPermissions.bind(this);
|
||||
this.handle.serverConnection.commandHandler["notifypermissionlist"] = this.onPermissionList.bind(this);
|
||||
|
||||
this.handle.serverConnection.commandHandler["notifychannelpermlist"] = this.onChannelPermList.bind(this);
|
||||
this.handle.serverConnection.commandHandler["notifyclientpermlist"] = this.onClientPermList.bind(this);
|
||||
this.handle.serverConnection.commandHandler["notifyplaylistpermlist"] = this.onPlaylistPermList.bind(this);
|
||||
handle_command(command: connection.ServerCommand): boolean {
|
||||
switch (command.command) {
|
||||
case "notifyclientneededpermissions":
|
||||
this.onNeededPermissions(command.arguments);
|
||||
return true;
|
||||
case "notifypermissionlist":
|
||||
this.onPermissionList(command.arguments);
|
||||
return true;
|
||||
case "notifychannelpermlist":
|
||||
this.onChannelPermList(command.arguments);
|
||||
return true;
|
||||
case "notifyclientpermlist":
|
||||
this.onClientPermList(command.arguments);
|
||||
return true;
|
||||
case "notifyplaylistpermlist":
|
||||
this.onPlaylistPermList(command.arguments);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
initialized() : boolean {
|
||||
|
@ -520,7 +540,7 @@ class PermissionManager {
|
|||
}
|
||||
|
||||
public requestPermissionList() {
|
||||
this.handle.serverConnection.sendCommand("permissionlist");
|
||||
this.handle.serverConnection.send_command("permissionlist");
|
||||
}
|
||||
|
||||
private onPermissionList(json) {
|
||||
|
@ -648,7 +668,7 @@ class PermissionManager {
|
|||
request = new ChannelPermissionRequest();
|
||||
request.requested = Date.now();
|
||||
request.channel_id = channelId;
|
||||
this.handle.serverConnection.sendCommand("channelpermlist", {"cid": channelId});
|
||||
this.handle.serverConnection.send_command("channelpermlist", {"cid": channelId});
|
||||
this.requests_channel_permissions.push(request);
|
||||
}
|
||||
request.callback_error.push(reject);
|
||||
|
@ -676,7 +696,7 @@ class PermissionManager {
|
|||
request.client_id = client_id;
|
||||
request.promise = new LaterPromise<PermissionValue[]>();
|
||||
|
||||
this.handle.serverConnection.sendCommand("clientpermlist", {cldbid: client_id}).catch(error => {
|
||||
this.handle.serverConnection.send_command("clientpermlist", {cldbid: client_id}).catch(error => {
|
||||
if(error instanceof CommandResult && error.id == ErrorID.EMPTY_RESULT)
|
||||
request.promise.resolved([]);
|
||||
else
|
||||
|
@ -697,7 +717,7 @@ class PermissionManager {
|
|||
request.channel_id = channel_id;
|
||||
request.promise = new LaterPromise<PermissionValue[]>();
|
||||
|
||||
this.handle.serverConnection.sendCommand("channelclientpermlist", {cldbid: client_id, cid: channel_id}).catch(error => {
|
||||
this.handle.serverConnection.send_command("channelclientpermlist", {cldbid: client_id, cid: channel_id}).catch(error => {
|
||||
if(error instanceof CommandResult && error.id == ErrorID.EMPTY_RESULT)
|
||||
request.promise.resolved([]);
|
||||
else
|
||||
|
@ -730,7 +750,7 @@ class PermissionManager {
|
|||
request.playlist_id = playlist_id;
|
||||
request.promise = new LaterPromise<PermissionValue[]>();
|
||||
|
||||
this.handle.serverConnection.sendCommand("playlistpermlist", {playlist_id: playlist_id}).catch(error => {
|
||||
this.handle.serverConnection.send_command("playlistpermlist", {playlist_id: playlist_id}).catch(error => {
|
||||
if(error instanceof CommandResult && error.id == ErrorID.EMPTY_RESULT)
|
||||
request.promise.resolved([]);
|
||||
else
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace profiles {
|
|||
this.identities[identities.IdentitifyType[type].toLowerCase()] = identity;
|
||||
}
|
||||
|
||||
spawn_identity_handshake_handler?(connection: ServerConnection) : HandshakeIdentityHandler {
|
||||
spawn_identity_handshake_handler?(connection: connection.AbstractServerConnection) : connection.HandshakeIdentityHandler {
|
||||
const identity = this.selected_identity();
|
||||
if(!identity)
|
||||
return undefined;
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace profiles.identities {
|
|||
encode?() : string;
|
||||
decode(data: string) : Promise<void>;
|
||||
|
||||
spawn_identity_handshake_handler(connection: ServerConnection) : HandshakeIdentityHandler;
|
||||
spawn_identity_handshake_handler(connection: connection.AbstractServerConnection) : connection.HandshakeIdentityHandler;
|
||||
}
|
||||
|
||||
export async function decode_identity(type: IdentitifyType, data: string) : Promise<Identity> {
|
||||
|
@ -61,12 +61,33 @@ namespace profiles.identities {
|
|||
return identity;
|
||||
}
|
||||
|
||||
export abstract class AbstractHandshakeIdentityHandler implements HandshakeIdentityHandler {
|
||||
connection: ServerConnection;
|
||||
export class HandshakeCommandHandler<T extends AbstractHandshakeIdentityHandler> extends connection.AbstractCommandHandler {
|
||||
readonly handle: T;
|
||||
|
||||
constructor(connection: connection.AbstractServerConnection, handle: T) {
|
||||
super(connection);
|
||||
this.handle = handle;
|
||||
}
|
||||
|
||||
|
||||
handle_command(command: connection.ServerCommand): boolean {
|
||||
if($.isFunction(this[command.command]))
|
||||
this[command.command](command.arguments);
|
||||
else if(command.command == "error") {
|
||||
return false;
|
||||
} else {
|
||||
console.warn(tr("Received unknown command while handshaking (%o)"), command);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class AbstractHandshakeIdentityHandler implements connection.HandshakeIdentityHandler {
|
||||
connection: connection.AbstractServerConnection;
|
||||
|
||||
protected callbacks: ((success: boolean, message?: string) => any)[] = [];
|
||||
|
||||
protected constructor(connection: ServerConnection) {
|
||||
protected constructor(connection: connection.AbstractServerConnection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,16 +3,19 @@
|
|||
namespace profiles.identities {
|
||||
class NameHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
||||
readonly identity: NameIdentity;
|
||||
handler: HandshakeCommandHandler<NameHandshakeHandler>;
|
||||
|
||||
constructor(connection: ServerConnection, identity: profiles.identities.NameIdentity) {
|
||||
constructor(connection: connection.AbstractServerConnection, identity: profiles.identities.NameIdentity) {
|
||||
super(connection);
|
||||
this.identity = identity;
|
||||
|
||||
this.handler = new HandshakeCommandHandler(connection, this);
|
||||
this.handler["handshakeidentityproof"] = () => this.trigger_fail("server requested unexpected proof");
|
||||
}
|
||||
|
||||
start_handshake() {
|
||||
this.connection.commandHandler["handshakeidentityproof"] = () => this.trigger_fail("server requested unexpected proof");
|
||||
|
||||
this.connection.sendCommand("handshakebegin", {
|
||||
this.connection.command_handler_boss().register_handler(this.handler);
|
||||
this.connection.send_command("handshakebegin", {
|
||||
intention: 0,
|
||||
authentication_method: this.identity.type(),
|
||||
client_nickname: this.identity.name()
|
||||
|
@ -24,6 +27,16 @@ namespace profiles.identities {
|
|||
this.trigger_fail("failed to execute begin (" + error + ")");
|
||||
}).then(() => this.trigger_success());
|
||||
}
|
||||
|
||||
protected trigger_fail(message: string) {
|
||||
this.connection.command_handler_boss().unregister_handler(this.handler);
|
||||
super.trigger_fail(message);
|
||||
}
|
||||
|
||||
protected trigger_success() {
|
||||
this.connection.command_handler_boss().unregister_handler(this.handler);
|
||||
super.trigger_success();
|
||||
}
|
||||
}
|
||||
|
||||
export class NameIdentity implements Identity {
|
||||
|
@ -67,7 +80,7 @@ namespace profiles.identities {
|
|||
});
|
||||
}
|
||||
|
||||
spawn_identity_handshake_handler(connection: ServerConnection) : HandshakeIdentityHandler {
|
||||
spawn_identity_handshake_handler(connection: connection.AbstractServerConnection) : connection.HandshakeIdentityHandler {
|
||||
return new NameHandshakeHandler(connection, this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,16 +3,18 @@
|
|||
namespace profiles.identities {
|
||||
class TeaForumHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
||||
readonly identity: TeaForumIdentity;
|
||||
handler: HandshakeCommandHandler<TeaForumHandshakeHandler>;
|
||||
|
||||
constructor(connection: ServerConnection, identity: profiles.identities.TeaForumIdentity) {
|
||||
constructor(connection: connection.AbstractServerConnection, identity: profiles.identities.TeaForumIdentity) {
|
||||
super(connection);
|
||||
this.identity = identity;
|
||||
this.handler = new HandshakeCommandHandler(connection, this);
|
||||
this.handler["handshakeidentityproof"] = this.handle_proof.bind(this);
|
||||
}
|
||||
|
||||
start_handshake() {
|
||||
this.connection.commandHandler["handshakeidentityproof"] = this.handle_proof.bind(this);
|
||||
|
||||
this.connection.sendCommand("handshakebegin", {
|
||||
this.connection.command_handler_boss().register_handler(this.handler);
|
||||
this.connection.send_command("handshakebegin", {
|
||||
intention: 0,
|
||||
authentication_method: this.identity.type(),
|
||||
data: this.identity.data_json()
|
||||
|
@ -27,7 +29,7 @@ namespace profiles.identities {
|
|||
|
||||
|
||||
private handle_proof(json) {
|
||||
this.connection.sendCommand("handshakeindentityproof", {
|
||||
this.connection.send_command("handshakeindentityproof", {
|
||||
proof: this.identity.data_sign()
|
||||
}).catch(error => {
|
||||
console.error(tr("Failed to proof the identity. Error: %o"), error);
|
||||
|
@ -37,6 +39,16 @@ namespace profiles.identities {
|
|||
this.trigger_fail("failed to execute proof (" + error + ")");
|
||||
}).then(() => this.trigger_success());
|
||||
}
|
||||
|
||||
protected trigger_fail(message: string) {
|
||||
this.connection.command_handler_boss().unregister_handler(this.handler);
|
||||
super.trigger_fail(message);
|
||||
}
|
||||
|
||||
protected trigger_success() {
|
||||
this.connection.command_handler_boss().unregister_handler(this.handler);
|
||||
super.trigger_success();
|
||||
}
|
||||
}
|
||||
|
||||
export class TeaForumIdentity implements Identity {
|
||||
|
@ -104,7 +116,7 @@ namespace profiles.identities {
|
|||
});
|
||||
}
|
||||
|
||||
spawn_identity_handshake_handler(connection: ServerConnection) : HandshakeIdentityHandler {
|
||||
spawn_identity_handshake_handler(connection: connection.AbstractServerConnection) : connection.HandshakeIdentityHandler {
|
||||
return new TeaForumHandshakeHandler(connection, this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -198,16 +198,18 @@ namespace profiles.identities {
|
|||
|
||||
class TeaSpeakHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
||||
identity: TeaSpeakIdentity;
|
||||
handler: HandshakeCommandHandler<TeaSpeakHandshakeHandler>;
|
||||
|
||||
constructor(connection: ServerConnection, identity: TeaSpeakIdentity) {
|
||||
constructor(connection: connection.AbstractServerConnection, identity: TeaSpeakIdentity) {
|
||||
super(connection);
|
||||
this.identity = identity;
|
||||
this.handler = new HandshakeCommandHandler(connection, this);
|
||||
this.handler["handshakeidentityproof"] = this.handle_proof.bind(this);
|
||||
}
|
||||
|
||||
start_handshake() {
|
||||
this.connection.commandHandler["handshakeidentityproof"] = this.handle_proof.bind(this);
|
||||
|
||||
this.connection.sendCommand("handshakebegin", {
|
||||
this.connection.command_handler_boss().register_handler(this.handler);
|
||||
this.connection.send_command("handshakebegin", {
|
||||
intention: 0,
|
||||
authentication_method: this.identity.type(),
|
||||
publicKey: this.identity.public_key
|
||||
|
@ -227,7 +229,7 @@ namespace profiles.identities {
|
|||
}
|
||||
|
||||
this.identity.sign_message(json[0]["message"], json[0]["digest"]).then(proof => {
|
||||
this.connection.sendCommand("handshakeindentityproof", {proof: proof}).catch(error => {
|
||||
this.connection.send_command("handshakeindentityproof", {proof: proof}).catch(error => {
|
||||
console.error(tr("Failed to proof the identity. Error: %o"), error);
|
||||
|
||||
if(error instanceof CommandResult)
|
||||
|
@ -238,6 +240,16 @@ namespace profiles.identities {
|
|||
this.trigger_fail("failed to sign message");
|
||||
});
|
||||
}
|
||||
|
||||
protected trigger_fail(message: string) {
|
||||
this.connection.command_handler_boss().unregister_handler(this.handler);
|
||||
super.trigger_fail(message);
|
||||
}
|
||||
|
||||
protected trigger_success() {
|
||||
this.connection.command_handler_boss().unregister_handler(this.handler);
|
||||
super.trigger_success();
|
||||
}
|
||||
}
|
||||
|
||||
class IdentityPOWWorker {
|
||||
|
@ -831,7 +843,7 @@ namespace profiles.identities {
|
|||
return base64ArrayBuffer(buffer.subarray(0, index));
|
||||
}
|
||||
|
||||
spawn_identity_handshake_handler(connection: ServerConnection): HandshakeIdentityHandler {
|
||||
spawn_identity_handshake_handler(connection: connection.AbstractServerConnection): connection.HandshakeIdentityHandler {
|
||||
return new TeaSpeakHandshakeHandler(connection, this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ class ChannelEntry {
|
|||
if(this._cached_channel_description) return new Promise<string>(resolve => resolve(this._cached_channel_description));
|
||||
if(this._cached_channel_description_promise) return this._cached_channel_description_promise;
|
||||
|
||||
this.channelTree.client.serverConnection.sendCommand("channelgetdescription", {cid: this.channelId}).catch(error => {
|
||||
this.channelTree.client.serverConnection.send_command("channelgetdescription", {cid: this.channelId}).catch(error => {
|
||||
this._cached_channel_description_promise_reject(error);
|
||||
});
|
||||
|
||||
|
@ -440,7 +440,7 @@ class ChannelEntry {
|
|||
Modals.createChannelModal(this, undefined, this.channelTree.client.permissions, (changes?, permissions?) => {
|
||||
if(changes) {
|
||||
changes["cid"] = this.channelId;
|
||||
this.channelTree.client.serverConnection.sendCommand("channeledit", changes);
|
||||
this.channelTree.client.serverConnection.send_command("channeledit", changes);
|
||||
log.info(LogCategory.CHANNEL, tr("Changed channel properties of channel %s: %o"), this.channelName(), changes);
|
||||
}
|
||||
|
||||
|
@ -456,7 +456,9 @@ class ChannelEntry {
|
|||
}
|
||||
|
||||
perms[0]["cid"] = this.channelId;
|
||||
this.channelTree.client.serverConnection.sendCommand("channeladdperm", perms, ["continueonerror"]).then(() => {
|
||||
this.channelTree.client.serverConnection.send_command("channeladdperm", perms, {
|
||||
flagset: ["continueonerror"]
|
||||
}).then(() => {
|
||||
sound.play(Sound.CHANNEL_EDITED_SELF);
|
||||
});
|
||||
}
|
||||
|
@ -469,7 +471,7 @@ class ChannelEntry {
|
|||
name: tr("Delete channel"),
|
||||
invalidPermission: !flagDelete,
|
||||
callback: () => {
|
||||
this.channelTree.client.serverConnection.sendCommand("channeldelete", {cid: this.channelId}).then(() => {
|
||||
this.channelTree.client.serverConnection.send_command("channeldelete", {cid: this.channelId}).then(() => {
|
||||
sound.play(Sound.CHANNEL_DELETED);
|
||||
})
|
||||
}
|
||||
|
@ -480,7 +482,7 @@ class ChannelEntry {
|
|||
icon: "client-addon-collection",
|
||||
name: tr("Create music bot"),
|
||||
callback: () => {
|
||||
this.channelTree.client.serverConnection.sendCommand("musicbotcreate", {cid: this.channelId}).then(() => {
|
||||
this.channelTree.client.serverConnection.send_command("musicbotcreate", {cid: this.channelId}).then(() => {
|
||||
createInfoModal(tr("Bot successfully created"), tr("Bot has been successfully created.")).open();
|
||||
}).catch(error => {
|
||||
if(error instanceof CommandResult) {
|
||||
|
@ -692,7 +694,7 @@ class ChannelEntry {
|
|||
});
|
||||
}).open();
|
||||
} else if(this.channelTree.client.getClient().currentChannel() != this)
|
||||
this.channelTree.client.getServerConnection().joinChannel(this, this._cachedPassword).then(() => {
|
||||
this.channelTree.client.getServerConnection().command_helper.joinChannel(this, this._cachedPassword).then(() => {
|
||||
sound.play(Sound.CHANNEL_JOINED);
|
||||
}).catch(error => {
|
||||
if(error instanceof CommandResult) {
|
||||
|
|
|
@ -146,7 +146,7 @@ class ClientEntry {
|
|||
|
||||
const source = client._channel;
|
||||
const self = this.channelTree.client.getClient();
|
||||
this.channelTree.client.serverConnection.sendCommand("clientmove", {
|
||||
this.channelTree.client.serverConnection.send_command("clientmove", {
|
||||
clid: client.clientId(),
|
||||
cid: target.getChannelId()
|
||||
}).then(event => {
|
||||
|
@ -179,7 +179,7 @@ class ClientEntry {
|
|||
entry.name = group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]";
|
||||
if(this.groupAssigned(group)) {
|
||||
entry.callback = () => {
|
||||
this.channelTree.client.serverConnection.sendCommand("servergroupdelclient", {
|
||||
this.channelTree.client.serverConnection.send_command("servergroupdelclient", {
|
||||
sgid: group.id,
|
||||
cldbid: this.properties.client_database_id
|
||||
});
|
||||
|
@ -187,7 +187,7 @@ class ClientEntry {
|
|||
entry.disabled = !this.channelTree.client.permissions.neededPermission(PermissionType.I_GROUP_MEMBER_ADD_POWER).granted(group.requiredMemberRemovePower);
|
||||
} else {
|
||||
entry.callback = () => {
|
||||
this.channelTree.client.serverConnection.sendCommand("servergroupaddclient", {
|
||||
this.channelTree.client.serverConnection.send_command("servergroupaddclient", {
|
||||
sgid: group.id,
|
||||
cldbid: this.properties.client_database_id
|
||||
});
|
||||
|
@ -211,7 +211,7 @@ class ClientEntry {
|
|||
}
|
||||
entry.name = group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]";
|
||||
entry.callback = () => {
|
||||
this.channelTree.client.serverConnection.sendCommand("setclientchannelgroup", {
|
||||
this.channelTree.client.serverConnection.send_command("setclientchannelgroup", {
|
||||
cldbid: this.properties.client_database_id,
|
||||
cgid: group.id,
|
||||
cid: this.currentChannel().channelId
|
||||
|
@ -234,12 +234,12 @@ class ClientEntry {
|
|||
callback: () => {
|
||||
Modals.createServerGroupAssignmentModal(this, (group, flag) => {
|
||||
if(flag) {
|
||||
return this.channelTree.client.serverConnection.sendCommand("servergroupaddclient", {
|
||||
return this.channelTree.client.serverConnection.send_command("servergroupaddclient", {
|
||||
sgid: group.id,
|
||||
cldbid: this.properties.client_database_id
|
||||
}).then(result => true);
|
||||
} else
|
||||
return this.channelTree.client.serverConnection.sendCommand("servergroupdelclient", {
|
||||
return this.channelTree.client.serverConnection.send_command("servergroupdelclient", {
|
||||
sgid: group.id,
|
||||
cldbid: this.properties.client_database_id
|
||||
}).then(result => true);
|
||||
|
@ -286,7 +286,7 @@ class ClientEntry {
|
|||
if(typeof(result) === "string") {
|
||||
//TODO tr
|
||||
console.log("Poking client " + _this.clientNickName() + " with message " + result);
|
||||
_this.channelTree.client.serverConnection.sendCommand("clientpoke", {
|
||||
_this.channelTree.client.serverConnection.send_command("clientpoke", {
|
||||
clid: _this.clientId(),
|
||||
msg: result
|
||||
});
|
||||
|
@ -303,7 +303,7 @@ class ClientEntry {
|
|||
if(typeof(result) === "string") {
|
||||
//TODO tr
|
||||
console.log("Changing " + _this.clientNickName() + "'s description to " + result);
|
||||
_this.channelTree.client.serverConnection.sendCommand("clientedit", {
|
||||
_this.channelTree.client.serverConnection.send_command("clientedit", {
|
||||
clid: _this.clientId(),
|
||||
client_description: result
|
||||
});
|
||||
|
@ -319,7 +319,7 @@ class ClientEntry {
|
|||
icon: "client-move_client_to_own_channel",
|
||||
name: tr("Move client to your channel"),
|
||||
callback: () => {
|
||||
this.channelTree.client.serverConnection.sendCommand("clientmove", {
|
||||
this.channelTree.client.serverConnection.send_command("clientmove", {
|
||||
clid: this.clientId(),
|
||||
cid: this.channelTree.client.getClient().currentChannel().getChannelId()
|
||||
});
|
||||
|
@ -333,7 +333,7 @@ class ClientEntry {
|
|||
if(result) {
|
||||
//TODO tr
|
||||
console.log("Kicking client " + _this.clientNickName() + " from channel with reason " + result);
|
||||
_this.channelTree.client.serverConnection.sendCommand("clientkick", {
|
||||
_this.channelTree.client.serverConnection.send_command("clientkick", {
|
||||
clid: _this.clientId(),
|
||||
reasonid: ViewReasonId.VREASON_CHANNEL_KICK,
|
||||
reasonmsg: result
|
||||
|
@ -351,7 +351,7 @@ class ClientEntry {
|
|||
if(result) {
|
||||
//TODO tr
|
||||
console.log("Kicking client " + _this.clientNickName() + " from server with reason " + result);
|
||||
_this.channelTree.client.serverConnection.sendCommand("clientkick", {
|
||||
_this.channelTree.client.serverConnection.send_command("clientkick", {
|
||||
clid: _this.clientId(),
|
||||
reasonid: ViewReasonId.VREASON_SERVER_KICK,
|
||||
reasonmsg: result
|
||||
|
@ -367,11 +367,13 @@ class ClientEntry {
|
|||
invalidPermission: !this.channelTree.client.permissions.neededPermission(PermissionType.I_CLIENT_BAN_MAX_BANTIME).granted(1),
|
||||
callback: () => {
|
||||
Modals.spawnBanClient(this.properties.client_nickname, (data) => {
|
||||
this.channelTree.client.serverConnection.sendCommand("banclient", {
|
||||
this.channelTree.client.serverConnection.send_command("banclient", {
|
||||
uid: this.properties.client_unique_identifier,
|
||||
banreason: data.reason,
|
||||
time: data.length
|
||||
}, [data.no_ip ? "no-ip" : "", data.no_hwid ? "no-hardware-id" : "", data.no_name ? "no-nickname" : ""]).then(() => {
|
||||
}, {
|
||||
flagset: [data.no_ip ? "no-ip" : "", data.no_hwid ? "no-hardware-id" : "", data.no_name ? "no-nickname" : ""]
|
||||
}).then(() => {
|
||||
sound.play(Sound.USER_BANNED);
|
||||
});
|
||||
});
|
||||
|
@ -386,7 +388,7 @@ class ClientEntry {
|
|||
invalidPermission: true, //!this.channelTree.client.permissions.neededPermission(PermissionType.I_CLIENT_BAN_MAX_BANTIME).granted(1),
|
||||
callback: () => {
|
||||
Modals.spawnBanClient(this.properties.client_nickname, (duration, reason) => {
|
||||
this.channelTree.client.serverConnection.sendCommand("banclient", {
|
||||
this.channelTree.client.serverConnection.send_command("banclient", {
|
||||
uid: this.properties.client_unique_identifier,
|
||||
banreason: reason,
|
||||
time: duration
|
||||
|
@ -653,7 +655,7 @@ class ClientEntry {
|
|||
updateClientVariables(){
|
||||
if(this.lastVariableUpdate == 0 || new Date().getTime() - 10 * 60 * 1000 > this.lastVariableUpdate){ //Cache these only 10 min
|
||||
this.lastVariableUpdate = new Date().getTime();
|
||||
this.channelTree.client.serverConnection.sendCommand("clientgetvariables", {clid: this.clientId()});
|
||||
this.channelTree.client.serverConnection.send_command("clientgetvariables", {clid: this.clientId()});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -667,12 +669,12 @@ class ClientEntry {
|
|||
|
||||
const _this = this;
|
||||
c.onMessageSend = function (text: string) {
|
||||
_this.channelTree.client.serverConnection.sendMessage(text, ChatType.CLIENT, _this);
|
||||
_this.channelTree.client.serverConnection.command_helper.sendMessage(text, ChatType.CLIENT, _this);
|
||||
};
|
||||
|
||||
c.onClose = function () : boolean {
|
||||
//TODO check online?
|
||||
_this.channelTree.client.serverConnection.sendCommand("clientchatclosed", {"clid": _this.clientId()});
|
||||
_this.channelTree.client.serverConnection.send_command("clientchatclosed", {"clid": _this.clientId()});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -797,7 +799,7 @@ class LocalClientEntry extends ClientEntry {
|
|||
createInputModal(tr("Change own description"), tr("New description:<br>"), text => true, result => {
|
||||
if(result) {
|
||||
console.log(tr("Changing own description to %s"), result);
|
||||
_self.channelTree.client.serverConnection.sendCommand("clientedit", {
|
||||
_self.channelTree.client.serverConnection.send_command("clientedit", {
|
||||
clid: _self.clientId(),
|
||||
client_description: result
|
||||
});
|
||||
|
@ -853,7 +855,7 @@ class LocalClientEntry extends ClientEntry {
|
|||
if(_self.clientNickName() == text) return;
|
||||
|
||||
elm.text(_self.clientNickName());
|
||||
_self.handle.serverConnection.updateClient("client_nickname", text).then((e) => {
|
||||
_self.handle.serverConnection.command_helper.updateClient("client_nickname", text).then((e) => {
|
||||
chat.serverChat().appendMessage(tr("Nickname successfully changed"));
|
||||
}).catch((e: CommandResult) => {
|
||||
chat.serverChat().appendError(tr("Could not change nickname ({})"), e.extra_message);
|
||||
|
@ -915,7 +917,7 @@ class MusicClientEntry extends ClientEntry {
|
|||
callback: () => {
|
||||
createInputModal(tr("Change music bots nickname"), tr("New nickname:<br>"), text => text.length >= 3 && text.length <= 31, result => {
|
||||
if(result) {
|
||||
this.channelTree.client.serverConnection.sendCommand("clientedit", {
|
||||
this.channelTree.client.serverConnection.send_command("clientedit", {
|
||||
clid: this.clientId(),
|
||||
client_nickname: result
|
||||
});
|
||||
|
@ -931,7 +933,7 @@ class MusicClientEntry extends ClientEntry {
|
|||
callback: () => {
|
||||
createInputModal(tr("Change music bots description"), tr("New description:<br>"), text => true, result => {
|
||||
if(typeof(result) === 'string') {
|
||||
this.channelTree.client.serverConnection.sendCommand("clientedit", {
|
||||
this.channelTree.client.serverConnection.send_command("clientedit", {
|
||||
clid: this.clientId(),
|
||||
client_description: result
|
||||
});
|
||||
|
@ -955,7 +957,7 @@ class MusicClientEntry extends ClientEntry {
|
|||
icon: "client-edit",
|
||||
disabled: false,
|
||||
callback: () => {
|
||||
this.channelTree.client.serverConnection.helper.request_playlist_list().then(lists => {
|
||||
this.channelTree.client.serverConnection.command_helper.request_playlist_list().then(lists => {
|
||||
for(const entry of lists) {
|
||||
if(entry.playlist_id == this.properties.client_playlist_id) {
|
||||
Modals.spawnPlaylistEdit(this.channelTree.client, entry);
|
||||
|
@ -976,7 +978,7 @@ class MusicClientEntry extends ClientEntry {
|
|||
callback: () => {
|
||||
createInputModal(tr("Please enter the URL"), tr("URL:"), text => true, result => {
|
||||
if(result) {
|
||||
this.channelTree.client.serverConnection.sendCommand("musicbotqueueadd", {
|
||||
this.channelTree.client.serverConnection.send_command("musicbotqueueadd", {
|
||||
bot_id: this.properties.client_database_id,
|
||||
type: "yt", //Its a hint not a force!
|
||||
url: result
|
||||
|
@ -999,7 +1001,7 @@ class MusicClientEntry extends ClientEntry {
|
|||
icon: "client-move_client_to_own_channel",
|
||||
name: tr("Move client to your channel"),
|
||||
callback: () => {
|
||||
this.channelTree.client.serverConnection.sendCommand("clientmove", {
|
||||
this.channelTree.client.serverConnection.send_command("clientmove", {
|
||||
clid: this.clientId(),
|
||||
cid: this.channelTree.client.getClient().currentChannel().getChannelId()
|
||||
});
|
||||
|
@ -1012,7 +1014,7 @@ class MusicClientEntry extends ClientEntry {
|
|||
createInputModal(tr("Kick client from channel"), tr("Kick reason:<br>"), text => true, result => {
|
||||
if(result) {
|
||||
console.log(tr("Kicking client %o from channel with reason %o"), this.clientNickName(), result);
|
||||
this.channelTree.client.serverConnection.sendCommand("clientkick", {
|
||||
this.channelTree.client.serverConnection.send_command("clientkick", {
|
||||
clid: this.clientId(),
|
||||
reasonid: ViewReasonId.VREASON_CHANNEL_KICK,
|
||||
reasonmsg: result
|
||||
|
@ -1045,7 +1047,7 @@ class MusicClientEntry extends ClientEntry {
|
|||
max_volume = 100;
|
||||
|
||||
Modals.spawnChangeRemoteVolume(this.properties.player_volume, max_volume / 100, value => {
|
||||
this.channelTree.client.serverConnection.sendCommand("clientedit", {
|
||||
this.channelTree.client.serverConnection.send_command("clientedit", {
|
||||
clid: this.clientId(),
|
||||
player_volume: value,
|
||||
}).then(() => {
|
||||
|
@ -1064,7 +1066,7 @@ class MusicClientEntry extends ClientEntry {
|
|||
const tag = $.spawn("div").append(MessageHelper.formatMessage(tr("Do you really want to delete {0}"), this.createChatTag(false)));
|
||||
Modals.spawnYesNo(tr("Are you sure?"), $.spawn("div").append(tag), result => {
|
||||
if(result) {
|
||||
this.channelTree.client.serverConnection.sendCommand("musicbotdelete", {
|
||||
this.channelTree.client.serverConnection.send_command("musicbotdelete", {
|
||||
bot_id: this.properties.client_database_id
|
||||
});
|
||||
}
|
||||
|
@ -1105,7 +1107,7 @@ class MusicClientEntry extends ClientEntry {
|
|||
this._info_promise_resolve = resolve;
|
||||
});
|
||||
|
||||
this.channelTree.client.serverConnection.sendCommand("musicbotplayerinfo", {bot_id: this.properties.client_database_id });
|
||||
this.channelTree.client.serverConnection.send_command("musicbotplayerinfo", {bot_id: this.properties.client_database_id });
|
||||
return this._info_promise;
|
||||
}
|
||||
}
|
|
@ -137,7 +137,7 @@ class ControlBar {
|
|||
|
||||
|
||||
if(this.handle.serverConnection.connected)
|
||||
this.handle.serverConnection.sendCommand("clientupdate", {
|
||||
this.handle.serverConnection.send_command("clientupdate", {
|
||||
client_input_muted: this._muteInput
|
||||
});
|
||||
settings.changeGlobal("mute_input", this._muteInput);
|
||||
|
@ -162,7 +162,7 @@ class ControlBar {
|
|||
}
|
||||
|
||||
if(this.handle.serverConnection.connected)
|
||||
this.handle.serverConnection.sendCommand("clientupdate", {
|
||||
this.handle.serverConnection.send_command("clientupdate", {
|
||||
client_output_muted: this._muteOutput
|
||||
});
|
||||
settings.changeGlobal("mute_output", this._muteOutput);
|
||||
|
@ -187,7 +187,7 @@ class ControlBar {
|
|||
}
|
||||
|
||||
if(this.handle.serverConnection.connected)
|
||||
this.handle.serverConnection.sendCommand("clientupdate", {
|
||||
this.handle.serverConnection.send_command("clientupdate", {
|
||||
client_away: this._away,
|
||||
client_away_message: this._awayMessage
|
||||
});
|
||||
|
@ -201,7 +201,7 @@ class ControlBar {
|
|||
|
||||
updateProperties() {
|
||||
if(this.handle.serverConnection.connected)
|
||||
this.handle.serverConnection.sendCommand("clientupdate", {
|
||||
this.handle.serverConnection.send_command("clientupdate", {
|
||||
client_input_muted: this._muteInput,
|
||||
client_output_muted: this._muteOutput,
|
||||
client_away: this._away,
|
||||
|
@ -221,7 +221,7 @@ class ControlBar {
|
|||
|
||||
this.htmlTag.find(".btn_mute_input").prop("disabled", !this.codec_supported|| !this.support_playback || !this.support_record);
|
||||
this.htmlTag.find(".btn_mute_output").prop("disabled", !this.codec_supported || !this.support_playback);
|
||||
this.handle.serverConnection.sendCommand("clientupdate", {
|
||||
this.handle.serverConnection.send_command("clientupdate", {
|
||||
client_input_hardware: this.codec_supported && this.support_record,
|
||||
client_output_hardware: this.codec_supported && this.support_playback
|
||||
});
|
||||
|
@ -273,7 +273,7 @@ class ControlBar {
|
|||
createInputModal(tr("Use token"), tr("Please enter your token/priviledge key"), message => message.length > 0, result => {
|
||||
if(!result) return;
|
||||
if(this.handle.serverConnection.connected)
|
||||
this.handle.serverConnection.sendCommand("tokenuse", {
|
||||
this.handle.serverConnection.send_command("tokenuse", {
|
||||
token: result
|
||||
}).then(() => {
|
||||
createInfoModal(tr("Use token"), tr("Toke successfully used!")).open();
|
||||
|
|
|
@ -412,7 +412,7 @@ enum MusicPlayerState {
|
|||
}
|
||||
|
||||
class MusicInfoManager extends ClientInfoManager {
|
||||
notify_status: (json) => any;
|
||||
single_handler: connection.SingleCommandHandler;
|
||||
|
||||
createFrame<_>(handle: InfoBar<_>, channel: MusicClientEntry, html_tag: JQuery<HTMLElement>) {
|
||||
super.createFrame(handle, channel, html_tag);
|
||||
|
@ -420,9 +420,9 @@ class MusicInfoManager extends ClientInfoManager {
|
|||
}
|
||||
|
||||
updateFrame(bot: MusicClientEntry, html_tag: JQuery<HTMLElement>) {
|
||||
if(this.notify_status) {
|
||||
this.handle.handle.serverConnection.commandHandler.unset_handler("notifymusicstatusupdate", this.notify_status);
|
||||
this.notify_status = undefined;
|
||||
if(this.single_handler) {
|
||||
this.handle.handle.serverConnection.command_handler_boss().remove_single_handler(this.single_handler);
|
||||
this.single_handler = undefined;
|
||||
}
|
||||
|
||||
this.resetIntervals();
|
||||
|
@ -459,7 +459,7 @@ class MusicInfoManager extends ClientInfoManager {
|
|||
let button_stop = frame.find('.button_stop');
|
||||
button_play.click(handler => {
|
||||
if(!button_play.hasClass("active")) {
|
||||
this.handle.handle.serverConnection.sendCommand("musicbotplayeraction", {
|
||||
this.handle.handle.serverConnection.send_command("musicbotplayeraction", {
|
||||
bot_id: bot.properties.client_database_id,
|
||||
action: 1
|
||||
}).then(updated => this.triggerUpdate()).catch(error => {
|
||||
|
@ -472,7 +472,7 @@ class MusicInfoManager extends ClientInfoManager {
|
|||
});
|
||||
button_pause.click(handler => {
|
||||
if(!button_pause.hasClass("active")) {
|
||||
this.handle.handle.serverConnection.sendCommand("musicbotplayeraction", {
|
||||
this.handle.handle.serverConnection.send_command("musicbotplayeraction", {
|
||||
bot_id: bot.properties.client_database_id,
|
||||
action: 2
|
||||
}).then(updated => this.triggerUpdate()).catch(error => {
|
||||
|
@ -484,7 +484,7 @@ class MusicInfoManager extends ClientInfoManager {
|
|||
button_pause.hide();
|
||||
});
|
||||
button_stop.click(handler => {
|
||||
this.handle.handle.serverConnection.sendCommand("musicbotplayeraction", {
|
||||
this.handle.handle.serverConnection.send_command("musicbotplayeraction", {
|
||||
bot_id: bot.properties.client_database_id,
|
||||
action: 0
|
||||
}).then(updated => this.triggerUpdate()).catch(error => {
|
||||
|
@ -507,7 +507,7 @@ class MusicInfoManager extends ClientInfoManager {
|
|||
|
||||
{ /* Button functions */
|
||||
_frame.find(".btn-forward").click(() => {
|
||||
this.handle.handle.serverConnection.sendCommand("musicbotplayeraction", {
|
||||
this.handle.handle.serverConnection.send_command("musicbotplayeraction", {
|
||||
bot_id: bot.properties.client_database_id,
|
||||
action: 3
|
||||
}).then(updated => this.triggerUpdate()).catch(error => {
|
||||
|
@ -516,7 +516,7 @@ class MusicInfoManager extends ClientInfoManager {
|
|||
});
|
||||
});
|
||||
_frame.find(".btn-rewind").click(() => {
|
||||
this.handle.handle.serverConnection.sendCommand("musicbotplayeraction", {
|
||||
this.handle.handle.serverConnection.send_command("musicbotplayeraction", {
|
||||
bot_id: bot.properties.client_database_id,
|
||||
action: 4
|
||||
}).then(updated => this.triggerUpdate()).catch(error => {
|
||||
|
@ -525,7 +525,7 @@ class MusicInfoManager extends ClientInfoManager {
|
|||
});
|
||||
});
|
||||
_frame.find(".btn-settings").click(() => {
|
||||
this.handle.handle.serverConnection.helper.request_playlist_list().then(lists => {
|
||||
this.handle.handle.serverConnection.command_helper.request_playlist_list().then(lists => {
|
||||
for(const entry of lists) {
|
||||
if(entry.playlist_id == bot.properties.client_playlist_id) {
|
||||
Modals.spawnPlaylistEdit(bot.channelTree.client, entry);
|
||||
|
@ -581,7 +581,7 @@ class MusicInfoManager extends ClientInfoManager {
|
|||
slider.prop("edited", true);
|
||||
|
||||
let current_timestamp = info.player_replay_index + Date.now() - timestamp;
|
||||
this.handle.handle.serverConnection.sendCommand("musicbotplayeraction", {
|
||||
this.handle.handle.serverConnection.send_command("musicbotplayeraction", {
|
||||
bot_id: bot.properties.client_database_id,
|
||||
action: current_timestamp > target_timestamp ? 6 : 5,
|
||||
units: current_timestamp < target_timestamp ? target_timestamp - current_timestamp : current_timestamp - target_timestamp
|
||||
|
@ -627,17 +627,23 @@ class MusicInfoManager extends ClientInfoManager {
|
|||
update_handler();
|
||||
|
||||
/* register subscription */
|
||||
this.handle.handle.serverConnection.sendCommand("musicbotsetsubscription", {bot_id: bot.properties.client_database_id}).catch(error => {
|
||||
this.handle.handle.serverConnection.send_command("musicbotsetsubscription", {bot_id: bot.properties.client_database_id}).catch(error => {
|
||||
console.error("Failed to subscribe to displayed music bot! Using pseudo timeline");
|
||||
}).then(() => {
|
||||
clearInterval(interval);
|
||||
});
|
||||
|
||||
this.notify_status = json => {
|
||||
json = json[0];
|
||||
update_handler(parseInt(json["player_replay_index"]), parseInt(json["player_buffered_index"]));
|
||||
this.single_handler = {
|
||||
command: "notifymusicstatusupdate",
|
||||
function: command => {
|
||||
const json = command.arguments[0];
|
||||
update_handler(parseInt(json["player_replay_index"]), parseInt(json["player_buffered_index"]));
|
||||
|
||||
return false; /* do not unregister me! */
|
||||
}
|
||||
};
|
||||
this.handle.handle.serverConnection.commandHandler.set_handler("notifymusicstatusupdate", this.notify_status);
|
||||
|
||||
this.handle.handle.serverConnection.command_handler_boss().register_single_handler(this.single_handler);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -718,9 +724,9 @@ class MusicInfoManager extends ClientInfoManager {
|
|||
}
|
||||
|
||||
finalizeFrame(object: ClientEntry, frame: JQuery<HTMLElement>) {
|
||||
if(this.notify_status) {
|
||||
this.handle.handle.serverConnection.commandHandler.unset_handler("notifymusicstatusupdate", this.notify_status);
|
||||
this.notify_status = undefined;
|
||||
if(this.single_handler) {
|
||||
this.handle.handle.serverConnection.command_handler_boss().remove_single_handler(this.single_handler);
|
||||
this.single_handler = undefined;
|
||||
}
|
||||
|
||||
super.finalizeFrame(object, frame);
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace Modals {
|
|||
if(result.server_id < 0) result.server_id = undefined;
|
||||
console.log(tr("Adding ban %o"), result);
|
||||
|
||||
client.serverConnection.sendCommand("banadd", {
|
||||
client.serverConnection.send_command("banadd", {
|
||||
ip: result.ip,
|
||||
name: result.name,
|
||||
uid: result.unique_id,
|
||||
|
@ -55,7 +55,7 @@ namespace Modals {
|
|||
console.log(tr("Apply edit changes %o"), result);
|
||||
if(result.server_id < 0) result.server_id = undefined;
|
||||
|
||||
client.serverConnection.sendCommand("banedit", {
|
||||
client.serverConnection.send_command("banedit", {
|
||||
banid: result.banid,
|
||||
ip: result.ip,
|
||||
name: result.name,
|
||||
|
@ -73,7 +73,7 @@ namespace Modals {
|
|||
});
|
||||
}, ban => {
|
||||
console.log(tr("Deleting ban %o"), ban);
|
||||
client.serverConnection.sendCommand("bandel", {
|
||||
client.serverConnection.send_command("bandel", {
|
||||
banid: ban.banid,
|
||||
sid: ban.server_id
|
||||
}).then(() => {
|
||||
|
@ -140,8 +140,8 @@ namespace Modals {
|
|||
|
||||
//TODO test permission
|
||||
modal.clear();
|
||||
client.serverConnection.sendCommand("banlist", { sid: 0 }); //Global ban list
|
||||
client.serverConnection.sendCommand("banlist").catch(error => {
|
||||
client.serverConnection.send_command("banlist", { sid: 0 }); //Global ban list
|
||||
client.serverConnection.send_command("banlist").catch(error => {
|
||||
if(error instanceof CommandResult) {
|
||||
} else {
|
||||
console.error(error);
|
||||
|
|
|
@ -665,7 +665,7 @@ namespace Modals {
|
|||
permission.id,
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("channelclientdelperm", {
|
||||
return globalClient.serverConnection.send_command("channelclientdelperm", {
|
||||
cldbid: current_cldbid,
|
||||
cid: current_channel.channelId,
|
||||
permid: permission.id,
|
||||
|
@ -677,7 +677,7 @@ namespace Modals {
|
|||
value.granted,
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("channelclientdelperm", {
|
||||
return globalClient.serverConnection.send_command("channelclientdelperm", {
|
||||
cldbid: current_cldbid,
|
||||
cid: current_channel.channelId,
|
||||
permid: permission.id_grant(),
|
||||
|
@ -694,7 +694,7 @@ namespace Modals {
|
|||
value.flag_negate
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("channelclientaddperm", {
|
||||
return globalClient.serverConnection.send_command("channelclientaddperm", {
|
||||
cldbid: current_cldbid,
|
||||
cid: current_channel.channelId,
|
||||
permid: permission.id,
|
||||
|
@ -709,7 +709,7 @@ namespace Modals {
|
|||
value.granted,
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("channelclientaddperm", {
|
||||
return globalClient.serverConnection.send_command("channelclientaddperm", {
|
||||
cldbid: current_cldbid,
|
||||
cid: current_channel.channelId,
|
||||
permid: permission.id_grant(),
|
||||
|
@ -821,7 +821,7 @@ namespace Modals {
|
|||
permission.id,
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("clientaddperm", {
|
||||
return globalClient.serverConnection.send_command("clientaddperm", {
|
||||
cldbid: current_cldbid,
|
||||
permid: permission.id,
|
||||
});
|
||||
|
@ -832,7 +832,7 @@ namespace Modals {
|
|||
value.granted,
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("clientaddperm", {
|
||||
return globalClient.serverConnection.send_command("clientaddperm", {
|
||||
cldbid: current_cldbid,
|
||||
permid: permission.id_grant(),
|
||||
});
|
||||
|
@ -848,7 +848,7 @@ namespace Modals {
|
|||
value.flag_negate
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("clientaddperm", {
|
||||
return globalClient.serverConnection.send_command("clientaddperm", {
|
||||
cldbid: current_cldbid,
|
||||
permid: permission.id,
|
||||
permvalue: value.value,
|
||||
|
@ -862,7 +862,7 @@ namespace Modals {
|
|||
value.granted,
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("clientaddperm", {
|
||||
return globalClient.serverConnection.send_command("clientaddperm", {
|
||||
cldbid: current_cldbid,
|
||||
permid: permission.id_grant(),
|
||||
permvalue: value.granted,
|
||||
|
@ -956,7 +956,7 @@ namespace Modals {
|
|||
permission.id,
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("channeldelperm", {
|
||||
return globalClient.serverConnection.send_command("channeldelperm", {
|
||||
cid: current_channel.channelId,
|
||||
permid: permission.id,
|
||||
});
|
||||
|
@ -968,7 +968,7 @@ namespace Modals {
|
|||
value.granted,
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("channeldelperm", {
|
||||
return globalClient.serverConnection.send_command("channeldelperm", {
|
||||
cid: current_channel.channelId,
|
||||
permid: permission.id_grant(),
|
||||
});
|
||||
|
@ -984,7 +984,7 @@ namespace Modals {
|
|||
value.flag_negate
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("channeladdperm", {
|
||||
return globalClient.serverConnection.send_command("channeladdperm", {
|
||||
cid: current_channel.channelId,
|
||||
permid: permission.id,
|
||||
permvalue: value.value,
|
||||
|
@ -999,7 +999,7 @@ namespace Modals {
|
|||
value.granted,
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("channeladdperm", {
|
||||
return globalClient.serverConnection.send_command("channeladdperm", {
|
||||
cid: current_channel.channelId,
|
||||
permid: permission.id_grant(),
|
||||
permvalue: value.granted,
|
||||
|
@ -1058,7 +1058,7 @@ namespace Modals {
|
|||
permission.id,
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("channelgroupdelperm", {
|
||||
return globalClient.serverConnection.send_command("channelgroupdelperm", {
|
||||
cgid: current_group.id,
|
||||
permid: permission.id,
|
||||
});
|
||||
|
@ -1069,7 +1069,7 @@ namespace Modals {
|
|||
value.granted,
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("channelgroupdelperm", {
|
||||
return globalClient.serverConnection.send_command("channelgroupdelperm", {
|
||||
cgid: current_group.id,
|
||||
permid: permission.id_grant(),
|
||||
});
|
||||
|
@ -1085,7 +1085,7 @@ namespace Modals {
|
|||
value.flag_negate
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("channelgroupaddperm", {
|
||||
return globalClient.serverConnection.send_command("channelgroupaddperm", {
|
||||
cgid: current_group.id,
|
||||
permid: permission.id,
|
||||
permvalue: value.value,
|
||||
|
@ -1099,7 +1099,7 @@ namespace Modals {
|
|||
value.granted,
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("channelgroupaddperm", {
|
||||
return globalClient.serverConnection.send_command("channelgroupaddperm", {
|
||||
cgid: current_group.id,
|
||||
permid: permission.id_grant(),
|
||||
permvalue: value.granted,
|
||||
|
@ -1218,7 +1218,7 @@ namespace Modals {
|
|||
permission.id,
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("servergroupdelperm", {
|
||||
return globalClient.serverConnection.send_command("servergroupdelperm", {
|
||||
sgid: current_group.id,
|
||||
permid: permission.id,
|
||||
});
|
||||
|
@ -1229,7 +1229,7 @@ namespace Modals {
|
|||
value.granted,
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("servergroupdelperm", {
|
||||
return globalClient.serverConnection.send_command("servergroupdelperm", {
|
||||
sgid: current_group.id,
|
||||
permid: permission.id_grant(),
|
||||
});
|
||||
|
@ -1245,7 +1245,7 @@ namespace Modals {
|
|||
value.flag_negate
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("servergroupaddperm", {
|
||||
return globalClient.serverConnection.send_command("servergroupaddperm", {
|
||||
sgid: current_group.id,
|
||||
permid: permission.id,
|
||||
permvalue: value.value,
|
||||
|
@ -1259,7 +1259,7 @@ namespace Modals {
|
|||
value.granted,
|
||||
);
|
||||
|
||||
return globalClient.serverConnection.sendCommand("servergroupaddperm", {
|
||||
return globalClient.serverConnection.send_command("servergroupaddperm", {
|
||||
sgid: current_group.id,
|
||||
permid: permission.id_grant(),
|
||||
permvalue: value.granted,
|
||||
|
|
|
@ -99,7 +99,7 @@ namespace Modals {
|
|||
template.find(".buttons .button-save").on('click', event => {
|
||||
if(Object.keys(changed_properties).length != 0) {
|
||||
changed_properties["playlist_id"] = playlist.playlist_id;
|
||||
client.serverConnection.sendCommand("playlistedit", changed_properties).then(() => {
|
||||
client.serverConnection.send_command("playlistedit", changed_properties).then(() => {
|
||||
changed_properties = {};
|
||||
update_save();
|
||||
}).catch(error => {
|
||||
|
@ -121,7 +121,7 @@ namespace Modals {
|
|||
}
|
||||
|
||||
array[0]["playlist_id"] = playlist.playlist_id;
|
||||
client.serverConnection.sendCommand("playlistaddperm", array).then(() => {
|
||||
client.serverConnection.send_command("playlistaddperm", array).then(() => {
|
||||
changed_permissions = {};
|
||||
update_save();
|
||||
}).catch(error => {
|
||||
|
@ -193,7 +193,7 @@ namespace Modals {
|
|||
button_delete.detach();
|
||||
else
|
||||
button_delete.on('click', event => {
|
||||
client.serverConnection.sendCommand("playlistsongremove", {
|
||||
client.serverConnection.send_command("playlistsongremove", {
|
||||
playlist_id: playlist.playlist_id,
|
||||
song_id: song.song_id
|
||||
}).then(() => {
|
||||
|
@ -236,7 +236,7 @@ namespace Modals {
|
|||
song_tag.find(".button-song-add").on('click', event => {
|
||||
spawnSongAdd(playlist, (url, loader) => {
|
||||
//playlist_id invoker previous url
|
||||
client.serverConnection.sendCommand("playlistsongadd", {
|
||||
client.serverConnection.send_command("playlistsongadd", {
|
||||
playlist_id: playlist.playlist_id,
|
||||
invoker: loader,
|
||||
url: url
|
||||
|
|
|
@ -108,7 +108,7 @@ namespace Modals {
|
|||
});
|
||||
};
|
||||
client.serverConnection.commandHandler.set_handler("notifyplaylistcreated", notify_handler);
|
||||
client.serverConnection.sendCommand("playlistcreate").catch(error => {
|
||||
client.serverConnection.send_command("playlistcreate").catch(error => {
|
||||
client.serverConnection.commandHandler.unset_handler("notifyplaylistcreated", notify_handler);
|
||||
if(error instanceof CommandResult)
|
||||
error = error.extra_message || error.message;
|
||||
|
@ -126,7 +126,7 @@ namespace Modals {
|
|||
|
||||
Modals.spawnYesNo(tr("Are you sure?"), tr("Do you really want to delete this playlist?"), result => {
|
||||
if(result) {
|
||||
client.serverConnection.sendCommand("playlistdelete", {playlist_id: selected_playlist.playlist_id}).then(() => {
|
||||
client.serverConnection.send_command("playlistdelete", {playlist_id: selected_playlist.playlist_id}).then(() => {
|
||||
createInfoModal(tr("Playlist deleted successful"), tr("This playlist has been deleted successfully.")).open();
|
||||
update_list();
|
||||
}).catch(error => {
|
||||
|
|
|
@ -19,8 +19,8 @@ namespace Modals {
|
|||
const update_list = () => {
|
||||
const info_tag = modal.htmlTag.find(".footer .info a");
|
||||
info_tag.text("loading...");
|
||||
client.serverConnection.helper.current_virtual_server_id().then(server_id => {
|
||||
client.serverConnection.helper.request_query_list(server_id).then(result => {
|
||||
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");
|
||||
|
@ -73,7 +73,7 @@ namespace Modals {
|
|||
|
||||
createInputModal(tr("Change account name"), tr("Enter the new name for the login:<br>"), text => text.length >= 3, result => {
|
||||
if(result) {
|
||||
client.serverConnection.sendCommand("queryrename", {
|
||||
client.serverConnection.send_command("queryrename", {
|
||||
client_login_name: selected_query.username,
|
||||
client_new_login_name: result
|
||||
}).catch(error => {
|
||||
|
@ -92,23 +92,28 @@ namespace Modals {
|
|||
|
||||
createInputModal(tr("Change account's password"), tr("Enter a new password (leave blank for auto generation):<br>"), text => true, result => {
|
||||
if(result !== false) {
|
||||
client.serverConnection.sendCommand("querychangepassword", {
|
||||
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<br>Message: ") + error).open();
|
||||
});
|
||||
|
||||
client.serverConnection.commandHandler["notifyquerypasswordchanges"] = json => {
|
||||
Modals.spawnQueryCreated({
|
||||
username: json[0]["client_login_name"],
|
||||
password: json[0]["client_login_password"]
|
||||
}, false);
|
||||
|
||||
client.serverConnection.commandHandler["notifyquerypasswordchanges"] = undefined;
|
||||
};
|
||||
}
|
||||
}).open();
|
||||
});
|
||||
|
@ -117,7 +122,7 @@ namespace Modals {
|
|||
|
||||
Modals.spawnYesNo(tr("Are you sure?"), tr("Do you really want to delete this account?"), result => {
|
||||
if(result) {
|
||||
client.serverConnection.sendCommand("querydelete", {
|
||||
client.serverConnection.send_command("querydelete", {
|
||||
client_login_name: selected_query.username
|
||||
}).catch(error => {
|
||||
if(error instanceof CommandResult)
|
||||
|
|
|
@ -144,7 +144,7 @@ class ServerEntry {
|
|||
log.info(LogCategory.SERVER, tr("Changing server properties %o"), properties);
|
||||
console.log(tr("Changed properties: %o"), properties);
|
||||
if (properties)
|
||||
this.channelTree.client.serverConnection.sendCommand("serveredit", properties).then(() => {
|
||||
this.channelTree.client.serverConnection.send_command("serveredit", properties).then(() => {
|
||||
sound.play(Sound.SERVER_EDITED_SELF);
|
||||
});
|
||||
});
|
||||
|
@ -200,7 +200,7 @@ class ServerEntry {
|
|||
if(this.info_request_promise && Date.now() - this.lastInfoRequest < 1000) return this.info_request_promise;
|
||||
this.lastInfoRequest = Date.now();
|
||||
this.nextInfoRequest = this.lastInfoRequest + 10 * 1000;
|
||||
this.channelTree.client.serverConnection.sendCommand("servergetvariables").catch(error => {
|
||||
this.channelTree.client.serverConnection.send_command("servergetvariables").catch(error => {
|
||||
this.info_request_promise_reject(error);
|
||||
this.info_request_promise = undefined;
|
||||
this.info_request_promise_reject = undefined;
|
||||
|
|
|
@ -450,7 +450,7 @@ class ChannelTree {
|
|||
createInputModal(tr("Poke clients"), tr("Poke message:<br>"), text => true, result => {
|
||||
if (typeof(result) === "string") {
|
||||
for (const client of this.currently_selected as ClientEntry[])
|
||||
this.client.serverConnection.sendCommand("clientpoke", {
|
||||
this.client.serverConnection.send_command("clientpoke", {
|
||||
clid: client.clientId(),
|
||||
msg: result
|
||||
});
|
||||
|
@ -467,7 +467,7 @@ class ChannelTree {
|
|||
callback: () => {
|
||||
const target = this.client.getClient().currentChannel().getChannelId();
|
||||
for(const client of clients)
|
||||
this.client.serverConnection.sendCommand("clientmove", {
|
||||
this.client.serverConnection.send_command("clientmove", {
|
||||
clid: client.clientId(),
|
||||
cid: target
|
||||
});
|
||||
|
@ -483,7 +483,7 @@ class ChannelTree {
|
|||
createInputModal(tr("Kick clients from channel"), tr("Kick reason:<br>"), text => true, result => {
|
||||
if (result) {
|
||||
for (const client of clients)
|
||||
this.client.serverConnection.sendCommand("clientkick", {
|
||||
this.client.serverConnection.send_command("clientkick", {
|
||||
clid: client.clientId(),
|
||||
reasonid: ViewReasonId.VREASON_CHANNEL_KICK,
|
||||
reasonmsg: result
|
||||
|
@ -503,7 +503,7 @@ class ChannelTree {
|
|||
createInputModal(tr("Kick clients from server"), tr("Kick reason:<br>"), text => true, result => {
|
||||
if (result) {
|
||||
for (const client of clients)
|
||||
this.client.serverConnection.sendCommand("clientkick", {
|
||||
this.client.serverConnection.send_command("clientkick", {
|
||||
clid: client.clientId(),
|
||||
reasonid: ViewReasonId.VREASON_SERVER_KICK,
|
||||
reasonmsg: result
|
||||
|
@ -520,11 +520,13 @@ class ChannelTree {
|
|||
callback: () => {
|
||||
Modals.spawnBanClient((clients).map(entry => entry.clientNickName()), (data) => {
|
||||
for (const client of clients)
|
||||
this.client.serverConnection.sendCommand("banclient", {
|
||||
this.client.serverConnection.send_command("banclient", {
|
||||
uid: client.properties.client_unique_identifier,
|
||||
banreason: data.reason,
|
||||
time: data.length
|
||||
}, [data.no_ip ? "no-ip" : "", data.no_hwid ? "no-hardware-id" : "", data.no_name ? "no-nickname" : ""]).then(() => {
|
||||
}, {
|
||||
flagset: [data.no_ip ? "no-ip" : "", data.no_hwid ? "no-hardware-id" : "", data.no_name ? "no-nickname" : ""]
|
||||
}).then(() => {
|
||||
sound.play(Sound.USER_BANNED);
|
||||
});
|
||||
});
|
||||
|
@ -545,7 +547,7 @@ class ChannelTree {
|
|||
Modals.spawnYesNo(tr("Are you sure?"), tag_container, result => {
|
||||
if(result) {
|
||||
for(const client of clients)
|
||||
this.client.serverConnection.sendCommand("musicbotdelete", {
|
||||
this.client.serverConnection.send_command("musicbotdelete", {
|
||||
botid: client.properties.client_database_id
|
||||
});
|
||||
}
|
||||
|
@ -595,7 +597,7 @@ class ChannelTree {
|
|||
if(!properties) return;
|
||||
properties["cpid"] = parent ? parent.channelId : 0;
|
||||
log.debug(LogCategory.CHANNEL, tr("Creating a new channel.\nProperties: %o\nPermissions: %o"), properties);
|
||||
this.client.serverConnection.sendCommand("channelcreate", properties).then(() => {
|
||||
this.client.serverConnection.send_command("channelcreate", properties).then(() => {
|
||||
let channel = this.find_channel_by_name(properties.channel_name, parent, true);
|
||||
if(!channel) {
|
||||
log.error(LogCategory.CHANNEL, tr("Failed to resolve channel after creation. Could not apply permissions!"));
|
||||
|
@ -613,7 +615,9 @@ class ChannelTree {
|
|||
}
|
||||
|
||||
perms[0]["cid"] = channel.channelId;
|
||||
return this.client.serverConnection.sendCommand("channeladdperm", perms, ["continueonerror"]).then(() => new Promise<ChannelEntry>(resolve => { resolve(channel); }));
|
||||
return this.client.serverConnection.send_command("channeladdperm", perms, {
|
||||
flagset: ["continueonerror"]
|
||||
}).then(() => new Promise<ChannelEntry>(resolve => { resolve(channel); }));
|
||||
}
|
||||
|
||||
return new Promise<ChannelEntry>(resolve => { resolve(channel); })
|
||||
|
|
|
@ -151,7 +151,7 @@ class AudioController {
|
|||
|
||||
private playQueue() {
|
||||
let buffer: AudioBuffer;
|
||||
while(buffer = this.audioCache.pop_front()) {
|
||||
while((buffer = this.audioCache.pop_front())) {
|
||||
if(this.playingAudioCache.length >= this._latencyBufferLength * 1.5 + 3) {
|
||||
console.log(tr("Dropping buffer because playing queue grows to much"));
|
||||
continue; /* drop the data (we're behind) */
|
||||
|
|
Loading…
Reference in New Issue