UNPKG

ts3-nodejs-library

Version:
1,187 lines 88.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.QueryProtocol = exports.TeamSpeak = void 0; const events_1 = require("events"); const buffer_crc32_1 = __importDefault(require("buffer-crc32")); const TeamSpeakQuery_1 = require("./transport/TeamSpeakQuery"); const FileTransfer_1 = require("./transport/FileTransfer"); const Client_1 = require("./node/Client"); const Server_1 = require("./node/Server"); const Channel_1 = require("./node/Channel"); const ServerGroup_1 = require("./node/ServerGroup"); const ChannelGroup_1 = require("./node/ChannelGroup"); const Command_1 = require("./transport/Command"); const context_1 = require("./types/context"); const EventError_1 = require("./exception/EventError"); const enum_1 = require("./types/enum"); const Permission_1 = require("./util/Permission"); class TeamSpeak extends events_1.EventEmitter { constructor(config) { super(); this.clients = {}; this.servers = {}; this.servergroups = {}; this.channels = {}; this.channelgroups = {}; this.priorizeNextCommand = false; this.context = { selectType: context_1.SelectType.NONE, selected: 0, events: [] }; this.config = { protocol: TeamSpeak.QueryProtocol.RAW, host: "127.0.0.1", queryport: config.protocol === TeamSpeak.QueryProtocol.SSH ? 10022 : 10011, readyTimeout: 10000, ignoreQueries: false, keepAlive: true, keepAliveTimeout: 250, autoConnect: true, ...config }; this.query = new TeamSpeakQuery_1.TeamSpeakQuery(this.config); this.query.on("cliententerview", this.evcliententerview.bind(this)); this.query.on("clientleftview", this.evclientleftview.bind(this)); this.query.on("tokenused", this.evtokenused.bind(this)); this.query.on("serveredited", this.evserveredited.bind(this)); this.query.on("channeledited", this.evchanneledited.bind(this)); this.query.on("channelmoved", this.evchannelmoved.bind(this)); this.query.on("channeldeleted", this.evchanneldeleted.bind(this)); this.query.on("channelcreated", this.evchannelcreated.bind(this)); this.query.on("clientmoved", this.evclientmoved.bind(this)); this.query.on("textmessage", this.evtextmessage.bind(this)); this.query.on("ready", this.handleReady.bind(this)); this.query.on("close", (e) => super.emit("close", e)); this.query.on("error", (e) => super.emit("error", e)); this.query.on("flooding", (e) => super.emit("flooding", e)); this.query.on("debug", (data) => super.emit("debug", data)); //@ts-ignore this.on("newListener", this.handleNewListener.bind(this)); if (this.config.autoConnect) /** can be dropped silently since errors are getting emitted via the error event */ this.connect().catch(() => null); } /** * connects via a Promise wrapper * @param config config options to connect */ static connect(config) { return new TeamSpeak({ ...config, autoConnect: false }).connect(); } /** * attempts a reconnect to the teamspeak server with full context features * @param attempts the amount of times it should try to reconnect (-1 = try forever) * @param timeout time in ms to wait inbetween reconnect */ async reconnect(attempts = 1, timeout = 2000) { let attempt = 0; let error = null; while (attempts === -1 || attempt++ < attempts) { try { await TeamSpeak.wait(timeout); if (this.query.isConnected()) throw new Error("already connected"); await this.connect(); return this; } catch (e) { error = e; } } throw error ? error : new Error(`reconnecting failed after ${attempts} attempt(s)`); } /** * waits a set time of ms * @param time time in ms to wait */ static wait(time) { return new Promise(fulfill => setTimeout(fulfill, time)); } /** * connects to the TeamSpeak Server */ connect() { return new Promise((fulfill, reject) => { const removeListeners = () => { this.removeListener("ready", readyCallback); this.removeListener("error", errorCallback); this.removeListener("close", closeCallback); }; const readyCallback = () => { removeListeners(); fulfill(this); }; const errorCallback = (error) => { removeListeners(); this.forceQuit(); reject(error); }; const closeCallback = (error) => { removeListeners(); if (error instanceof Error) return reject(error); reject(new Error("TeamSpeak Server prematurely closed the connection")); }; this.once("ready", readyCallback); this.once("error", errorCallback); this.once("close", closeCallback); this.query.connect(); }); } /** subscribes to some query events if necessary */ handleNewListener(event) { const commands = []; switch (event) { case "clientconnect": case "clientdisconnect": case "serveredit": if (this.isSubscribedToEvent("server")) break; commands.push(this.registerEvent("server")); break; case "tokenused": if (this.isSubscribedToEvent("tokenused")) break; commands.push(this.registerEvent("tokenused")); break; case "channeledit": case "channelmoved": case "channeldelete": case "channelcreate": case "clientmoved": if (this.isSubscribedToEvent("channel", "0")) break; commands.push(this.registerEvent("channel", "0")); break; case "textmessage": if (!this.isSubscribedToEvent("textserver")) commands.push(this.registerEvent("textserver")); if (!this.isSubscribedToEvent("textchannel")) commands.push(this.registerEvent("textchannel")); if (!this.isSubscribedToEvent("textprivate")) commands.push(this.registerEvent("textprivate")); } Promise.all(commands).catch(e => this.emit("error", e)); } /** handles initial commands after successfully connecting to a TeamSpeak Server */ handleReady() { const exec = []; if (this.context.login && this.config.protocol === TeamSpeak.QueryProtocol.RAW) { exec.push(this.priorize().login(this.context.login.username, this.context.login.password)); } else if (this.config.username && this.config.password && this.config.protocol === TeamSpeak.QueryProtocol.RAW) { exec.push(this.priorize().login(this.config.username, this.config.password)); } if (this.context.selectType !== context_1.SelectType.NONE) { if (this.context.selectType === context_1.SelectType.PORT) { exec.push(this.priorize().useByPort(this.context.selected, this.context.clientNickname || this.config.nickname)); } else if (this.context.selectType === context_1.SelectType.SID) { exec.push(this.priorize().useBySid(this.context.selected, this.context.clientNickname || this.config.nickname)); } } else if (this.config.serverport) { exec.push(this.priorize().useByPort(this.config.serverport, this.config.nickname)); } exec.push(...this.context.events.map(ev => this.priorize().registerEvent(ev.event, ev.id))); exec.push(this.priorize().version()); this.query.pause(false); return Promise.all(exec) .then(() => super.emit("ready")) .catch(e => super.emit("error", e)); } /** * Gets called when a client connects to the TeamSpeak Server * @param event the raw teamspeak event */ evcliententerview(event) { this.clientList().then(clients => { const client = clients.find(client => client.clid === event.clid); if (!client) throw new EventError_1.EventError(`could not fetch client with id ${event.clid}`, "cliententerview"); if (this.ignoreQueryClient(client.type)) return; super.emit("clientconnect", { client, cid: event.ctid }); }) .catch(error => this.emit("error", error)); } /** * Gets called when a client discconnects from the TeamSpeak Server * @param event the raw teamspeak event */ evclientleftview(event) { const { clid } = event; const client = this.clients[clid]; if (client && this.ignoreQueryClient(client.type)) return; super.emit("clientdisconnect", { client, event }); Reflect.deleteProperty(this.clients, clid); } /** * Gets called when a client uses a privilege key * @param event the raw teamspeak event */ evtokenused(event) { this.getClientById(event.clid).then(client => { if (!client) throw new EventError_1.EventError(`could not fetch client with id ${event.clid}`, "tokenused"); if (this.ignoreQueryClient(client.type)) return; super.emit("tokenused", { client, token: event.token, token1: event.token1, token2: event.token2, tokencustomset: event.tokencustomset }); }).catch(e => super.emit("error", e)); } /** * Gets called when a chat message gets received * @param event the raw teamspeak event */ evtextmessage(event) { this.getClientById(event.invokerid).then(invoker => { if (!invoker) throw new EventError_1.EventError(`could not fetch client with id ${event.invokerid}`, "textmessage"); if (this.ignoreQueryClient(invoker.type)) return; super.emit("textmessage", { invoker, msg: event.msg, targetmode: event.targetmode }); }).catch(e => super.emit("error", e)); } /** * Gets called when a client moves to a different channel * @param event the raw teamspeak event */ evclientmoved(event) { Promise.all([ this.getClientById(event.clid), this.getChannelById(event.ctid) ]).then(([client, channel]) => { if (!client) throw new EventError_1.EventError(`could not fetch client with id ${event.clid}`, "clientmoved"); if (!channel) throw new EventError_1.EventError(`could not fetch channel with id ${event.ctid}`, "clientmoved"); if (this.ignoreQueryClient(client.type)) return; this.emit("clientmoved", { client, channel, reasonid: event.reasonid }); }).catch(e => this.emit("error", e)); } /** * Gets called when the server has been edited * @param event the raw teamspeak event */ async evserveredited(event) { this.getClientById(event.invokerid).then(invoker => { if (!invoker) throw new EventError_1.EventError(`could not fetch client with id ${event.invokerid}`, "serveredited"); if (this.ignoreQueryClient(invoker.type)) return; const modified = {}; Object.keys(event) .filter(k => k.startsWith("virtualserver")) .forEach(k => modified[k] = event[k]); this.emit("serveredit", { invoker, modified, reasonid: event.reasonid }); }).catch(e => this.emit("error", e)); } /** * Gets called when a channel gets edited * @param event the raw teamspeak event */ evchanneledited(event) { Promise.all([ this.getClientById(event.invokerid), this.getChannelById(event.cid) ]).then(([invoker, channel]) => { if (!invoker) throw new EventError_1.EventError(`could not fetch client with id ${event.invokerid}`, "channeledited"); if (this.ignoreQueryClient(invoker.type)) return; if (!channel) throw new EventError_1.EventError(`could not fetch channel with id ${event.cid}`, "channeledited"); const modified = {}; Object.keys(event) .filter(k => k.startsWith("channel")) .forEach(k => modified[k] = event[k]); this.emit("channeledit", { invoker, channel, modified, reasonid: event.reasonid }); }).catch(e => this.emit("error", e)); } /** * Gets called when a channel gets edited * @param event the raw teamspeak event */ evchannelcreated(event) { Promise.all([ this.getClientById(event.invokerid), this.getChannelById(event.cid) ]).then(([invoker, channel]) => { if (!invoker) throw new EventError_1.EventError(`could not fetch client with id ${event.invokerid}`, "channelcreated"); if (this.ignoreQueryClient(invoker.type)) return; if (!channel) throw new EventError_1.EventError(`could not fetch channel with id ${event.cid}`, "channelcreated"); const modified = {}; Object.keys(event) .filter(k => k.startsWith("channel")) .forEach(k => modified[k] = event[k]); this.emit("channelcreate", { invoker, channel, modified, cpid: event.cpid }); }).catch(e => this.emit("error", e)); } /** * Gets called when a channel gets moved * @param event the raw teamspeak event */ evchannelmoved(event) { Promise.all([ this.getClientById(event.invokerid), this.getChannelById(event.cid), this.getChannelById(event.cpid) ]).then(([invoker, channel, parent]) => { if (!invoker) throw new EventError_1.EventError(`could not fetch client with id ${event.invokerid}`, "channelmoved"); if (this.ignoreQueryClient(invoker.type)) return; if (!channel) throw new EventError_1.EventError(`could not fetch channel with id ${event.cid}`, "channelmoved"); this.emit("channelmoved", { invoker, channel, parent, order: event.order }); }).catch(e => this.emit("error", e)); } /** * Gets called when a channel gets deleted * @param event the raw teamspeak event */ async evchanneldeleted(event) { this.getClientById(event.invokerid).then(invoker => { if (invoker && this.ignoreQueryClient(invoker.type)) return; this.emit("channeldelete", { invoker, cid: event.cid }); }) .catch(e => this.emit("error", e)); } /** priorizes the next command, this commands will be first in execution */ priorize() { this.priorizeNextCommand = true; return this; } /** * Sends a raw command to the TeamSpeak Server. * @param {...any} args the command which should get executed on the teamspeak server * @example * ts3.execute("clientlist", ["-ip"]) * ts3.execute("use", [9987], { clientnickname: "test" }) */ execute(cmd, ...args) { if (this.priorizeNextCommand) { this.priorizeNextCommand = false; return this.query.executePrio(cmd, ...args); } else { return this.query.execute(cmd, ...args); } } /** * Adds a new query client login, or enables query login for existing clients. * When no virtual server has been selected, the command will create global query logins. * Otherwise the command enables query login for existing client, and cldbid must be specified. * @param clientLoginName the login name * @param client optional database id or teamspeak client */ queryLoginAdd(clientLoginName, client) { return this.execute("queryloginadd", { clientLoginName, cldbid: Client_1.TeamSpeakClient.getDbid(client) }).then(TeamSpeak.singleResponse); } /** * Deletes an existing server query login on selected server. * When no virtual server has been selected, deletes global query logins instead. * @param client client database id or teamspeak client object */ queryLoginDel(client) { return this.execute("querylogindel", { cldbid: Client_1.TeamSpeakClient.getDbid(client) }); } /** * List existing query client logins. * The pattern parameter can include regular characters and SQL wildcard characters (e.g. %). * Only displays query logins of the selected virtual server, or all query logins when no virtual server have been selected. * @param pattern the pattern to filter for client login names * @param start the offset from where clients should be listed * @param duration how many clients should be listed */ queryLoginList(pattern, start, duration) { return this.execute("queryloginlist", { pattern, start, duration }, ["-count"]) .then(TeamSpeak.toArray); } apiKeyAdd(props) { return this.execute("apikeyadd", props) .then(TeamSpeak.singleResponse); } /** * Lists all apikeys owned by the user, or of all users using cldbid=*. * Usage of cldbid=... requires bVirtualserverApikeyManage. */ apiKeyList(props = {}) { return this.execute("apikeylist", props, ["-count"]) .then(TeamSpeak.toArray); } /** * Deletes an apikey. Any apikey owned by the current user, can always be deleted * Deleting apikeys from other requires bVirtualserverApikeyManage * @param id the key id to delete */ apiKeyDel(id) { return this.execute("apikeydel", { id }); } /** * Updates your own ServerQuery login credentials using a specified username. * The password will be auto-generated. * @param name */ clientSetServerQueryLogin(name) { return this.execute("clientsetserverquerylogin", { clientLoginName: name }) .then(TeamSpeak.singleResponse); } /** * Change your ServerQuery clients settings using given properties. * @param props the properties which should be changed */ clientUpdate(props) { return this.execute("clientupdate", props) .then(this.updateContextResolve({ clientNickname: props.clientNickname ? props.clientNickname : this.context.clientNickname })); } /** * Subscribes to an Event * @param event the event on which should be subscribed * @param id the channel id, only required when subscribing to the "channel" event */ registerEvent(event, id) { return this.execute("servernotifyregister", { event, id }) .then(this.updateContextResolve({ events: [{ event, id }] })); } /** * Subscribes to an Event. */ unregisterEvent() { return this.execute("servernotifyunregister") .then(this.updateContextResolve({ events: [] })); } /** * Authenticates with the TeamSpeak 3 Server instance using given ServerQuery login credentials. * @param username the username which you want to login with * @param password the password you want to login with */ login(username, password) { return this.execute("login", [username, password]) .then(this.updateContextResolve({ login: { username, password } })) .catch(this.updateContextReject({ login: undefined })); } /** Deselects the active virtual server and logs out from the server instance. */ logout() { return this.execute("logout") .then(this.updateContextResolve({ selectType: context_1.SelectType.NONE, clientNickname: this.config.nickname, login: undefined, events: [] })); } /** * Displays the servers version information including platform and build number. * @param refresh if this parameter has been set it will send a command to the server otherwise will use the cached info */ async version(refresh = false) { if (refresh || !this.serverVersion) { this.serverVersion = await this.execute("version").then(TeamSpeak.singleResponse); } return this.serverVersion; } /** * Displays detailed connection information about the server instance including uptime, * number of virtual servers online, traffic information, etc. */ hostInfo() { return this.execute("hostinfo") .then(TeamSpeak.singleResponse); } /** * Displays the server instance configuration including database revision number, * the file transfer port, default group IDs, etc. */ instanceInfo() { return this.execute("instanceinfo") .then(TeamSpeak.singleResponse); } /** * Changes the server instance configuration using given properties. * @param properties the props you want to change */ instanceEdit(properties) { return this.execute("instanceedit", properties); } /** returns a list of IP addresses used by the server instance on multi-homed machines. */ bindingList() { return this.execute("bindinglist") .then(TeamSpeak.toArray); } /** * Selects the virtual server specified with the port to allow further interaction. * @param port the port the server runs on * @param clientNickname set nickname when selecting a server */ useByPort(port, clientNickname) { return this.execute("use", { port, clientNickname }, ["-virtual"]) .then(this.updateContextResolve({ selectType: context_1.SelectType.PORT, selected: port, clientNickname, events: [] })) .catch(this.updateContextReject({ selectType: context_1.SelectType.NONE })); } /** * Selects the virtual server specified with the sid to allow further interaction. * @param server the server id * @param clientNickname set nickname when selecting a server */ useBySid(server, clientNickname) { return this.execute("use", [Server_1.TeamSpeakServer.getId(server), "-virtual"], { clientNickname }) .then(this.updateContextResolve({ selectType: context_1.SelectType.SID, selected: Server_1.TeamSpeakServer.getId(server), clientNickname, events: [] })); } /** returns information about your current ServerQuery connection including your loginname, etc. */ whoami() { return this.execute("whoami") .then(TeamSpeak.singleResponse); } /** retrieves the own query client as TeamSpeakClient instance */ async self() { const { clientId } = await this.whoami(); let client = this.clients[clientId]; if (client) return client; client = await this.getClientById(clientId); if (client) return client; throw new Error("could not find own query client"); } /** * Displays detailed configuration information about the selected virtual server * including unique ID, number of clients online, configuration, etc. */ serverInfo() { return this.execute("serverinfo") .then(TeamSpeak.singleResponse); } /** * Displays the database ID of the virtual server running on the UDP port * @param virtualserverPort the server port where data should be retrieved */ serverIdGetByPort(virtualserverPort) { return this.execute("serveridgetbyport", { virtualserverPort }) .then(TeamSpeak.singleResponse); } /** * Changes the selected virtual servers configuration using given properties. * Note that this command accepts multiple properties which means that you're able to change all settings of the selected virtual server at once. */ serverEdit(properties) { return this.execute("serveredit", properties); } /** * Stops the entire TeamSpeak 3 Server instance by shutting down the process. * @param reasonmsg specifies a text message that is sent to the clients before the client disconnects (requires TeamSpeak Server 3.2.0 or newer). */ serverProcessStop(reasonmsg) { return this.execute("serverprocessstop", { reasonmsg }); } /** * returns detailed connection information about the selected virtual server including uptime, traffic information, etc. */ connectionInfo() { return this.execute("serverrequestconnectioninfo") .then(TeamSpeak.singleResponse); } /** * Creates a new virtual server using the given properties and displays its ID, port and initial administrator privilege key. * If virtualserverPort is not specified, the server will test for the first unused UDP port * @param properties the server properties */ serverCreate(properties) { let servertoken = ""; return this.execute("servercreate", properties) .then(TeamSpeak.singleResponse) .then(({ token, sid }) => { servertoken = token; return this.serverList({ virtualserverId: sid }); }) .then(([server]) => ({ server, token: servertoken })); } /** * deletes the teamspeak server * @param server the server id to delete */ serverDelete(server) { return this.execute("serverdelete", { sid: Server_1.TeamSpeakServer.getId(server) }); } /** * Starts the virtual server. Depending on your permissions, * you're able to start either your own virtual server only or all virtual servers in the server instance. * @param server the server id to start */ serverStart(server) { return this.execute("serverstart", { sid: Server_1.TeamSpeakServer.getId(server) }); } /** * Stops the virtual server. Depending on your permissions, * you're able to stop either your own virtual server only or all virtual servers in the server instance. * @param server the server id to stop * @param reasonmsg Specifies a text message that is sent to the clients before the client disconnects (requires TeamSpeak Server 3.2.0 or newer). */ serverStop(server, reasonmsg) { return this.execute("serverstop", { sid: Server_1.TeamSpeakServer.getId(server), reasonmsg }); } /** * Creates a new server group using the name specified with name. * The optional type parameter can be used to create ServerQuery groups and template groups. * @param name the name of the servergroup * @param type type of the servergroup */ serverGroupCreate(name, type = 1) { return this.execute("servergroupadd", { name, type }) .then(TeamSpeak.singleResponse) .then(({ sgid }) => this.serverGroupList({ sgid })) .then(group => group[0]); } /** * returns the IDs of all clients currently residing in the server group. * @param group the servergroup id */ serverGroupClientList(group) { return this.execute("servergroupclientlist", { sgid: ServerGroup_1.TeamSpeakServerGroup.getId(group) }, ["-names"]) .then(TeamSpeak.toArray); } /** * Adds one or more clients to a server group specified with sgid. * Please note that a client cannot be added to default groups or template groups * @param client one or more client database ids which should be added * @param group the servergroup id which the client(s) should be added to */ serverGroupAddClient(client, group) { return this.execute("servergroupaddclient", { sgid: ServerGroup_1.TeamSpeakServerGroup.getId(group), cldbid: Client_1.TeamSpeakClient.getMultipleDbids(client) }); } /** * Removes one or more clients from the server group specified with sgid. * @param client one or more client database ids which should be added * @param group the servergroup id which the client(s) should be removed from */ serverGroupDelClient(client, group) { return this.execute("servergroupdelclient", { sgid: ServerGroup_1.TeamSpeakServerGroup.getId(group), cldbid: Client_1.TeamSpeakClient.getMultipleDbids(client) }); } /** * displays all server groups the client specified with cldbid is currently residing in * @param client the client database id to check */ serverGroupsByClientId(client) { return this.execute("servergroupsbyclientid", { cldbid: Client_1.TeamSpeakClient.getMultipleDbids(client) }) .then(TeamSpeak.toArray); } /** * Adds one or more servergroups to a client. * Please note that a client cannot be added to default groups or template groups * @param client one or more client database ids which should be added * @param group one or more servergroup ids which the client should be added to */ clientAddServerGroup(client, group) { return this.execute("clientaddservergroup", { cldbid: Client_1.TeamSpeakClient.getDbid(client), sgid: ServerGroup_1.TeamSpeakServerGroup.getMultipleIds(group) }); } /** * Removes one or more servergroups from the client. * @param client one or more client database ids which should be added * @param groups one or more servergroup ids which the client should be removed from */ clientDelServerGroup(client, groups) { return this.execute("clientdelservergroup", { cldbid: Client_1.TeamSpeakClient.getDbid(client), sgid: ServerGroup_1.TeamSpeakServerGroup.getMultipleIds(groups) }); } /** * Deletes the server group. If force is set to 1, the server group will be deleted even if there are clients within. * @param group the servergroup id * @param force if set to 1 the servergoup will be deleted even when clients stil belong to this group */ serverGroupDel(group, force = false) { return this.execute("servergroupdel", { sgid: ServerGroup_1.TeamSpeakServerGroup.getId(group), force }); } /** * Creates a copy of the server group specified with ssgid. * If tsgid is set to 0, the server will create a new group. * To overwrite an existing group, simply set tsgid to the ID of a designated target group. * If a target group is set, the name parameter will be ignored. * @param sourceGroup the source ServerGroup * @param targetGroup the target ServerGroup, 0 to create a new Group * @param type the type of the servergroup (0 = Query Group | 1 = Normal Group) * @param name name of the group */ serverGroupCopy(sourceGroup, targetGroup = "0", type = 1, name = "foo") { return this.execute("servergroupcopy", { ssgid: ServerGroup_1.TeamSpeakServerGroup.getId(sourceGroup), tsgid: ServerGroup_1.TeamSpeakServerGroup.getId(targetGroup), type, name }).then(TeamSpeak.singleResponse); } /** * Changes the name of the server group * @param group the servergroup id * @param name new name of the servergroup */ serverGroupRename(group, name) { return this.execute("servergrouprename", { sgid: ServerGroup_1.TeamSpeakServerGroup.getId(group), name }); } /** * Displays a list of permissions assigned to the server group specified with sgid. * @param sgid the servergroup id * @param permsid if the permsid option is set to true the output will contain the permission names */ serverGroupPermList(group, permsid = false) { const sgid = ServerGroup_1.TeamSpeakServerGroup.getId(group); return this.execute("servergrouppermlist", { sgid }, [permsid ? "-permsid" : null]).then(response => { return response.map(perm => { return this.createServerGroupPermBuilder(sgid) .perm(perm.permsid || perm.permid) .value(perm.permvalue) .skip(perm.permskip) .negate(perm.permnegated); }); }); } serverGroupAddPerm(group, perm) { const builder = this.createServerGroupPermBuilder(ServerGroup_1.TeamSpeakServerGroup.getId(group)); if (!perm) return builder; if (perm.permskip) builder.skip(perm.permskip); if (perm.permnegated) builder.negate(perm.permnegated); return builder.perm(perm.permname).value(perm.permvalue).update(); } /** * Removes a set of specified permissions from the server group. * A permission can be specified by permid or permsid. * @param group the servergroup id * @param perm the permid or permsid */ serverGroupDelPerm(group, perm) { const properties = { sgid: ServerGroup_1.TeamSpeakServerGroup.getId(group) }; properties[typeof perm === "string" ? "permsid" : "permid"] = perm; return this.execute("servergroupdelperm", properties); } /** * Sets a new temporary server password specified with pw. The temporary * password will be valid for the number of seconds specified with duration. The * client connecting with this password will automatically join the channel * specified with tcid. If tcid is set to 0, the client will join the default * channel. */ serverTempPasswordAdd(props) { return this.execute("servertemppasswordadd", { tcid: "0", tcpw: "", desc: "", ...props }); } /** * Deletes the temporary server password specified with pw. * @param pw the password to delete */ serverTempPasswordDel(pw) { return this.execute("servertemppassworddel", { pw }); } /** * Returns a list of active temporary server passwords. The output contains the * clear-text password, the nickname and unique identifier of the creating * client. */ serverTempPasswordList() { return this.execute("servertemppasswordlist") .then(TeamSpeak.toArray); } /** * Creates a new channel using the given properties. * Note that this command accepts multiple properties which means that you're able to specifiy all settings of the new channel at once. * @param name the name of the channel * @param properties properties of the channel */ channelCreate(name, properties = {}) { properties.channelName = name; return this.execute("channelcreate", properties) .then(TeamSpeak.singleResponse) .then(({ cid }) => this.channelList({ cid })) .then(([channel]) => channel); } /** * Creates a new channel group using a given name. * The optional type parameter can be used to create ServerQuery groups and template groups. * @param name the name of the channelgroup * @param type type of the channelgroup */ channelGroupCreate(name, type = 1) { return this.execute("channelgroupadd", { name, type }) .then(TeamSpeak.singleResponse) .then(({ cgid }) => this.channelGroupList({ cgid })) .then(([group]) => group); } /** * Retrieves a Single Channel by the given Channel ID * @param channel the channel id */ getChannelById(channel) { return this.channelList({ cid: Channel_1.TeamSpeakChannel.getId(channel) }).then(([channel]) => channel); } /** * Retrieves a Single Channel by the given Channel Name * @param channelName the name of the channel */ getChannelByName(channelName) { return this.channelList({ channelName }).then(([channel]) => channel); } /** * displays a list of channels matching a given name pattern * @param pattern the channel name pattern to search for */ channelFind(pattern) { return this.execute("channelfind", { pattern }).then(TeamSpeak.toArray); } /** * Displays detailed configuration information about a channel including ID, topic, description, etc. * @param channel the channel id */ channelInfo(channel) { return this.execute("channelinfo", { cid: Channel_1.TeamSpeakChannel.getId(channel) }).then(TeamSpeak.singleResponse); } /** * Moves a channel to a new parent channel with the ID cpid. * If order is specified, the channel will be sorted right under the channel with the specified ID. * If order is set to 0, the channel will be sorted right below the new parent. * @param channel the channel id * @param parent channel parent id * @param order channel sort order */ channelMove(channel, parent, order = 0) { return this.execute("channelmove", { cid: Channel_1.TeamSpeakChannel.getId(channel), cpid: Channel_1.TeamSpeakChannel.getId(parent), order }); } /** * Deletes an existing channel by ID. * If force is set to 1, the channel will be deleted even if there are clients within. * The clients will be kicked to the default channel with an appropriate reason message. * @param channel the channel id * @param force if set to 1 the channel will be deleted even when client are in it */ channelDelete(channel, force = false) { return this.execute("channeldelete", { cid: Channel_1.TeamSpeakChannel.getId(channel), force }); } /** * Changes a channels configuration using given properties. * Note that this command accepts multiple properties which means that you're able to change all settings of the channel specified with cid at once. * @param channel the channel id * @param properties the properties of the channel which should get changed */ async channelEdit(channel, properties = {}) { const cid = Channel_1.TeamSpeakChannel.getId(channel); if (typeof properties.channelName === "string") { if (!this.isSubscribedToEvent("server") || Object.keys(this.channels).length === 0) await this.channelList(); const c = await this.channels[cid]; if (c && properties.channelName === c.name) delete properties.channelName; if (Object.keys(properties).length === 0) return []; } properties.cid = cid; return this.execute("channeledit", properties); } /** * Displays a list of permissions defined for a channel. * @param channel the channel id * @param permsid whether the permsid should be displayed aswell */ channelPermList(channel, permsid = false) { const cid = Channel_1.TeamSpeakChannel.getId(channel); return this.execute("channelpermlist", { cid }, [permsid ? "-permsid" : null]).then(response => { return response.map(perm => { return this.createChannelPermBuilder(cid) .perm(perm.permsid || perm.permid) .value(perm.permvalue); }); }); } channelSetPerm(channel, perm) { const builder = this.createChannelPermBuilder(Channel_1.TeamSpeakChannel.getId(channel)); if (!perm) return builder; return builder.perm(perm.permname).value(perm.permvalue).update(); } /** * Adds a set of specified permissions to a channel. * A permission can be specified by permid or permsid. * @param channel the channel id * @param permissions the permissions to assign * @example * TeamSpeak.channelSetPerms(5, [{ permsid: "i_channel_needed_modify_power", permvalue: 75 }]) */ channelSetPerms(channel, permissions) { return this.execute("channeladdperm", { cid: Channel_1.TeamSpeakChannel.getId(channel) }, permissions); } /** * Removes a set of specified permissions from a channel. * Multiple permissions can be removed at once. * A permission can be specified by permid or permsid. * @param channel the channel id * @param perm the permid or permsid */ channelDelPerm(channel, perm) { const prop = { cid: Channel_1.TeamSpeakChannel.getId(channel) }; prop[typeof perm === "string" ? "permsid" : "permid"] = perm; return this.execute("channeldelperm", prop); } /** * Retrieves a Single Client by the given Client ID * @param client the client id */ getClientById(client) { return this.clientList({ clid: Client_1.TeamSpeakClient.getId(client) }) .then(([client]) => client); } /** * Retrieves a Single Client by the given Client Database ID * @param client the client database Id */ getClientByDbid(client) { return this.clientList({ clientDatabaseId: Client_1.TeamSpeakClient.getDbid(client) }) .then(([client]) => client); } /** * Retrieves a Single Client by the given Client Unique Identifier * @param client the client unique identifier */ getClientByUid(client) { return this.clientList({ clientUniqueIdentifier: Client_1.TeamSpeakClient.getUid(client) }) .then(([client]) => client); } /** * Retrieves a Single Client by the given Client Unique Identifier * @param clientNickname the nickname of the client */ getClientByName(clientNickname) { return this.clientList({ clientNickname }) .then(([client]) => client); } /** * Returns General Info of the Client, requires the Client to be online * @param clients one or more client ids to get */ clientInfo(clients) { return this.execute("clientinfo", { clid: Client_1.TeamSpeakClient.getMultipleIds(clients) }) .then(TeamSpeak.toArray); } /** * Returns the Clients Database List * @param start start offset * @param duration amount of entries which should get retrieved * @param count retrieve the count of entries */ clientDbList(start = 0, duration = 1000, count = true) { return this.execute("clientdblist", { start, duration }, [count ? "-count" : null]) .then(TeamSpeak.toArray); } /** * Returns the Clients Database Info * @param clients one or more client database ids to get */ clientDbInfo(clients) { return this.execute("clientdbinfo", { cldbid: Client_1.TeamSpeakClient.getMultipleDbids(clients) }) .then(TeamSpeak.toArray); } /** * Kicks the Client from the Server * @param client the client id * @param reasonid the reasonid * @param reasonmsg the message the client should receive when getting kicked * @param continueOnError ignore errors */ clientKick(client, reasonid, reasonmsg, continueOnError = false) { const flags = []; if (continueOnError) flags.push("-continueonerror"); return this.execute("clientkick", { clid: Client_1.TeamSpeakClient.getId(client), reasonid, reasonmsg }, flags); } /** * Moves the Client to a different Channel * @param client the client id * @param channel channel id in which the client should get moved * @param cpw the channel password * @param continueOnError ignore errors */ clientMove(client, channel, cpw, continueOnError = false) { const flags = []; if (continueOnError) flags.push("-continueonerror"); return this.execute("clientmove", { clid: Client_1.TeamSpeakClient.getId(client), cid: Channel_1.TeamSpeakChannel.getId(channel), cpw }, flags); } /** * Pokes the Client with a certain message * @param client the client id * @param msg the message the client should receive */ clientPoke(client, msg) { return this.execute("clientpoke", { clid: Client_1.TeamSpeakClient.getId(client), msg }); } /** * Displays a list of permissions defined for a client * @param client the client database id * @param permsid if the permsid option is set to true the output will contain the permission names */ clientPermList(client, permsid = false) { const cldbid = Client_1.TeamSpeakClient.getDbid(client); return this.execute("clientpermlist", { cldbid }, [permsid ? "-permsid" : null]).then(response => { return response.map(perm => { return this.createClientPermBuilder(cldbid) .perm(perm.permsid || perm.permid) .value(perm.permvalue) .skip(perm.permskip) .negate(perm.permnegated); }); }); } clientAddPerm(client, perm) { const builder = this.createClientPermBuilder(Client_1.TeamSpeakClient.getDbid(client)); if (!perm) return builder; if (perm.permskip) builder.skip(perm.permskip); if (perm.permnegated) builder.negate(perm.permnegated); return builder.perm(perm.permname).value(perm.permvalue).update(); } /** * Removes a set of specified permissions from a client. * Multiple permissions can be removed at once. * A permission can be specified by permid or permsid * @param client the client database id * @param perm the permid or permsid */ clientDelPerm(client, perm) { const properties = { cldbid: Client_1.TeamSpeakClient.getDbid(client) }; properties[typeof perm === "string" ? "permsid" : "permid"] = perm; return this.execute("clientdelperm", properties); } /** * Searches for custom client properties specified by ident and value. * The value parameter can include regular characters and SQL wildcard characters (e.g. %). * @param ident the key to search for * @param pattern the search pattern to use */ async customSearch(ident, pattern) { try { return await this.execute("customsearch", { ident, pattern }); } catch (e) { if (e.id !== "1281") return []; //empty result set throw e; } } /** * returns a list of custom properties for the client specified with cldbid. * @param client the Client Database ID which should be retrieved */ async customInfo(client) { try { return await this.execute("custominfo", { cldbid: Client_1.TeamSpeakClient.getDbid(client) }); } catch (e) { if (e.id === "1281") return []; //empty result set throw e; } } /** * Removes a custom property from a client specified by the cldbid. * This requires TeamSpeak Server Version 3.2.0 or newer. * @param client the client Database ID which should be changed * @param ident the key which should be deleted */ customDelete(client, ident) { return this.execute("customdelete", { cldbid: Client_1.TeamSpeakClient.getDbid(client), ident }); } /** * Creates or updates a custom property for client specified by the cldbid. * Ident and value can be any value, and are the key value pair of the custom property. * This requires TeamSpeak Server Version 3.2.0 or newer. * @param client the client database id which should be changed * @param ident the key which should be set * @param value the value which should be set */ customSet(client, ident, value) { return this.execute("customset", { cldbid: Client_1.TeamSpeakClient.getDbid(client), ident, value }); } sendTextMessage(target, targetmode, msg) { let selectedTarget = "0"; if (targetmode === enum_1.TextMessageTargetMode.CLIENT) { selectedTarget = Client_1.TeamSpeakClient.getId(target); } else if (targetmode === enum_1.TextMessageTargetMode.CHANNEL) { selectedTarget = Channel_1.TeamSpeakChannel.getId(target); } return this.execute("sendtextmessage", { target: selectedTarget, targetmode, msg }); } /** * sends a message to a teamspeak channel, * if the client is not in this channel he will move into the channel, send the message and move back after * @param target the target channel to send the message * @param msg the message which should be sent */ async sendChannelMessage(target, msg) { const self = await this.self(); const sourceChannel = self.cid; const cid = Channel_1.TeamSpeakChannel.getId(target); const orders = []; if (sourceChannel !== cid) orders.push(self.move(cid)); orders.push(this