Restructuring of the connection part
This commit is contained in:
parent
fbf820377c
commit
e75bbeabef
30 changed files with 1917 additions and 1519 deletions
|
@ -20,8 +20,5 @@ jobs:
|
||||||
- "ls -lah /tmp/build/"
|
- "ls -lah /tmp/build/"
|
||||||
- "ls -lah /tmp/build/logs/"
|
- "ls -lah /tmp/build/logs/"
|
||||||
- "ls -lah /tmp/build/packages/"
|
- "ls -lah /tmp/build/packages/"
|
||||||
- >
|
- "./scripts/travis_deploy.sh"
|
||||||
mkdir -p /tmp/build/packages/;
|
|
||||||
echo "XXXX" > /tmp/build/packages/xxxxx;
|
|
||||||
./scripts/travis_deploy.sh
|
|
||||||
if: branch = master
|
if: branch = master
|
|
@ -109,7 +109,7 @@ class DownloadFileTransfer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FileManager {
|
class FileManager extends connection.AbstractCommandHandler {
|
||||||
handle: TSClient;
|
handle: TSClient;
|
||||||
icons: IconManager;
|
icons: IconManager;
|
||||||
avatars: AvatarManager;
|
avatars: AvatarManager;
|
||||||
|
@ -119,13 +119,28 @@ class FileManager {
|
||||||
private downloadCounter : number = 0;
|
private downloadCounter : number = 0;
|
||||||
|
|
||||||
constructor(client: TSClient) {
|
constructor(client: TSClient) {
|
||||||
|
super(client.serverConnection);
|
||||||
|
|
||||||
this.handle = client;
|
this.handle = client;
|
||||||
this.icons = new IconManager(this);
|
this.icons = new IconManager(this);
|
||||||
this.avatars = new AvatarManager(this);
|
this.avatars = new AvatarManager(this);
|
||||||
|
|
||||||
this.handle.serverConnection.commandHandler["notifyfilelist"] = this.notifyFileList.bind(this);
|
this.connection.command_handler_boss().register_handler(this);
|
||||||
this.handle.serverConnection.commandHandler["notifyfilelistfinished"] = this.notifyFileListFinished.bind(this);
|
}
|
||||||
this.handle.serverConnection.commandHandler["notifystartdownload"] = this.notifyStartDownload.bind(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;
|
req.callback = accept;
|
||||||
_this.listRequests.push(req);
|
_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);
|
_this.listRequests.remove(req);
|
||||||
if(reason instanceof CommandResult) {
|
if(reason instanceof CommandResult) {
|
||||||
if(reason.id == 0x0501) {
|
if(reason.id == 0x0501) {
|
||||||
|
@ -197,7 +212,7 @@ class FileManager {
|
||||||
this.pendingDownloadTransfers.push(transfer);
|
this.pendingDownloadTransfers.push(transfer);
|
||||||
return new Promise<DownloadFileTransfer>((resolve, reject) => {
|
return new Promise<DownloadFileTransfer>((resolve, reject) => {
|
||||||
transfer["_promiseCallback"] = resolve;
|
transfer["_promiseCallback"] = resolve;
|
||||||
_this.handle.serverConnection.sendCommand("ftinitdownload", {
|
_this.handle.serverConnection.send_command("ftinitdownload", {
|
||||||
"path": path,
|
"path": path,
|
||||||
"name": file,
|
"name": file,
|
||||||
"cid": (channel ? channel.channelId : "0"),
|
"cid": (channel ? channel.channelId : "0"),
|
||||||
|
|
|
@ -354,7 +354,13 @@ class ChatBox {
|
||||||
chat.serverChat().appendError(tr("Could not send chant message (Not connected)"));
|
chat.serverChat().appendError(tr("Could not send chant message (Not connected)"));
|
||||||
return;
|
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");
|
this.serverChat().name = tr("Server chat");
|
||||||
|
|
||||||
|
@ -364,7 +370,10 @@ class ChatBox {
|
||||||
return;
|
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");
|
this.channelChat().name = tr("Channel chat");
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
/// <reference path="voice/AudioController.ts" />
|
/// <reference path="voice/AudioController.ts" />
|
||||||
/// <reference path="proto.ts" />
|
/// <reference path="proto.ts" />
|
||||||
/// <reference path="ui/view.ts" />
|
/// <reference path="ui/view.ts" />
|
||||||
/// <reference path="connection.ts" />
|
|
||||||
/// <reference path="settings.ts" />
|
/// <reference path="settings.ts" />
|
||||||
/// <reference path="ui/frames/SelectedItemInfo.ts" />
|
/// <reference path="ui/frames/SelectedItemInfo.ts" />
|
||||||
/// <reference path="FileManager.ts" />
|
/// <reference path="FileManager.ts" />
|
||||||
|
@ -49,7 +48,7 @@ enum ViewReasonId {
|
||||||
|
|
||||||
class TSClient {
|
class TSClient {
|
||||||
channelTree: ChannelTree;
|
channelTree: ChannelTree;
|
||||||
serverConnection: ServerConnection;
|
serverConnection: connection.ServerConnection;
|
||||||
voiceConnection: VoiceConnection;
|
voiceConnection: VoiceConnection;
|
||||||
fileManager: FileManager;
|
fileManager: FileManager;
|
||||||
selectInfo: InfoBar;
|
selectInfo: InfoBar;
|
||||||
|
@ -65,7 +64,7 @@ class TSClient {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.selectInfo = new InfoBar(this, $("#select_info"));
|
this.selectInfo = new InfoBar(this, $("#select_info"));
|
||||||
this.channelTree = new ChannelTree(this, $("#channelTree"));
|
this.channelTree = new ChannelTree(this, $("#channelTree"));
|
||||||
this.serverConnection = new ServerConnection(this);
|
this.serverConnection = new connection.ServerConnection(this);
|
||||||
this.fileManager = new FileManager(this);
|
this.fileManager = new FileManager(this);
|
||||||
this.permissions = new PermissionManager(this);
|
this.permissions = new PermissionManager(this);
|
||||||
this.groups = new GroupManager(this);
|
this.groups = new GroupManager(this);
|
||||||
|
@ -101,12 +100,15 @@ class TSClient {
|
||||||
|
|
||||||
if(password && !password.hashed) {
|
if(password && !password.hashed) {
|
||||||
helpers.hashPassword(password.password).then(password => {
|
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 => {
|
}).catch(error => {
|
||||||
createErrorModal(tr("Error while hashing password"), tr("Failed to hash server password!<br>") + error).open();
|
createErrorModal(tr("Error while hashing password"), tr("Failed to hash server password!<br>") + error).open();
|
||||||
})
|
})
|
||||||
} else
|
} else {
|
||||||
this.serverConnection.startConnection({host, port}, new HandshakeHandler(profile, name, password ? password.password : undefined));
|
/* 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;
|
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);
|
this.channelTree.registerClient(this._ownEntry);
|
||||||
settings.setServer(this.channelTree.server);
|
settings.setServer(this.channelTree.server);
|
||||||
this.permissions.requestPermissionList();
|
this.permissions.requestPermissionList();
|
||||||
this.serverConnection.sendCommand("channelsubscribeall");
|
this.serverConnection.send_command("channelsubscribeall");
|
||||||
if(this.groups.serverGroups.length == 0)
|
if(this.groups.serverGroups.length == 0)
|
||||||
this.groups.requestGroups();
|
this.groups.requestGroups();
|
||||||
this.controlBar.updateProperties();
|
this.controlBar.updateProperties();
|
||||||
|
@ -142,7 +144,7 @@ class TSClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
get connected() : boolean {
|
get connected() : boolean {
|
||||||
return !!this.serverConnection && this.serverConnection.connected;
|
return this.serverConnection && this.serverConnection.connected();
|
||||||
}
|
}
|
||||||
|
|
||||||
private certAcceptUrl() {
|
private certAcceptUrl() {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
649
shared/js/connection/CommandHandler.ts
Normal file
649
shared/js/connection/CommandHandler.ts
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
311
shared/js/connection/CommandHelper.ts
Normal file
311
shared/js/connection/CommandHelper.ts
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
148
shared/js/connection/ConnectionBase.ts
Normal file
148
shared/js/connection/ConnectionBase.ts
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
108
shared/js/connection/HandshakeHandler.ts
Normal file
108
shared/js/connection/HandshakeHandler.ts
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
377
shared/js/connection/ServerConnection.ts
Normal file
377
shared/js/connection/ServerConnection.ts
Normal file
|
@ -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 */
|
/* load the main app */
|
||||||
await loader.load_scripts([
|
await loader.load_scripts([
|
||||||
//Load general API's
|
//Load general API's
|
||||||
|
@ -539,11 +544,16 @@ const loader_javascript = {
|
||||||
"js/settings.js",
|
"js/settings.js",
|
||||||
"js/bookmarks.js",
|
"js/bookmarks.js",
|
||||||
"js/contextMenu.js",
|
"js/contextMenu.js",
|
||||||
"js/connection.js",
|
|
||||||
"js/FileManager.js",
|
"js/FileManager.js",
|
||||||
"js/client.js",
|
"js/client.js",
|
||||||
"js/chat.js",
|
"js/chat.js",
|
||||||
|
|
||||||
|
//Connection
|
||||||
|
"js/connection/CommandHandler.js",
|
||||||
|
"js/connection/CommandHelper.js",
|
||||||
|
"js/connection/HandshakeHandler.js",
|
||||||
|
"js/connection/ServerConnection.js",
|
||||||
|
|
||||||
"js/PPTListener.js",
|
"js/PPTListener.js",
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ class Group {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GroupManager {
|
class GroupManager extends connection.AbstractCommandHandler {
|
||||||
readonly handle: TSClient;
|
readonly handle: TSClient;
|
||||||
|
|
||||||
serverGroups: Group[] = [];
|
serverGroups: Group[] = [];
|
||||||
|
@ -66,18 +66,29 @@ class GroupManager {
|
||||||
|
|
||||||
private requests_group_permissions: GroupPermissionRequest[] = [];
|
private requests_group_permissions: GroupPermissionRequest[] = [];
|
||||||
constructor(client: TSClient) {
|
constructor(client: TSClient) {
|
||||||
|
super(client.serverConnection);
|
||||||
|
|
||||||
|
client.serverConnection.command_handler_boss().register_handler(this);
|
||||||
this.handle = client;
|
this.handle = client;
|
||||||
|
}
|
||||||
|
|
||||||
this.handle.serverConnection.commandHandler["notifyservergrouplist"] = this.onServerGroupList.bind(this);
|
handle_command(command: connection.ServerCommand): boolean {
|
||||||
this.handle.serverConnection.commandHandler["notifychannelgrouplist"] = this.onServerGroupList.bind(this);
|
switch (command.command) {
|
||||||
|
case "notifyservergrouplist":
|
||||||
this.handle.serverConnection.commandHandler["notifyservergrouppermlist"] = this.onPermissionList.bind(this);
|
case "notifychannelgrouplist":
|
||||||
this.handle.serverConnection.commandHandler["notifychannelgrouppermlist"] = this.onPermissionList.bind(this);
|
this.handle_grouplist(command.arguments);
|
||||||
|
return true;
|
||||||
|
case "notifyservergrouppermlist":
|
||||||
|
case "notifychannelgrouppermlist":
|
||||||
|
this.handle_group_permission_list(command.arguments);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
requestGroups(){
|
requestGroups(){
|
||||||
this.handle.serverConnection.sendCommand("servergrouplist");
|
this.handle.serverConnection.send_command("servergrouplist");
|
||||||
this.handle.serverConnection.sendCommand("channelgrouplist");
|
this.handle.serverConnection.send_command("channelgrouplist");
|
||||||
}
|
}
|
||||||
|
|
||||||
static sorter() : (a: Group, b: Group) => number {
|
static sorter() : (a: Group, b: Group) => number {
|
||||||
|
@ -107,7 +118,7 @@ class GroupManager {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
private onServerGroupList(json) {
|
private handle_grouplist(json) {
|
||||||
let target : GroupTarget;
|
let target : GroupTarget;
|
||||||
if(json[0]["sgid"]) target = GroupTarget.SERVER;
|
if(json[0]["sgid"]) target = GroupTarget.SERVER;
|
||||||
else if(json[0]["cgid"]) target = GroupTarget.CHANNEL;
|
else if(json[0]["cgid"]) target = GroupTarget.CHANNEL;
|
||||||
|
@ -167,7 +178,7 @@ class GroupManager {
|
||||||
req.promise = new LaterPromise<PermissionValue[]>();
|
req.promise = new LaterPromise<PermissionValue[]>();
|
||||||
this.requests_group_permissions.push(req);
|
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,
|
cgid: group.id,
|
||||||
sgid: group.id
|
sgid: group.id
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
@ -179,7 +190,7 @@ class GroupManager {
|
||||||
return req.promise;
|
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"]));
|
let group = json[0]["sgid"] ? this.serverGroup(parseInt(json[0]["sgid"])) : this.channelGroup(parseInt(json[0]["cgid"]));
|
||||||
if(!group) {
|
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"]);
|
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[]>;
|
promise: LaterPromise<PermissionValue[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PermissionManager {
|
class PermissionManager extends connection.AbstractCommandHandler {
|
||||||
readonly handle: TSClient;
|
readonly handle: TSClient;
|
||||||
|
|
||||||
permissionList: PermissionInfo[] = [];
|
permissionList: PermissionInfo[] = [];
|
||||||
|
@ -505,14 +505,34 @@ class PermissionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(client: TSClient) {
|
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 = client;
|
||||||
|
}
|
||||||
|
|
||||||
this.handle.serverConnection.commandHandler["notifyclientneededpermissions"] = this.onNeededPermissions.bind(this);
|
handle_command(command: connection.ServerCommand): boolean {
|
||||||
this.handle.serverConnection.commandHandler["notifypermissionlist"] = this.onPermissionList.bind(this);
|
switch (command.command) {
|
||||||
|
case "notifyclientneededpermissions":
|
||||||
this.handle.serverConnection.commandHandler["notifychannelpermlist"] = this.onChannelPermList.bind(this);
|
this.onNeededPermissions(command.arguments);
|
||||||
this.handle.serverConnection.commandHandler["notifyclientpermlist"] = this.onClientPermList.bind(this);
|
return true;
|
||||||
this.handle.serverConnection.commandHandler["notifyplaylistpermlist"] = this.onPlaylistPermList.bind(this);
|
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 {
|
initialized() : boolean {
|
||||||
|
@ -520,7 +540,7 @@ class PermissionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public requestPermissionList() {
|
public requestPermissionList() {
|
||||||
this.handle.serverConnection.sendCommand("permissionlist");
|
this.handle.serverConnection.send_command("permissionlist");
|
||||||
}
|
}
|
||||||
|
|
||||||
private onPermissionList(json) {
|
private onPermissionList(json) {
|
||||||
|
@ -648,7 +668,7 @@ class PermissionManager {
|
||||||
request = new ChannelPermissionRequest();
|
request = new ChannelPermissionRequest();
|
||||||
request.requested = Date.now();
|
request.requested = Date.now();
|
||||||
request.channel_id = channelId;
|
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);
|
this.requests_channel_permissions.push(request);
|
||||||
}
|
}
|
||||||
request.callback_error.push(reject);
|
request.callback_error.push(reject);
|
||||||
|
@ -676,7 +696,7 @@ class PermissionManager {
|
||||||
request.client_id = client_id;
|
request.client_id = client_id;
|
||||||
request.promise = new LaterPromise<PermissionValue[]>();
|
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)
|
if(error instanceof CommandResult && error.id == ErrorID.EMPTY_RESULT)
|
||||||
request.promise.resolved([]);
|
request.promise.resolved([]);
|
||||||
else
|
else
|
||||||
|
@ -697,7 +717,7 @@ class PermissionManager {
|
||||||
request.channel_id = channel_id;
|
request.channel_id = channel_id;
|
||||||
request.promise = new LaterPromise<PermissionValue[]>();
|
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)
|
if(error instanceof CommandResult && error.id == ErrorID.EMPTY_RESULT)
|
||||||
request.promise.resolved([]);
|
request.promise.resolved([]);
|
||||||
else
|
else
|
||||||
|
@ -730,7 +750,7 @@ class PermissionManager {
|
||||||
request.playlist_id = playlist_id;
|
request.playlist_id = playlist_id;
|
||||||
request.promise = new LaterPromise<PermissionValue[]>();
|
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)
|
if(error instanceof CommandResult && error.id == ErrorID.EMPTY_RESULT)
|
||||||
request.promise.resolved([]);
|
request.promise.resolved([]);
|
||||||
else
|
else
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace profiles {
|
||||||
this.identities[identities.IdentitifyType[type].toLowerCase()] = identity;
|
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();
|
const identity = this.selected_identity();
|
||||||
if(!identity)
|
if(!identity)
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace profiles.identities {
|
||||||
encode?() : string;
|
encode?() : string;
|
||||||
decode(data: string) : Promise<void>;
|
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> {
|
export async function decode_identity(type: IdentitifyType, data: string) : Promise<Identity> {
|
||||||
|
@ -61,12 +61,33 @@ namespace profiles.identities {
|
||||||
return identity;
|
return identity;
|
||||||
}
|
}
|
||||||
|
|
||||||
export abstract class AbstractHandshakeIdentityHandler implements HandshakeIdentityHandler {
|
export class HandshakeCommandHandler<T extends AbstractHandshakeIdentityHandler> extends connection.AbstractCommandHandler {
|
||||||
connection: ServerConnection;
|
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 callbacks: ((success: boolean, message?: string) => any)[] = [];
|
||||||
|
|
||||||
protected constructor(connection: ServerConnection) {
|
protected constructor(connection: connection.AbstractServerConnection) {
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,16 +3,19 @@
|
||||||
namespace profiles.identities {
|
namespace profiles.identities {
|
||||||
class NameHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
class NameHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
||||||
readonly identity: NameIdentity;
|
readonly identity: NameIdentity;
|
||||||
|
handler: HandshakeCommandHandler<NameHandshakeHandler>;
|
||||||
|
|
||||||
constructor(connection: ServerConnection, identity: profiles.identities.NameIdentity) {
|
constructor(connection: connection.AbstractServerConnection, identity: profiles.identities.NameIdentity) {
|
||||||
super(connection);
|
super(connection);
|
||||||
this.identity = identity;
|
this.identity = identity;
|
||||||
|
|
||||||
|
this.handler = new HandshakeCommandHandler(connection, this);
|
||||||
|
this.handler["handshakeidentityproof"] = () => this.trigger_fail("server requested unexpected proof");
|
||||||
}
|
}
|
||||||
|
|
||||||
start_handshake() {
|
start_handshake() {
|
||||||
this.connection.commandHandler["handshakeidentityproof"] = () => this.trigger_fail("server requested unexpected proof");
|
this.connection.command_handler_boss().register_handler(this.handler);
|
||||||
|
this.connection.send_command("handshakebegin", {
|
||||||
this.connection.sendCommand("handshakebegin", {
|
|
||||||
intention: 0,
|
intention: 0,
|
||||||
authentication_method: this.identity.type(),
|
authentication_method: this.identity.type(),
|
||||||
client_nickname: this.identity.name()
|
client_nickname: this.identity.name()
|
||||||
|
@ -24,6 +27,16 @@ namespace profiles.identities {
|
||||||
this.trigger_fail("failed to execute begin (" + error + ")");
|
this.trigger_fail("failed to execute begin (" + error + ")");
|
||||||
}).then(() => this.trigger_success());
|
}).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 {
|
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);
|
return new NameHandshakeHandler(connection, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,18 @@
|
||||||
namespace profiles.identities {
|
namespace profiles.identities {
|
||||||
class TeaForumHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
class TeaForumHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
||||||
readonly identity: TeaForumIdentity;
|
readonly identity: TeaForumIdentity;
|
||||||
|
handler: HandshakeCommandHandler<TeaForumHandshakeHandler>;
|
||||||
|
|
||||||
constructor(connection: ServerConnection, identity: profiles.identities.TeaForumIdentity) {
|
constructor(connection: connection.AbstractServerConnection, identity: profiles.identities.TeaForumIdentity) {
|
||||||
super(connection);
|
super(connection);
|
||||||
this.identity = identity;
|
this.identity = identity;
|
||||||
|
this.handler = new HandshakeCommandHandler(connection, this);
|
||||||
|
this.handler["handshakeidentityproof"] = this.handle_proof.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
start_handshake() {
|
start_handshake() {
|
||||||
this.connection.commandHandler["handshakeidentityproof"] = this.handle_proof.bind(this);
|
this.connection.command_handler_boss().register_handler(this.handler);
|
||||||
|
this.connection.send_command("handshakebegin", {
|
||||||
this.connection.sendCommand("handshakebegin", {
|
|
||||||
intention: 0,
|
intention: 0,
|
||||||
authentication_method: this.identity.type(),
|
authentication_method: this.identity.type(),
|
||||||
data: this.identity.data_json()
|
data: this.identity.data_json()
|
||||||
|
@ -27,7 +29,7 @@ namespace profiles.identities {
|
||||||
|
|
||||||
|
|
||||||
private handle_proof(json) {
|
private handle_proof(json) {
|
||||||
this.connection.sendCommand("handshakeindentityproof", {
|
this.connection.send_command("handshakeindentityproof", {
|
||||||
proof: this.identity.data_sign()
|
proof: this.identity.data_sign()
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error(tr("Failed to proof the identity. Error: %o"), 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 + ")");
|
this.trigger_fail("failed to execute proof (" + error + ")");
|
||||||
}).then(() => this.trigger_success());
|
}).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 {
|
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);
|
return new TeaForumHandshakeHandler(connection, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -198,16 +198,18 @@ namespace profiles.identities {
|
||||||
|
|
||||||
class TeaSpeakHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
class TeaSpeakHandshakeHandler extends AbstractHandshakeIdentityHandler {
|
||||||
identity: TeaSpeakIdentity;
|
identity: TeaSpeakIdentity;
|
||||||
|
handler: HandshakeCommandHandler<TeaSpeakHandshakeHandler>;
|
||||||
|
|
||||||
constructor(connection: ServerConnection, identity: TeaSpeakIdentity) {
|
constructor(connection: connection.AbstractServerConnection, identity: TeaSpeakIdentity) {
|
||||||
super(connection);
|
super(connection);
|
||||||
this.identity = identity;
|
this.identity = identity;
|
||||||
|
this.handler = new HandshakeCommandHandler(connection, this);
|
||||||
|
this.handler["handshakeidentityproof"] = this.handle_proof.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
start_handshake() {
|
start_handshake() {
|
||||||
this.connection.commandHandler["handshakeidentityproof"] = this.handle_proof.bind(this);
|
this.connection.command_handler_boss().register_handler(this.handler);
|
||||||
|
this.connection.send_command("handshakebegin", {
|
||||||
this.connection.sendCommand("handshakebegin", {
|
|
||||||
intention: 0,
|
intention: 0,
|
||||||
authentication_method: this.identity.type(),
|
authentication_method: this.identity.type(),
|
||||||
publicKey: this.identity.public_key
|
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.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);
|
console.error(tr("Failed to proof the identity. Error: %o"), error);
|
||||||
|
|
||||||
if(error instanceof CommandResult)
|
if(error instanceof CommandResult)
|
||||||
|
@ -238,6 +240,16 @@ namespace profiles.identities {
|
||||||
this.trigger_fail("failed to sign message");
|
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 {
|
class IdentityPOWWorker {
|
||||||
|
@ -831,7 +843,7 @@ namespace profiles.identities {
|
||||||
return base64ArrayBuffer(buffer.subarray(0, index));
|
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);
|
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) return new Promise<string>(resolve => resolve(this._cached_channel_description));
|
||||||
if(this._cached_channel_description_promise) return this._cached_channel_description_promise;
|
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);
|
this._cached_channel_description_promise_reject(error);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -440,7 +440,7 @@ class ChannelEntry {
|
||||||
Modals.createChannelModal(this, undefined, this.channelTree.client.permissions, (changes?, permissions?) => {
|
Modals.createChannelModal(this, undefined, this.channelTree.client.permissions, (changes?, permissions?) => {
|
||||||
if(changes) {
|
if(changes) {
|
||||||
changes["cid"] = this.channelId;
|
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);
|
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;
|
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);
|
sound.play(Sound.CHANNEL_EDITED_SELF);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -469,7 +471,7 @@ class ChannelEntry {
|
||||||
name: tr("Delete channel"),
|
name: tr("Delete channel"),
|
||||||
invalidPermission: !flagDelete,
|
invalidPermission: !flagDelete,
|
||||||
callback: () => {
|
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);
|
sound.play(Sound.CHANNEL_DELETED);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -480,7 +482,7 @@ class ChannelEntry {
|
||||||
icon: "client-addon-collection",
|
icon: "client-addon-collection",
|
||||||
name: tr("Create music bot"),
|
name: tr("Create music bot"),
|
||||||
callback: () => {
|
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();
|
createInfoModal(tr("Bot successfully created"), tr("Bot has been successfully created.")).open();
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
if(error instanceof CommandResult) {
|
if(error instanceof CommandResult) {
|
||||||
|
@ -692,7 +694,7 @@ class ChannelEntry {
|
||||||
});
|
});
|
||||||
}).open();
|
}).open();
|
||||||
} else if(this.channelTree.client.getClient().currentChannel() != this)
|
} 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);
|
sound.play(Sound.CHANNEL_JOINED);
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
if(error instanceof CommandResult) {
|
if(error instanceof CommandResult) {
|
||||||
|
|
|
@ -146,7 +146,7 @@ class ClientEntry {
|
||||||
|
|
||||||
const source = client._channel;
|
const source = client._channel;
|
||||||
const self = this.channelTree.client.getClient();
|
const self = this.channelTree.client.getClient();
|
||||||
this.channelTree.client.serverConnection.sendCommand("clientmove", {
|
this.channelTree.client.serverConnection.send_command("clientmove", {
|
||||||
clid: client.clientId(),
|
clid: client.clientId(),
|
||||||
cid: target.getChannelId()
|
cid: target.getChannelId()
|
||||||
}).then(event => {
|
}).then(event => {
|
||||||
|
@ -179,7 +179,7 @@ class ClientEntry {
|
||||||
entry.name = group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]";
|
entry.name = group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]";
|
||||||
if(this.groupAssigned(group)) {
|
if(this.groupAssigned(group)) {
|
||||||
entry.callback = () => {
|
entry.callback = () => {
|
||||||
this.channelTree.client.serverConnection.sendCommand("servergroupdelclient", {
|
this.channelTree.client.serverConnection.send_command("servergroupdelclient", {
|
||||||
sgid: group.id,
|
sgid: group.id,
|
||||||
cldbid: this.properties.client_database_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);
|
entry.disabled = !this.channelTree.client.permissions.neededPermission(PermissionType.I_GROUP_MEMBER_ADD_POWER).granted(group.requiredMemberRemovePower);
|
||||||
} else {
|
} else {
|
||||||
entry.callback = () => {
|
entry.callback = () => {
|
||||||
this.channelTree.client.serverConnection.sendCommand("servergroupaddclient", {
|
this.channelTree.client.serverConnection.send_command("servergroupaddclient", {
|
||||||
sgid: group.id,
|
sgid: group.id,
|
||||||
cldbid: this.properties.client_database_id
|
cldbid: this.properties.client_database_id
|
||||||
});
|
});
|
||||||
|
@ -211,7 +211,7 @@ class ClientEntry {
|
||||||
}
|
}
|
||||||
entry.name = group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]";
|
entry.name = group.name + " [" + (group.properties.savedb ? "perm" : "tmp") + "]";
|
||||||
entry.callback = () => {
|
entry.callback = () => {
|
||||||
this.channelTree.client.serverConnection.sendCommand("setclientchannelgroup", {
|
this.channelTree.client.serverConnection.send_command("setclientchannelgroup", {
|
||||||
cldbid: this.properties.client_database_id,
|
cldbid: this.properties.client_database_id,
|
||||||
cgid: group.id,
|
cgid: group.id,
|
||||||
cid: this.currentChannel().channelId
|
cid: this.currentChannel().channelId
|
||||||
|
@ -234,12 +234,12 @@ class ClientEntry {
|
||||||
callback: () => {
|
callback: () => {
|
||||||
Modals.createServerGroupAssignmentModal(this, (group, flag) => {
|
Modals.createServerGroupAssignmentModal(this, (group, flag) => {
|
||||||
if(flag) {
|
if(flag) {
|
||||||
return this.channelTree.client.serverConnection.sendCommand("servergroupaddclient", {
|
return this.channelTree.client.serverConnection.send_command("servergroupaddclient", {
|
||||||
sgid: group.id,
|
sgid: group.id,
|
||||||
cldbid: this.properties.client_database_id
|
cldbid: this.properties.client_database_id
|
||||||
}).then(result => true);
|
}).then(result => true);
|
||||||
} else
|
} else
|
||||||
return this.channelTree.client.serverConnection.sendCommand("servergroupdelclient", {
|
return this.channelTree.client.serverConnection.send_command("servergroupdelclient", {
|
||||||
sgid: group.id,
|
sgid: group.id,
|
||||||
cldbid: this.properties.client_database_id
|
cldbid: this.properties.client_database_id
|
||||||
}).then(result => true);
|
}).then(result => true);
|
||||||
|
@ -286,7 +286,7 @@ class ClientEntry {
|
||||||
if(typeof(result) === "string") {
|
if(typeof(result) === "string") {
|
||||||
//TODO tr
|
//TODO tr
|
||||||
console.log("Poking client " + _this.clientNickName() + " with message " + result);
|
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(),
|
clid: _this.clientId(),
|
||||||
msg: result
|
msg: result
|
||||||
});
|
});
|
||||||
|
@ -303,7 +303,7 @@ class ClientEntry {
|
||||||
if(typeof(result) === "string") {
|
if(typeof(result) === "string") {
|
||||||
//TODO tr
|
//TODO tr
|
||||||
console.log("Changing " + _this.clientNickName() + "'s description to " + result);
|
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(),
|
clid: _this.clientId(),
|
||||||
client_description: result
|
client_description: result
|
||||||
});
|
});
|
||||||
|
@ -319,7 +319,7 @@ class ClientEntry {
|
||||||
icon: "client-move_client_to_own_channel",
|
icon: "client-move_client_to_own_channel",
|
||||||
name: tr("Move client to your channel"),
|
name: tr("Move client to your channel"),
|
||||||
callback: () => {
|
callback: () => {
|
||||||
this.channelTree.client.serverConnection.sendCommand("clientmove", {
|
this.channelTree.client.serverConnection.send_command("clientmove", {
|
||||||
clid: this.clientId(),
|
clid: this.clientId(),
|
||||||
cid: this.channelTree.client.getClient().currentChannel().getChannelId()
|
cid: this.channelTree.client.getClient().currentChannel().getChannelId()
|
||||||
});
|
});
|
||||||
|
@ -333,7 +333,7 @@ class ClientEntry {
|
||||||
if(result) {
|
if(result) {
|
||||||
//TODO tr
|
//TODO tr
|
||||||
console.log("Kicking client " + _this.clientNickName() + " from channel with reason " + result);
|
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(),
|
clid: _this.clientId(),
|
||||||
reasonid: ViewReasonId.VREASON_CHANNEL_KICK,
|
reasonid: ViewReasonId.VREASON_CHANNEL_KICK,
|
||||||
reasonmsg: result
|
reasonmsg: result
|
||||||
|
@ -351,7 +351,7 @@ class ClientEntry {
|
||||||
if(result) {
|
if(result) {
|
||||||
//TODO tr
|
//TODO tr
|
||||||
console.log("Kicking client " + _this.clientNickName() + " from server with reason " + result);
|
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(),
|
clid: _this.clientId(),
|
||||||
reasonid: ViewReasonId.VREASON_SERVER_KICK,
|
reasonid: ViewReasonId.VREASON_SERVER_KICK,
|
||||||
reasonmsg: result
|
reasonmsg: result
|
||||||
|
@ -367,11 +367,13 @@ class ClientEntry {
|
||||||
invalidPermission: !this.channelTree.client.permissions.neededPermission(PermissionType.I_CLIENT_BAN_MAX_BANTIME).granted(1),
|
invalidPermission: !this.channelTree.client.permissions.neededPermission(PermissionType.I_CLIENT_BAN_MAX_BANTIME).granted(1),
|
||||||
callback: () => {
|
callback: () => {
|
||||||
Modals.spawnBanClient(this.properties.client_nickname, (data) => {
|
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,
|
uid: this.properties.client_unique_identifier,
|
||||||
banreason: data.reason,
|
banreason: data.reason,
|
||||||
time: data.length
|
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);
|
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),
|
invalidPermission: true, //!this.channelTree.client.permissions.neededPermission(PermissionType.I_CLIENT_BAN_MAX_BANTIME).granted(1),
|
||||||
callback: () => {
|
callback: () => {
|
||||||
Modals.spawnBanClient(this.properties.client_nickname, (duration, reason) => {
|
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,
|
uid: this.properties.client_unique_identifier,
|
||||||
banreason: reason,
|
banreason: reason,
|
||||||
time: duration
|
time: duration
|
||||||
|
@ -653,7 +655,7 @@ class ClientEntry {
|
||||||
updateClientVariables(){
|
updateClientVariables(){
|
||||||
if(this.lastVariableUpdate == 0 || new Date().getTime() - 10 * 60 * 1000 > this.lastVariableUpdate){ //Cache these only 10 min
|
if(this.lastVariableUpdate == 0 || new Date().getTime() - 10 * 60 * 1000 > this.lastVariableUpdate){ //Cache these only 10 min
|
||||||
this.lastVariableUpdate = new Date().getTime();
|
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;
|
const _this = this;
|
||||||
c.onMessageSend = function (text: string) {
|
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 {
|
c.onClose = function () : boolean {
|
||||||
//TODO check online?
|
//TODO check online?
|
||||||
_this.channelTree.client.serverConnection.sendCommand("clientchatclosed", {"clid": _this.clientId()});
|
_this.channelTree.client.serverConnection.send_command("clientchatclosed", {"clid": _this.clientId()});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -797,7 +799,7 @@ class LocalClientEntry extends ClientEntry {
|
||||||
createInputModal(tr("Change own description"), tr("New description:<br>"), text => true, result => {
|
createInputModal(tr("Change own description"), tr("New description:<br>"), text => true, result => {
|
||||||
if(result) {
|
if(result) {
|
||||||
console.log(tr("Changing own description to %s"), 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(),
|
clid: _self.clientId(),
|
||||||
client_description: result
|
client_description: result
|
||||||
});
|
});
|
||||||
|
@ -853,7 +855,7 @@ class LocalClientEntry extends ClientEntry {
|
||||||
if(_self.clientNickName() == text) return;
|
if(_self.clientNickName() == text) return;
|
||||||
|
|
||||||
elm.text(_self.clientNickName());
|
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"));
|
chat.serverChat().appendMessage(tr("Nickname successfully changed"));
|
||||||
}).catch((e: CommandResult) => {
|
}).catch((e: CommandResult) => {
|
||||||
chat.serverChat().appendError(tr("Could not change nickname ({})"), e.extra_message);
|
chat.serverChat().appendError(tr("Could not change nickname ({})"), e.extra_message);
|
||||||
|
@ -915,7 +917,7 @@ class MusicClientEntry extends ClientEntry {
|
||||||
callback: () => {
|
callback: () => {
|
||||||
createInputModal(tr("Change music bots nickname"), tr("New nickname:<br>"), text => text.length >= 3 && text.length <= 31, result => {
|
createInputModal(tr("Change music bots nickname"), tr("New nickname:<br>"), text => text.length >= 3 && text.length <= 31, result => {
|
||||||
if(result) {
|
if(result) {
|
||||||
this.channelTree.client.serverConnection.sendCommand("clientedit", {
|
this.channelTree.client.serverConnection.send_command("clientedit", {
|
||||||
clid: this.clientId(),
|
clid: this.clientId(),
|
||||||
client_nickname: result
|
client_nickname: result
|
||||||
});
|
});
|
||||||
|
@ -931,7 +933,7 @@ class MusicClientEntry extends ClientEntry {
|
||||||
callback: () => {
|
callback: () => {
|
||||||
createInputModal(tr("Change music bots description"), tr("New description:<br>"), text => true, result => {
|
createInputModal(tr("Change music bots description"), tr("New description:<br>"), text => true, result => {
|
||||||
if(typeof(result) === 'string') {
|
if(typeof(result) === 'string') {
|
||||||
this.channelTree.client.serverConnection.sendCommand("clientedit", {
|
this.channelTree.client.serverConnection.send_command("clientedit", {
|
||||||
clid: this.clientId(),
|
clid: this.clientId(),
|
||||||
client_description: result
|
client_description: result
|
||||||
});
|
});
|
||||||
|
@ -955,7 +957,7 @@ class MusicClientEntry extends ClientEntry {
|
||||||
icon: "client-edit",
|
icon: "client-edit",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
callback: () => {
|
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) {
|
for(const entry of lists) {
|
||||||
if(entry.playlist_id == this.properties.client_playlist_id) {
|
if(entry.playlist_id == this.properties.client_playlist_id) {
|
||||||
Modals.spawnPlaylistEdit(this.channelTree.client, entry);
|
Modals.spawnPlaylistEdit(this.channelTree.client, entry);
|
||||||
|
@ -976,7 +978,7 @@ class MusicClientEntry extends ClientEntry {
|
||||||
callback: () => {
|
callback: () => {
|
||||||
createInputModal(tr("Please enter the URL"), tr("URL:"), text => true, result => {
|
createInputModal(tr("Please enter the URL"), tr("URL:"), text => true, result => {
|
||||||
if(result) {
|
if(result) {
|
||||||
this.channelTree.client.serverConnection.sendCommand("musicbotqueueadd", {
|
this.channelTree.client.serverConnection.send_command("musicbotqueueadd", {
|
||||||
bot_id: this.properties.client_database_id,
|
bot_id: this.properties.client_database_id,
|
||||||
type: "yt", //Its a hint not a force!
|
type: "yt", //Its a hint not a force!
|
||||||
url: result
|
url: result
|
||||||
|
@ -999,7 +1001,7 @@ class MusicClientEntry extends ClientEntry {
|
||||||
icon: "client-move_client_to_own_channel",
|
icon: "client-move_client_to_own_channel",
|
||||||
name: tr("Move client to your channel"),
|
name: tr("Move client to your channel"),
|
||||||
callback: () => {
|
callback: () => {
|
||||||
this.channelTree.client.serverConnection.sendCommand("clientmove", {
|
this.channelTree.client.serverConnection.send_command("clientmove", {
|
||||||
clid: this.clientId(),
|
clid: this.clientId(),
|
||||||
cid: this.channelTree.client.getClient().currentChannel().getChannelId()
|
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 => {
|
createInputModal(tr("Kick client from channel"), tr("Kick reason:<br>"), text => true, result => {
|
||||||
if(result) {
|
if(result) {
|
||||||
console.log(tr("Kicking client %o from channel with reason %o"), this.clientNickName(), 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(),
|
clid: this.clientId(),
|
||||||
reasonid: ViewReasonId.VREASON_CHANNEL_KICK,
|
reasonid: ViewReasonId.VREASON_CHANNEL_KICK,
|
||||||
reasonmsg: result
|
reasonmsg: result
|
||||||
|
@ -1045,7 +1047,7 @@ class MusicClientEntry extends ClientEntry {
|
||||||
max_volume = 100;
|
max_volume = 100;
|
||||||
|
|
||||||
Modals.spawnChangeRemoteVolume(this.properties.player_volume, max_volume / 100, value => {
|
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(),
|
clid: this.clientId(),
|
||||||
player_volume: value,
|
player_volume: value,
|
||||||
}).then(() => {
|
}).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)));
|
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 => {
|
Modals.spawnYesNo(tr("Are you sure?"), $.spawn("div").append(tag), result => {
|
||||||
if(result) {
|
if(result) {
|
||||||
this.channelTree.client.serverConnection.sendCommand("musicbotdelete", {
|
this.channelTree.client.serverConnection.send_command("musicbotdelete", {
|
||||||
bot_id: this.properties.client_database_id
|
bot_id: this.properties.client_database_id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1105,7 +1107,7 @@ class MusicClientEntry extends ClientEntry {
|
||||||
this._info_promise_resolve = resolve;
|
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;
|
return this._info_promise;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -137,7 +137,7 @@ class ControlBar {
|
||||||
|
|
||||||
|
|
||||||
if(this.handle.serverConnection.connected)
|
if(this.handle.serverConnection.connected)
|
||||||
this.handle.serverConnection.sendCommand("clientupdate", {
|
this.handle.serverConnection.send_command("clientupdate", {
|
||||||
client_input_muted: this._muteInput
|
client_input_muted: this._muteInput
|
||||||
});
|
});
|
||||||
settings.changeGlobal("mute_input", this._muteInput);
|
settings.changeGlobal("mute_input", this._muteInput);
|
||||||
|
@ -162,7 +162,7 @@ class ControlBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.handle.serverConnection.connected)
|
if(this.handle.serverConnection.connected)
|
||||||
this.handle.serverConnection.sendCommand("clientupdate", {
|
this.handle.serverConnection.send_command("clientupdate", {
|
||||||
client_output_muted: this._muteOutput
|
client_output_muted: this._muteOutput
|
||||||
});
|
});
|
||||||
settings.changeGlobal("mute_output", this._muteOutput);
|
settings.changeGlobal("mute_output", this._muteOutput);
|
||||||
|
@ -187,7 +187,7 @@ class ControlBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.handle.serverConnection.connected)
|
if(this.handle.serverConnection.connected)
|
||||||
this.handle.serverConnection.sendCommand("clientupdate", {
|
this.handle.serverConnection.send_command("clientupdate", {
|
||||||
client_away: this._away,
|
client_away: this._away,
|
||||||
client_away_message: this._awayMessage
|
client_away_message: this._awayMessage
|
||||||
});
|
});
|
||||||
|
@ -201,7 +201,7 @@ class ControlBar {
|
||||||
|
|
||||||
updateProperties() {
|
updateProperties() {
|
||||||
if(this.handle.serverConnection.connected)
|
if(this.handle.serverConnection.connected)
|
||||||
this.handle.serverConnection.sendCommand("clientupdate", {
|
this.handle.serverConnection.send_command("clientupdate", {
|
||||||
client_input_muted: this._muteInput,
|
client_input_muted: this._muteInput,
|
||||||
client_output_muted: this._muteOutput,
|
client_output_muted: this._muteOutput,
|
||||||
client_away: this._away,
|
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_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.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_input_hardware: this.codec_supported && this.support_record,
|
||||||
client_output_hardware: this.codec_supported && this.support_playback
|
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 => {
|
createInputModal(tr("Use token"), tr("Please enter your token/priviledge key"), message => message.length > 0, result => {
|
||||||
if(!result) return;
|
if(!result) return;
|
||||||
if(this.handle.serverConnection.connected)
|
if(this.handle.serverConnection.connected)
|
||||||
this.handle.serverConnection.sendCommand("tokenuse", {
|
this.handle.serverConnection.send_command("tokenuse", {
|
||||||
token: result
|
token: result
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
createInfoModal(tr("Use token"), tr("Toke successfully used!")).open();
|
createInfoModal(tr("Use token"), tr("Toke successfully used!")).open();
|
||||||
|
|
|
@ -412,7 +412,7 @@ enum MusicPlayerState {
|
||||||
}
|
}
|
||||||
|
|
||||||
class MusicInfoManager extends ClientInfoManager {
|
class MusicInfoManager extends ClientInfoManager {
|
||||||
notify_status: (json) => any;
|
single_handler: connection.SingleCommandHandler;
|
||||||
|
|
||||||
createFrame<_>(handle: InfoBar<_>, channel: MusicClientEntry, html_tag: JQuery<HTMLElement>) {
|
createFrame<_>(handle: InfoBar<_>, channel: MusicClientEntry, html_tag: JQuery<HTMLElement>) {
|
||||||
super.createFrame(handle, channel, html_tag);
|
super.createFrame(handle, channel, html_tag);
|
||||||
|
@ -420,9 +420,9 @@ class MusicInfoManager extends ClientInfoManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFrame(bot: MusicClientEntry, html_tag: JQuery<HTMLElement>) {
|
updateFrame(bot: MusicClientEntry, html_tag: JQuery<HTMLElement>) {
|
||||||
if(this.notify_status) {
|
if(this.single_handler) {
|
||||||
this.handle.handle.serverConnection.commandHandler.unset_handler("notifymusicstatusupdate", this.notify_status);
|
this.handle.handle.serverConnection.command_handler_boss().remove_single_handler(this.single_handler);
|
||||||
this.notify_status = undefined;
|
this.single_handler = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.resetIntervals();
|
this.resetIntervals();
|
||||||
|
@ -459,7 +459,7 @@ class MusicInfoManager extends ClientInfoManager {
|
||||||
let button_stop = frame.find('.button_stop');
|
let button_stop = frame.find('.button_stop');
|
||||||
button_play.click(handler => {
|
button_play.click(handler => {
|
||||||
if(!button_play.hasClass("active")) {
|
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,
|
bot_id: bot.properties.client_database_id,
|
||||||
action: 1
|
action: 1
|
||||||
}).then(updated => this.triggerUpdate()).catch(error => {
|
}).then(updated => this.triggerUpdate()).catch(error => {
|
||||||
|
@ -472,7 +472,7 @@ class MusicInfoManager extends ClientInfoManager {
|
||||||
});
|
});
|
||||||
button_pause.click(handler => {
|
button_pause.click(handler => {
|
||||||
if(!button_pause.hasClass("active")) {
|
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,
|
bot_id: bot.properties.client_database_id,
|
||||||
action: 2
|
action: 2
|
||||||
}).then(updated => this.triggerUpdate()).catch(error => {
|
}).then(updated => this.triggerUpdate()).catch(error => {
|
||||||
|
@ -484,7 +484,7 @@ class MusicInfoManager extends ClientInfoManager {
|
||||||
button_pause.hide();
|
button_pause.hide();
|
||||||
});
|
});
|
||||||
button_stop.click(handler => {
|
button_stop.click(handler => {
|
||||||
this.handle.handle.serverConnection.sendCommand("musicbotplayeraction", {
|
this.handle.handle.serverConnection.send_command("musicbotplayeraction", {
|
||||||
bot_id: bot.properties.client_database_id,
|
bot_id: bot.properties.client_database_id,
|
||||||
action: 0
|
action: 0
|
||||||
}).then(updated => this.triggerUpdate()).catch(error => {
|
}).then(updated => this.triggerUpdate()).catch(error => {
|
||||||
|
@ -507,7 +507,7 @@ class MusicInfoManager extends ClientInfoManager {
|
||||||
|
|
||||||
{ /* Button functions */
|
{ /* Button functions */
|
||||||
_frame.find(".btn-forward").click(() => {
|
_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,
|
bot_id: bot.properties.client_database_id,
|
||||||
action: 3
|
action: 3
|
||||||
}).then(updated => this.triggerUpdate()).catch(error => {
|
}).then(updated => this.triggerUpdate()).catch(error => {
|
||||||
|
@ -516,7 +516,7 @@ class MusicInfoManager extends ClientInfoManager {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
_frame.find(".btn-rewind").click(() => {
|
_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,
|
bot_id: bot.properties.client_database_id,
|
||||||
action: 4
|
action: 4
|
||||||
}).then(updated => this.triggerUpdate()).catch(error => {
|
}).then(updated => this.triggerUpdate()).catch(error => {
|
||||||
|
@ -525,7 +525,7 @@ class MusicInfoManager extends ClientInfoManager {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
_frame.find(".btn-settings").click(() => {
|
_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) {
|
for(const entry of lists) {
|
||||||
if(entry.playlist_id == bot.properties.client_playlist_id) {
|
if(entry.playlist_id == bot.properties.client_playlist_id) {
|
||||||
Modals.spawnPlaylistEdit(bot.channelTree.client, entry);
|
Modals.spawnPlaylistEdit(bot.channelTree.client, entry);
|
||||||
|
@ -581,7 +581,7 @@ class MusicInfoManager extends ClientInfoManager {
|
||||||
slider.prop("edited", true);
|
slider.prop("edited", true);
|
||||||
|
|
||||||
let current_timestamp = info.player_replay_index + Date.now() - timestamp;
|
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,
|
bot_id: bot.properties.client_database_id,
|
||||||
action: current_timestamp > target_timestamp ? 6 : 5,
|
action: current_timestamp > target_timestamp ? 6 : 5,
|
||||||
units: current_timestamp < target_timestamp ? target_timestamp - current_timestamp : current_timestamp - target_timestamp
|
units: current_timestamp < target_timestamp ? target_timestamp - current_timestamp : current_timestamp - target_timestamp
|
||||||
|
@ -627,17 +627,23 @@ class MusicInfoManager extends ClientInfoManager {
|
||||||
update_handler();
|
update_handler();
|
||||||
|
|
||||||
/* register subscription */
|
/* 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");
|
console.error("Failed to subscribe to displayed music bot! Using pseudo timeline");
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.notify_status = json => {
|
this.single_handler = {
|
||||||
json = json[0];
|
command: "notifymusicstatusupdate",
|
||||||
|
function: command => {
|
||||||
|
const json = command.arguments[0];
|
||||||
update_handler(parseInt(json["player_replay_index"]), parseInt(json["player_buffered_index"]));
|
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>) {
|
finalizeFrame(object: ClientEntry, frame: JQuery<HTMLElement>) {
|
||||||
if(this.notify_status) {
|
if(this.single_handler) {
|
||||||
this.handle.handle.serverConnection.commandHandler.unset_handler("notifymusicstatusupdate", this.notify_status);
|
this.handle.handle.serverConnection.command_handler_boss().remove_single_handler(this.single_handler);
|
||||||
this.notify_status = undefined;
|
this.single_handler = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
super.finalizeFrame(object, frame);
|
super.finalizeFrame(object, frame);
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace Modals {
|
||||||
if(result.server_id < 0) result.server_id = undefined;
|
if(result.server_id < 0) result.server_id = undefined;
|
||||||
console.log(tr("Adding ban %o"), result);
|
console.log(tr("Adding ban %o"), result);
|
||||||
|
|
||||||
client.serverConnection.sendCommand("banadd", {
|
client.serverConnection.send_command("banadd", {
|
||||||
ip: result.ip,
|
ip: result.ip,
|
||||||
name: result.name,
|
name: result.name,
|
||||||
uid: result.unique_id,
|
uid: result.unique_id,
|
||||||
|
@ -55,7 +55,7 @@ namespace Modals {
|
||||||
console.log(tr("Apply edit changes %o"), result);
|
console.log(tr("Apply edit changes %o"), result);
|
||||||
if(result.server_id < 0) result.server_id = undefined;
|
if(result.server_id < 0) result.server_id = undefined;
|
||||||
|
|
||||||
client.serverConnection.sendCommand("banedit", {
|
client.serverConnection.send_command("banedit", {
|
||||||
banid: result.banid,
|
banid: result.banid,
|
||||||
ip: result.ip,
|
ip: result.ip,
|
||||||
name: result.name,
|
name: result.name,
|
||||||
|
@ -73,7 +73,7 @@ namespace Modals {
|
||||||
});
|
});
|
||||||
}, ban => {
|
}, ban => {
|
||||||
console.log(tr("Deleting ban %o"), ban);
|
console.log(tr("Deleting ban %o"), ban);
|
||||||
client.serverConnection.sendCommand("bandel", {
|
client.serverConnection.send_command("bandel", {
|
||||||
banid: ban.banid,
|
banid: ban.banid,
|
||||||
sid: ban.server_id
|
sid: ban.server_id
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
@ -140,8 +140,8 @@ namespace Modals {
|
||||||
|
|
||||||
//TODO test permission
|
//TODO test permission
|
||||||
modal.clear();
|
modal.clear();
|
||||||
client.serverConnection.sendCommand("banlist", { sid: 0 }); //Global ban list
|
client.serverConnection.send_command("banlist", { sid: 0 }); //Global ban list
|
||||||
client.serverConnection.sendCommand("banlist").catch(error => {
|
client.serverConnection.send_command("banlist").catch(error => {
|
||||||
if(error instanceof CommandResult) {
|
if(error instanceof CommandResult) {
|
||||||
} else {
|
} else {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
|
|
@ -665,7 +665,7 @@ namespace Modals {
|
||||||
permission.id,
|
permission.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("channelclientdelperm", {
|
return globalClient.serverConnection.send_command("channelclientdelperm", {
|
||||||
cldbid: current_cldbid,
|
cldbid: current_cldbid,
|
||||||
cid: current_channel.channelId,
|
cid: current_channel.channelId,
|
||||||
permid: permission.id,
|
permid: permission.id,
|
||||||
|
@ -677,7 +677,7 @@ namespace Modals {
|
||||||
value.granted,
|
value.granted,
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("channelclientdelperm", {
|
return globalClient.serverConnection.send_command("channelclientdelperm", {
|
||||||
cldbid: current_cldbid,
|
cldbid: current_cldbid,
|
||||||
cid: current_channel.channelId,
|
cid: current_channel.channelId,
|
||||||
permid: permission.id_grant(),
|
permid: permission.id_grant(),
|
||||||
|
@ -694,7 +694,7 @@ namespace Modals {
|
||||||
value.flag_negate
|
value.flag_negate
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("channelclientaddperm", {
|
return globalClient.serverConnection.send_command("channelclientaddperm", {
|
||||||
cldbid: current_cldbid,
|
cldbid: current_cldbid,
|
||||||
cid: current_channel.channelId,
|
cid: current_channel.channelId,
|
||||||
permid: permission.id,
|
permid: permission.id,
|
||||||
|
@ -709,7 +709,7 @@ namespace Modals {
|
||||||
value.granted,
|
value.granted,
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("channelclientaddperm", {
|
return globalClient.serverConnection.send_command("channelclientaddperm", {
|
||||||
cldbid: current_cldbid,
|
cldbid: current_cldbid,
|
||||||
cid: current_channel.channelId,
|
cid: current_channel.channelId,
|
||||||
permid: permission.id_grant(),
|
permid: permission.id_grant(),
|
||||||
|
@ -821,7 +821,7 @@ namespace Modals {
|
||||||
permission.id,
|
permission.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("clientaddperm", {
|
return globalClient.serverConnection.send_command("clientaddperm", {
|
||||||
cldbid: current_cldbid,
|
cldbid: current_cldbid,
|
||||||
permid: permission.id,
|
permid: permission.id,
|
||||||
});
|
});
|
||||||
|
@ -832,7 +832,7 @@ namespace Modals {
|
||||||
value.granted,
|
value.granted,
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("clientaddperm", {
|
return globalClient.serverConnection.send_command("clientaddperm", {
|
||||||
cldbid: current_cldbid,
|
cldbid: current_cldbid,
|
||||||
permid: permission.id_grant(),
|
permid: permission.id_grant(),
|
||||||
});
|
});
|
||||||
|
@ -848,7 +848,7 @@ namespace Modals {
|
||||||
value.flag_negate
|
value.flag_negate
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("clientaddperm", {
|
return globalClient.serverConnection.send_command("clientaddperm", {
|
||||||
cldbid: current_cldbid,
|
cldbid: current_cldbid,
|
||||||
permid: permission.id,
|
permid: permission.id,
|
||||||
permvalue: value.value,
|
permvalue: value.value,
|
||||||
|
@ -862,7 +862,7 @@ namespace Modals {
|
||||||
value.granted,
|
value.granted,
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("clientaddperm", {
|
return globalClient.serverConnection.send_command("clientaddperm", {
|
||||||
cldbid: current_cldbid,
|
cldbid: current_cldbid,
|
||||||
permid: permission.id_grant(),
|
permid: permission.id_grant(),
|
||||||
permvalue: value.granted,
|
permvalue: value.granted,
|
||||||
|
@ -956,7 +956,7 @@ namespace Modals {
|
||||||
permission.id,
|
permission.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("channeldelperm", {
|
return globalClient.serverConnection.send_command("channeldelperm", {
|
||||||
cid: current_channel.channelId,
|
cid: current_channel.channelId,
|
||||||
permid: permission.id,
|
permid: permission.id,
|
||||||
});
|
});
|
||||||
|
@ -968,7 +968,7 @@ namespace Modals {
|
||||||
value.granted,
|
value.granted,
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("channeldelperm", {
|
return globalClient.serverConnection.send_command("channeldelperm", {
|
||||||
cid: current_channel.channelId,
|
cid: current_channel.channelId,
|
||||||
permid: permission.id_grant(),
|
permid: permission.id_grant(),
|
||||||
});
|
});
|
||||||
|
@ -984,7 +984,7 @@ namespace Modals {
|
||||||
value.flag_negate
|
value.flag_negate
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("channeladdperm", {
|
return globalClient.serverConnection.send_command("channeladdperm", {
|
||||||
cid: current_channel.channelId,
|
cid: current_channel.channelId,
|
||||||
permid: permission.id,
|
permid: permission.id,
|
||||||
permvalue: value.value,
|
permvalue: value.value,
|
||||||
|
@ -999,7 +999,7 @@ namespace Modals {
|
||||||
value.granted,
|
value.granted,
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("channeladdperm", {
|
return globalClient.serverConnection.send_command("channeladdperm", {
|
||||||
cid: current_channel.channelId,
|
cid: current_channel.channelId,
|
||||||
permid: permission.id_grant(),
|
permid: permission.id_grant(),
|
||||||
permvalue: value.granted,
|
permvalue: value.granted,
|
||||||
|
@ -1058,7 +1058,7 @@ namespace Modals {
|
||||||
permission.id,
|
permission.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("channelgroupdelperm", {
|
return globalClient.serverConnection.send_command("channelgroupdelperm", {
|
||||||
cgid: current_group.id,
|
cgid: current_group.id,
|
||||||
permid: permission.id,
|
permid: permission.id,
|
||||||
});
|
});
|
||||||
|
@ -1069,7 +1069,7 @@ namespace Modals {
|
||||||
value.granted,
|
value.granted,
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("channelgroupdelperm", {
|
return globalClient.serverConnection.send_command("channelgroupdelperm", {
|
||||||
cgid: current_group.id,
|
cgid: current_group.id,
|
||||||
permid: permission.id_grant(),
|
permid: permission.id_grant(),
|
||||||
});
|
});
|
||||||
|
@ -1085,7 +1085,7 @@ namespace Modals {
|
||||||
value.flag_negate
|
value.flag_negate
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("channelgroupaddperm", {
|
return globalClient.serverConnection.send_command("channelgroupaddperm", {
|
||||||
cgid: current_group.id,
|
cgid: current_group.id,
|
||||||
permid: permission.id,
|
permid: permission.id,
|
||||||
permvalue: value.value,
|
permvalue: value.value,
|
||||||
|
@ -1099,7 +1099,7 @@ namespace Modals {
|
||||||
value.granted,
|
value.granted,
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("channelgroupaddperm", {
|
return globalClient.serverConnection.send_command("channelgroupaddperm", {
|
||||||
cgid: current_group.id,
|
cgid: current_group.id,
|
||||||
permid: permission.id_grant(),
|
permid: permission.id_grant(),
|
||||||
permvalue: value.granted,
|
permvalue: value.granted,
|
||||||
|
@ -1218,7 +1218,7 @@ namespace Modals {
|
||||||
permission.id,
|
permission.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("servergroupdelperm", {
|
return globalClient.serverConnection.send_command("servergroupdelperm", {
|
||||||
sgid: current_group.id,
|
sgid: current_group.id,
|
||||||
permid: permission.id,
|
permid: permission.id,
|
||||||
});
|
});
|
||||||
|
@ -1229,7 +1229,7 @@ namespace Modals {
|
||||||
value.granted,
|
value.granted,
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("servergroupdelperm", {
|
return globalClient.serverConnection.send_command("servergroupdelperm", {
|
||||||
sgid: current_group.id,
|
sgid: current_group.id,
|
||||||
permid: permission.id_grant(),
|
permid: permission.id_grant(),
|
||||||
});
|
});
|
||||||
|
@ -1245,7 +1245,7 @@ namespace Modals {
|
||||||
value.flag_negate
|
value.flag_negate
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("servergroupaddperm", {
|
return globalClient.serverConnection.send_command("servergroupaddperm", {
|
||||||
sgid: current_group.id,
|
sgid: current_group.id,
|
||||||
permid: permission.id,
|
permid: permission.id,
|
||||||
permvalue: value.value,
|
permvalue: value.value,
|
||||||
|
@ -1259,7 +1259,7 @@ namespace Modals {
|
||||||
value.granted,
|
value.granted,
|
||||||
);
|
);
|
||||||
|
|
||||||
return globalClient.serverConnection.sendCommand("servergroupaddperm", {
|
return globalClient.serverConnection.send_command("servergroupaddperm", {
|
||||||
sgid: current_group.id,
|
sgid: current_group.id,
|
||||||
permid: permission.id_grant(),
|
permid: permission.id_grant(),
|
||||||
permvalue: value.granted,
|
permvalue: value.granted,
|
||||||
|
|
|
@ -99,7 +99,7 @@ namespace Modals {
|
||||||
template.find(".buttons .button-save").on('click', event => {
|
template.find(".buttons .button-save").on('click', event => {
|
||||||
if(Object.keys(changed_properties).length != 0) {
|
if(Object.keys(changed_properties).length != 0) {
|
||||||
changed_properties["playlist_id"] = playlist.playlist_id;
|
changed_properties["playlist_id"] = playlist.playlist_id;
|
||||||
client.serverConnection.sendCommand("playlistedit", changed_properties).then(() => {
|
client.serverConnection.send_command("playlistedit", changed_properties).then(() => {
|
||||||
changed_properties = {};
|
changed_properties = {};
|
||||||
update_save();
|
update_save();
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
@ -121,7 +121,7 @@ namespace Modals {
|
||||||
}
|
}
|
||||||
|
|
||||||
array[0]["playlist_id"] = playlist.playlist_id;
|
array[0]["playlist_id"] = playlist.playlist_id;
|
||||||
client.serverConnection.sendCommand("playlistaddperm", array).then(() => {
|
client.serverConnection.send_command("playlistaddperm", array).then(() => {
|
||||||
changed_permissions = {};
|
changed_permissions = {};
|
||||||
update_save();
|
update_save();
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
@ -193,7 +193,7 @@ namespace Modals {
|
||||||
button_delete.detach();
|
button_delete.detach();
|
||||||
else
|
else
|
||||||
button_delete.on('click', event => {
|
button_delete.on('click', event => {
|
||||||
client.serverConnection.sendCommand("playlistsongremove", {
|
client.serverConnection.send_command("playlistsongremove", {
|
||||||
playlist_id: playlist.playlist_id,
|
playlist_id: playlist.playlist_id,
|
||||||
song_id: song.song_id
|
song_id: song.song_id
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
@ -236,7 +236,7 @@ namespace Modals {
|
||||||
song_tag.find(".button-song-add").on('click', event => {
|
song_tag.find(".button-song-add").on('click', event => {
|
||||||
spawnSongAdd(playlist, (url, loader) => {
|
spawnSongAdd(playlist, (url, loader) => {
|
||||||
//playlist_id invoker previous url
|
//playlist_id invoker previous url
|
||||||
client.serverConnection.sendCommand("playlistsongadd", {
|
client.serverConnection.send_command("playlistsongadd", {
|
||||||
playlist_id: playlist.playlist_id,
|
playlist_id: playlist.playlist_id,
|
||||||
invoker: loader,
|
invoker: loader,
|
||||||
url: url
|
url: url
|
||||||
|
|
|
@ -108,7 +108,7 @@ namespace Modals {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
client.serverConnection.commandHandler.set_handler("notifyplaylistcreated", notify_handler);
|
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);
|
client.serverConnection.commandHandler.unset_handler("notifyplaylistcreated", notify_handler);
|
||||||
if(error instanceof CommandResult)
|
if(error instanceof CommandResult)
|
||||||
error = error.extra_message || error.message;
|
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 => {
|
Modals.spawnYesNo(tr("Are you sure?"), tr("Do you really want to delete this playlist?"), result => {
|
||||||
if(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();
|
createInfoModal(tr("Playlist deleted successful"), tr("This playlist has been deleted successfully.")).open();
|
||||||
update_list();
|
update_list();
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
|
|
@ -19,8 +19,8 @@ namespace Modals {
|
||||||
const update_list = () => {
|
const update_list = () => {
|
||||||
const info_tag = modal.htmlTag.find(".footer .info a");
|
const info_tag = modal.htmlTag.find(".footer .info a");
|
||||||
info_tag.text("loading...");
|
info_tag.text("loading...");
|
||||||
client.serverConnection.helper.current_virtual_server_id().then(server_id => {
|
client.serverConnection.command_helper.current_virtual_server_id().then(server_id => {
|
||||||
client.serverConnection.helper.request_query_list(server_id).then(result => {
|
client.serverConnection.command_helper.request_query_list(server_id).then(result => {
|
||||||
selected_query = undefined;
|
selected_query = undefined;
|
||||||
|
|
||||||
const entries_tag = modal.htmlTag.find(".query-list-entries");
|
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 => {
|
createInputModal(tr("Change account name"), tr("Enter the new name for the login:<br>"), text => text.length >= 3, result => {
|
||||||
if(result) {
|
if(result) {
|
||||||
client.serverConnection.sendCommand("queryrename", {
|
client.serverConnection.send_command("queryrename", {
|
||||||
client_login_name: selected_query.username,
|
client_login_name: selected_query.username,
|
||||||
client_new_login_name: result
|
client_new_login_name: result
|
||||||
}).catch(error => {
|
}).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 => {
|
createInputModal(tr("Change account's password"), tr("Enter a new password (leave blank for auto generation):<br>"), text => true, result => {
|
||||||
if(result !== false) {
|
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_name: selected_query.username,
|
||||||
client_login_password: result
|
client_login_password: result
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
client.serverConnection.command_handler_boss().remove_single_handler(single_handler);
|
||||||
if(error instanceof CommandResult)
|
if(error instanceof CommandResult)
|
||||||
error = error.extra_message || error.message;
|
error = error.extra_message || error.message;
|
||||||
createErrorModal(tr("Unable to change password"), tr("Failed to change password<br>Message: ") + error).open();
|
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();
|
}).open();
|
||||||
});
|
});
|
||||||
|
@ -117,7 +122,7 @@ namespace Modals {
|
||||||
|
|
||||||
Modals.spawnYesNo(tr("Are you sure?"), tr("Do you really want to delete this account?"), result => {
|
Modals.spawnYesNo(tr("Are you sure?"), tr("Do you really want to delete this account?"), result => {
|
||||||
if(result) {
|
if(result) {
|
||||||
client.serverConnection.sendCommand("querydelete", {
|
client.serverConnection.send_command("querydelete", {
|
||||||
client_login_name: selected_query.username
|
client_login_name: selected_query.username
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
if(error instanceof CommandResult)
|
if(error instanceof CommandResult)
|
||||||
|
|
|
@ -144,7 +144,7 @@ class ServerEntry {
|
||||||
log.info(LogCategory.SERVER, tr("Changing server properties %o"), properties);
|
log.info(LogCategory.SERVER, tr("Changing server properties %o"), properties);
|
||||||
console.log(tr("Changed properties: %o"), properties);
|
console.log(tr("Changed properties: %o"), properties);
|
||||||
if (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);
|
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;
|
if(this.info_request_promise && Date.now() - this.lastInfoRequest < 1000) return this.info_request_promise;
|
||||||
this.lastInfoRequest = Date.now();
|
this.lastInfoRequest = Date.now();
|
||||||
this.nextInfoRequest = this.lastInfoRequest + 10 * 1000;
|
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_reject(error);
|
||||||
this.info_request_promise = undefined;
|
this.info_request_promise = undefined;
|
||||||
this.info_request_promise_reject = undefined;
|
this.info_request_promise_reject = undefined;
|
||||||
|
|
|
@ -450,7 +450,7 @@ class ChannelTree {
|
||||||
createInputModal(tr("Poke clients"), tr("Poke message:<br>"), text => true, result => {
|
createInputModal(tr("Poke clients"), tr("Poke message:<br>"), text => true, result => {
|
||||||
if (typeof(result) === "string") {
|
if (typeof(result) === "string") {
|
||||||
for (const client of this.currently_selected as ClientEntry[])
|
for (const client of this.currently_selected as ClientEntry[])
|
||||||
this.client.serverConnection.sendCommand("clientpoke", {
|
this.client.serverConnection.send_command("clientpoke", {
|
||||||
clid: client.clientId(),
|
clid: client.clientId(),
|
||||||
msg: result
|
msg: result
|
||||||
});
|
});
|
||||||
|
@ -467,7 +467,7 @@ class ChannelTree {
|
||||||
callback: () => {
|
callback: () => {
|
||||||
const target = this.client.getClient().currentChannel().getChannelId();
|
const target = this.client.getClient().currentChannel().getChannelId();
|
||||||
for(const client of clients)
|
for(const client of clients)
|
||||||
this.client.serverConnection.sendCommand("clientmove", {
|
this.client.serverConnection.send_command("clientmove", {
|
||||||
clid: client.clientId(),
|
clid: client.clientId(),
|
||||||
cid: target
|
cid: target
|
||||||
});
|
});
|
||||||
|
@ -483,7 +483,7 @@ class ChannelTree {
|
||||||
createInputModal(tr("Kick clients from channel"), tr("Kick reason:<br>"), text => true, result => {
|
createInputModal(tr("Kick clients from channel"), tr("Kick reason:<br>"), text => true, result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
for (const client of clients)
|
for (const client of clients)
|
||||||
this.client.serverConnection.sendCommand("clientkick", {
|
this.client.serverConnection.send_command("clientkick", {
|
||||||
clid: client.clientId(),
|
clid: client.clientId(),
|
||||||
reasonid: ViewReasonId.VREASON_CHANNEL_KICK,
|
reasonid: ViewReasonId.VREASON_CHANNEL_KICK,
|
||||||
reasonmsg: result
|
reasonmsg: result
|
||||||
|
@ -503,7 +503,7 @@ class ChannelTree {
|
||||||
createInputModal(tr("Kick clients from server"), tr("Kick reason:<br>"), text => true, result => {
|
createInputModal(tr("Kick clients from server"), tr("Kick reason:<br>"), text => true, result => {
|
||||||
if (result) {
|
if (result) {
|
||||||
for (const client of clients)
|
for (const client of clients)
|
||||||
this.client.serverConnection.sendCommand("clientkick", {
|
this.client.serverConnection.send_command("clientkick", {
|
||||||
clid: client.clientId(),
|
clid: client.clientId(),
|
||||||
reasonid: ViewReasonId.VREASON_SERVER_KICK,
|
reasonid: ViewReasonId.VREASON_SERVER_KICK,
|
||||||
reasonmsg: result
|
reasonmsg: result
|
||||||
|
@ -520,11 +520,13 @@ class ChannelTree {
|
||||||
callback: () => {
|
callback: () => {
|
||||||
Modals.spawnBanClient((clients).map(entry => entry.clientNickName()), (data) => {
|
Modals.spawnBanClient((clients).map(entry => entry.clientNickName()), (data) => {
|
||||||
for (const client of clients)
|
for (const client of clients)
|
||||||
this.client.serverConnection.sendCommand("banclient", {
|
this.client.serverConnection.send_command("banclient", {
|
||||||
uid: client.properties.client_unique_identifier,
|
uid: client.properties.client_unique_identifier,
|
||||||
banreason: data.reason,
|
banreason: data.reason,
|
||||||
time: data.length
|
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);
|
sound.play(Sound.USER_BANNED);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -545,7 +547,7 @@ class ChannelTree {
|
||||||
Modals.spawnYesNo(tr("Are you sure?"), tag_container, result => {
|
Modals.spawnYesNo(tr("Are you sure?"), tag_container, result => {
|
||||||
if(result) {
|
if(result) {
|
||||||
for(const client of clients)
|
for(const client of clients)
|
||||||
this.client.serverConnection.sendCommand("musicbotdelete", {
|
this.client.serverConnection.send_command("musicbotdelete", {
|
||||||
botid: client.properties.client_database_id
|
botid: client.properties.client_database_id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -595,7 +597,7 @@ class ChannelTree {
|
||||||
if(!properties) return;
|
if(!properties) return;
|
||||||
properties["cpid"] = parent ? parent.channelId : 0;
|
properties["cpid"] = parent ? parent.channelId : 0;
|
||||||
log.debug(LogCategory.CHANNEL, tr("Creating a new channel.\nProperties: %o\nPermissions: %o"), properties);
|
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);
|
let channel = this.find_channel_by_name(properties.channel_name, parent, true);
|
||||||
if(!channel) {
|
if(!channel) {
|
||||||
log.error(LogCategory.CHANNEL, tr("Failed to resolve channel after creation. Could not apply permissions!"));
|
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;
|
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); })
|
return new Promise<ChannelEntry>(resolve => { resolve(channel); })
|
||||||
|
|
|
@ -151,7 +151,7 @@ class AudioController {
|
||||||
|
|
||||||
private playQueue() {
|
private playQueue() {
|
||||||
let buffer: AudioBuffer;
|
let buffer: AudioBuffer;
|
||||||
while(buffer = this.audioCache.pop_front()) {
|
while((buffer = this.audioCache.pop_front())) {
|
||||||
if(this.playingAudioCache.length >= this._latencyBufferLength * 1.5 + 3) {
|
if(this.playingAudioCache.length >= this._latencyBufferLength * 1.5 + 3) {
|
||||||
console.log(tr("Dropping buffer because playing queue grows to much"));
|
console.log(tr("Dropping buffer because playing queue grows to much"));
|
||||||
continue; /* drop the data (we're behind) */
|
continue; /* drop the data (we're behind) */
|
||||||
|
|
Loading…
Add table
Reference in a new issue