UNPKG

ts3-nodejs-library

Version:
1,344 lines (1,147 loc) 78.7 kB
import { EventEmitter } from "events" import { TeamSpeakQuery } from "./transport/TeamSpeakQuery" import { FileTransfer } from "./transport/FileTransfer" import { QueryResponse } from "./types/QueryResponse" import { ResponseError } from "./exception/ResponseError" import { TeamSpeakClient } from "./node/Client" import { TeamSpeakServer } from "./node/Server" import { TeamSpeakChannel } from "./node/Channel" import { TeamSpeakServerGroup } from "./node/ServerGroup" import { TeamSpeakChannelGroup } from "./node/ChannelGroup" import * as Response from "./types/ResponseTypes" import * as Event from "./types/Events" import * as Props from "./types/PropertyTypes" import { QueryProtocol, ReasonIdentifier, TextMessageTargetMode, TokenType, LogLevel } from "./types/enum" import { Command } from "./transport/Command" import { Context, SelectType } from "./types/context" export * from "./types/enum" /** * missing Query Commands * @todo * channelclientaddperm * channelclientdelperm * servergroupautoaddperm * servergroupautodelperm * tokenadd * tokendelete * tokenlist * tokenuse * clientfind */ declare type NodeType = TeamSpeakClient|TeamSpeakChannel|TeamSpeakChannelGroup|TeamSpeakServer|TeamSpeakServerGroup declare interface NodeConstructable<T> { new(parent: TeamSpeak, props: QueryResponse): T } export interface ConnectionParams { /** the host to connect to (default: 127.0.0.1) */ host: string, /** the query protocol to use (default: @see QueryProtocol ) */ protocol: QueryProtocol, /** the queryport to use (default: raw=10011 ssh=10022) */ queryport: number, /** the server to select upon connect (default: none) */ serverport?: number, /** the username to login with (default: none) */ username?: string, /** the password to use with the login (default: none) */ password?: string, /** the nickname to connect with */ nickname?: string, /** time to wait until a timeout gets fired (default: 10000) */ readyTimeout: number, /** wether a keepalive should get sent (default: true) */ keepAlive: boolean, /** local address the socket should connect from */ localAddress?: string, /** wether it should automatically connect after instanciating (default: true) */ autoConnect?: boolean } export interface TeamSpeak { on(event: "error", listener: (error: Error) => void): this on(event: "ready", listener: () => void): this on(event: "close", listener: (error?: Error) => void): this on(event: "flooding", listener: (error: ResponseError) => void): this on(event: "debug", listener: (event: Event.Debug) => void): this on(event: "clientconnect", listener: (event: Event.ClientConnect) => void): this on(event: "clientdisconnect", listener: (event: Event.ClientDisconnect) => void): this on(event: "tokenused", listener: (event: Event.TokenUsed) => void): this on(event: "textmessage", listener: (event: Event.TextMessage) => void): this on(event: "clientmoved", listener: (event: Event.ClientMoved) => void): this on(event: "serveredit", listener: (event: Event.ServerEdit) => void): this on(event: "channeledit", listener: (event: Event.ChannelEdit) => void): this on(event: "channelcreate", listener: (event: Event.ChannelCreate) => void): this on(event: "channelmoved", listener: (event: Event.ChannelMove) => void): this on(event: "channeldelete", listener: (event: Event.ChannelDelete) => void): this channelClientPermList(cid: number, cldbid: number, permsid: false): Promise<Response.ChannelClientPermListId[]> channelClientPermList(cid: number, cldbid: number, permsid: true): Promise<Response.ChannelClientPermListSid[]> } export class TeamSpeak extends EventEmitter { readonly config: ConnectionParams private clients: Record<string, TeamSpeakClient> = {} private servers: Record<string, TeamSpeakServer> = {} private servergroups: Record<string, TeamSpeakServerGroup> = {} private channels: Record<string, TeamSpeakChannel> = {} private channelgroups: Record<string, TeamSpeakChannelGroup> = {} private priorizeNextCommand: boolean = false private query: TeamSpeakQuery private context: Context = { selectType: SelectType.NONE, selected: 0, events: [] } constructor(config: Partial<ConnectionParams>) { super() this.config = { protocol: QueryProtocol.RAW, host: "127.0.0.1", queryport: config.protocol === QueryProtocol.SSH ? 10022 : 10011, readyTimeout: 10000, keepAlive: true, autoConnect: true, ...config } this.query = new 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?: string) => super.emit("close", e)) this.query.on("error", (e: Error) => super.emit("error", e)) this.query.on("flooding", (e: ResponseError) => super.emit("flooding", e)) this.query.on("debug", (data: Event.Debug) => super.emit("debug", data)) 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: Partial<ConnectionParams>): Promise<TeamSpeak> { 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: number = 1, timeout: number = 2000) { let error: Error|null = null while (attempts === -1 || attempts-- > 0) { 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: number) { return new Promise(fulfill => setTimeout(fulfill, time)) } /** * connects to the TeamSpeak Server */ connect(): Promise<TeamSpeak> { 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: Error) => { removeListeners() this.forceQuit() reject(error) } const closeCallback = (error?: 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() }) } /** handles initial commands after successfully connecting to a TeamSpeak Server */ private handleReady() { const exec: Promise<any>[] = [] if (this.context.login && this.config.protocol === 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 === QueryProtocol.RAW) { exec.push(this.priorize().login(this.config.username, this.config.password)) } if (this.context.selectType !== SelectType.NONE) { if (this.context.selectType === SelectType.PORT) { exec.push(this.priorize().useByPort(this.context.selected, this.context.client_nickname || this.config.nickname)) } else if (this.context.selectType === SelectType.SID) { exec.push(this.priorize().useBySid(this.context.selected, this.context.client_nickname || 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))) this.query.pause(false) 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 */ private evcliententerview(event: QueryResponse) { this.clientList() .then(clients => { const client = clients.find(client => client.clid === event.clid) 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 */ private evclientleftview(event: QueryResponse) { const { clid } = event super.emit("clientdisconnect", { client: (String(clid) in this.clients) ? this.clients[String(clid)!].toJSON() : { clid }, event }) Reflect.deleteProperty(this.clients, String(clid)) } /** * Gets called when a client uses a privilege key * @param event the raw teamspeak event */ private evtokenused(event: QueryResponse) { this.getClientByID(event.clid!) .then(client => { 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 */ private evtextmessage(event: QueryResponse) { this.getClientByID(event.invokerid!) .then(invoker => { 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 */ private evclientmoved(event: QueryResponse) { Promise.all([ this.getClientByID(event.clid!), this.getChannelByID(event.ctid!) ]).then(([client, channel]) => { 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 */ private async evserveredited(event: QueryResponse) { this.getClientByID(event.invokerid!) .then(invoker => { const modified: QueryResponse = {} Object.keys(event) .filter(k => k.startsWith("virtualserver_")) .forEach(<T extends keyof QueryResponse>(k: T) => 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 */ private evchanneledited(event: QueryResponse) { Promise.all([ this.getClientByID(event.invokerid!), this.getChannelByID(event.cid!) ]).then(([invoker, channel]) => { const modified: Partial<QueryResponse> = {} Object.keys(event) .filter(k => k.startsWith("channel_")) .forEach(<T extends keyof QueryResponse>(k: T) => 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 */ private evchannelcreated(event: QueryResponse) { Promise.all([ this.getClientByID(event.invokerid!), this.getChannelByID(event.cid!) ]).then(([invoker, channel]) => { const modified: QueryResponse = {} Object.keys(event) .filter(k => k.startsWith("channel_")) .forEach(<T extends keyof QueryResponse>(k: T) => 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 */ private evchannelmoved(event: QueryResponse) { Promise.all([ this.getClientByID(event.invokerid!), this.getChannelByID(event.cid!), this.getChannelByID(event.cpid!) ]).then(([invoker, channel, parent]) => { 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 */ private evchanneldeleted(event: QueryResponse) { this.getClientByID(event.invokerid!) .then(invoker => 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], { client_nickname: "test" }) */ execute(cmd: string, ...args: TeamSpeakQuery.executeArgs[]) { 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 client_login_name the login name * @param cldbid the database id which should be used */ queryLoginAdd(client_login_name: string, cldbid?: number): Promise<Response.QueryLoginAdd> { return this.execute("queryloginadd", { client_login_name, cldbid }).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 cldbid deletes the querylogin of this client */ queryLoginDel(cldbid: number) { return this.execute("querylogindel", { cldbid }) } /** * 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?: string, start?: number, duration?: number): Promise<Response.QueryLoginList[]> { return this.execute("queryloginlist", { pattern, start, duration }, ["-count"]).then(TeamSpeak.toArray) } /** * Updates your own ServerQuery login credentials using a specified username. * The password will be auto-generated. * @param name */ clientSetServerQueryLogin(name: string): Promise<Response.ClientSetServerQueryLogin> { return this.execute("clientsetserverquerylogin", { client_login_name: name }).then(TeamSpeak.singleResponse) } /** * Change your ServerQuery clients settings using given properties. * @param props the properties which should be changed */ clientUpdate(props: Props.ClientUpdate) { return this.execute("clientupdate", props) .then(this.updateContextResolve({ client_nickname: props.client_nickname ? props.client_nickname : this.context.client_nickname })) } /** * 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: string, id?: number) { return this.execute("servernotifyregister", { event, id }) .then(this.updateContextResolve({ events: [...this.context.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: string, password: string) { 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: SelectType.NONE, client_nickname: this.config.nickname, login: undefined, events: [] })) } /** Displays the servers version information including platform and build number. */ version(): Promise<Response.Version> { return this.execute("version").then(TeamSpeak.singleResponse) } /** * Displays detailed connection information about the server instance including uptime, * number of virtual servers online, traffic information, etc. */ hostInfo(): Promise<Response.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(): Promise<Response.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: Props.InstanceEdit) { return this.execute("instanceedit", properties) } /** returns a list of IP addresses used by the server instance on multi-homed machines. */ bindingList(): Promise<Response.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 client_nickname set nickname when selecting a server */ useByPort(port: number, client_nickname?: string) { return this.execute("use", { port, client_nickname }, ["-virtual"]) .then(this.updateContextResolve({ selectType: SelectType.PORT, selected: port, client_nickname, events: [] })) .catch(this.updateContextReject({ selectType: SelectType.NONE })) } /** * Selects the virtual server specified with the sid to allow further interaction. * @param sid the server id * @param client_nickname set nickname when selecting a server */ useBySid(sid: number, client_nickname?: string) { return this.execute("use", [sid, "-virtual"], { client_nickname }) .then(this.updateContextResolve({ selectType: SelectType.SID, selected: sid, client_nickname, events: [] })) } /** returns information about your current ServerQuery connection including your loginname, etc. */ whoami(): Promise<Response.Whoami> { return this.execute("whoami").then(TeamSpeak.singleResponse) } /** * Displays detailed configuration information about the selected virtual server * including unique ID, number of clients online, configuration, etc. */ serverInfo(): Promise<Response.ServerInfo> { return this.execute("serverinfo").then(TeamSpeak.singleResponse) } /** * Displays the database ID of the virtual server running on the UDP port * @param virtualserver_port the server port where data should be retrieved */ serverIdGetByPort(virtualserver_port: number): Promise<Response.ServerIdGetByPort> { return this.execute("serveridgetbyport", { virtualserver_port }).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: Props.ServerEdit) { 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?: string) { return this.execute("serverprocessstop", { reasonmsg }) } /** * returns detailed connection information about the selected virtual server including uptime, traffic information, etc. */ connectionInfo(): Promise<Response.ServerRequestConnectionInfo> { 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 virtualserver_port is not specified, the server will test for the first unused UDP port * @param properties the server properties */ serverCreate(properties: Props.ServerEdit): Promise<Response.ServerCreate> { let servertoken = "" return this.execute("servercreate", properties) .then(TeamSpeak.singleResponse) .then(({ token, sid }) => { servertoken = token return this.serverList({ virtualserver_id: sid }) }) .then(([server]) => ({ server, token: servertoken })) } /** * deletes the server * @param sid the server id to delete */ serverDelete(sid: number) { return this.execute("serverdelete", { sid }) } /** * 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 sid the server id to start */ serverStart(sid: number) { return this.execute("serverstart", { sid }) } /** * 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 sid 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(sid: number, reasonmsg?: string) { return this.execute("serverstop", { sid, 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: string, type: number = 1): Promise<TeamSpeakServerGroup> { 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 sgid the servergroup id */ serverGroupClientList(sgid: number): Promise<Response.ServerGroupClientList[]> { return this.execute("servergroupclientlist", { sgid }, ["-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 cldbid one or more client database ids which should be added * @param sgid the servergroup id which the client(s) should be added to */ serverGroupAddClient(cldbid: number|number[], sgid: number) { return this.execute("servergroupaddclient", { sgid, cldbid }) } /** * Removes one or more clients from the server group specified with sgid. * @param cldbid one or more client database ids which should be added * @param sgid the servergroup id which the client(s) should be removed from */ serverGroupDelClient(cldbid: number|number[], sgid: number) { return this.execute("servergroupdelclient", { cldbid, sgid }) } /** * displays all server groups the client specified with cldbid is currently residing in * @param cldbid the client database id to check */ serverGroupsByClientId(cldbid: number): Promise<Response.ServerGroupsByClientId[]> { return this.execute("servergroupsbyclientid", { cldbid }).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 cldbid one or more client database ids which should be added * @param sgid one or more servergroup ids which the client should be added to */ clientAddServerGroup(cldbid: number, sgid: number|number[]) { return this.execute("clientaddservergroup", { sgid, cldbid }) } /** * Removes one or more servergroups from the client. * @param cldbid one or more client database ids which should be added * @param sgid one or more servergroup ids which the client should be removed from */ clientDelServerGroup(cldbid: number, sgid: number|number[]) { return this.execute("clientdelservergroup", { cldbid, sgid }) } /** * Deletes the server group. If force is set to 1, the server group will be deleted even if there are clients within. * @param sgid the servergroup id * @param force if set to 1 the servergoup will be deleted even when clients stil belong to this group */ serverGroupDel(sgid: number, force: number = 0) { return this.execute("servergroupdel", {sgid, 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 ssgid the source ServerGroup * @param tsgid 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(ssgid: number, tsgid: number = 0, type: number = 1, name: string = "foo"): Promise<Response.ServerGroupCopy> { return this.execute("servergroupcopy", { ssgid, tsgid, type, name }).then(TeamSpeak.singleResponse) } /** * Changes the name of the server group * @param sgid the servergroup id * @param name new name of the servergroup */ serverGroupRename(sgid: number, name: string) { return this.execute("servergrouprename", { sgid, 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(sgid: number, permsid: boolean = false): Promise<Response.PermList[]> { return this.execute("servergrouppermlist", { sgid }, [permsid ? "-permsid" : null]).then(TeamSpeak.toArray) } /** * Adds a specified permissions to the server group. A permission can be specified by permid or permsid. * @param sgid the ServerGroup id * @param perm the permid or permsid * @param value value of the Permission * @param skip whether the skip flag should be set * @param negate whether the negate flag should be set */ serverGroupAddPerm(sgid: number, perm: string|number, value: number, skip: number = 0, negate: number = 0) { const properties: Record<string, any> = { sgid, permvalue: value, permskip: skip, permnegated: negate } properties[typeof perm === "string" ? "permsid" : "permid"] = perm return this.execute("servergroupaddperm", properties) } /** * Removes a set of specified permissions from the server group. * A permission can be specified by permid or permsid. * @param sgid the servergroup id * @param perm the permid or permsid */ serverGroupDelPerm(sgid: number, perm: string|number) { const properties: Record<string, any> = { sgid } 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: Props.ServerTempPasswordAdd) { 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: string) { 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(): Promise<Response.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: string, properties: Props.ChannelEdit = {}) { properties.channel_name = 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: string, type: number = 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 cid the channel id */ getChannelByID(cid: number): Promise<TeamSpeakChannel|undefined> { return this.channelList({ cid }).then(([channel]) => channel) } /** * Retrieves a Single Channel by the given Channel Name * @param channel_name the name of the channel */ getChannelByName(channel_name: string): Promise<TeamSpeakChannel|undefined> { return this.channelList({ channel_name }).then(([channel]) => channel) } /** * displays a list of channels matching a given name pattern * @param pattern the channel name pattern to search for */ channelFind(pattern: string): Promise<Response.ChannelFind[]> { return this.execute("channelfind", { pattern }) } /** * Displays detailed configuration information about a channel including ID, topic, description, etc. * @param cid the channel id */ channelInfo(cid: number): Promise<Response.ChannelInfo> { return this.execute("channelinfo", { cid }).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 cid the channel id * @param cpid channel parent id * @param order channel sort order */ channelMove(cid: number, cpid: number, order: number = 0) { return this.execute("channelmove", { cid, cpid, 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 cid the channel id * @param force if set to 1 the channel will be deleted even when client are in it */ channelDelete(cid: number, force: number = 0) { return this.execute("channeldelete", { cid, 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 cid the channel id * @param properties the properties of the channel which should get changed */ channelEdit(cid: number, properties: Props.ChannelEdit = {}) { properties.cid = cid return this.execute("channeledit", properties) } /** * Displays a list of permissions defined for a channel. * @param cid the channel id * @param permsid whether the permsid should be displayed aswell */ channelPermList(cid: number, permsid: boolean = false): Promise<Response.PermList[]> { return this.execute("channelpermlist", { cid }, [permsid ? "-permsid" : null]).then(TeamSpeak.toArray) } /** * Adds a set of specified permissions to a channel. * @param cid the channel id * @param perm the permid or permsid * @param value the value which should be set */ channelSetPerm(cid: number, perm: string|number, value: number) { const properties: Record<string, any> = { cid } properties[typeof perm === "string" ? "permsid" : "permid"] = perm properties.permvalue = value return this.execute("channeladdperm", properties) } /** * Adds a set of specified permissions to a channel. * A permission can be specified by permid or permsid. * @param cid the channel id * @param permissions the permissions to assign * @example * TeamSpeak.channelSetPerms(5, [{ permsid: "i_channel_needed_modify_power", permvalue: 75 }]) */ channelSetPerms(cid: number, permissions: any[]) { return this.execute("channeladdperm", { cid }, 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 cid the channel id * @param perm the permid or permsid */ channelDelPerm(cid: number, perm: string|number) { const prop: Record<string, any> = { cid } prop[typeof perm === "string" ? "permsid" : "permid"] = perm return this.execute("channeldelperm", prop) } /** * Retrieves a Single Client by the given Client ID * @param clid the client id */ getClientByID(clid: number): Promise<TeamSpeakClient|undefined> { return this.clientList({ clid }) .then(([client]) => client) } /** * Retrieves a Single Client by the given Client Database ID * @param client_database_id the client database Id */ getClientByDBID(client_database_id: number): Promise<TeamSpeakClient|undefined> { return this.clientList({ client_database_id }) .then(([client]) => client) } /** * Retrieves a Single Client by the given Client Unique Identifier * @param client_unique_identifier the client unique identifier */ getClientByUID(client_unique_identifier: string): Promise<TeamSpeakClient|undefined> { return this.clientList({ client_unique_identifier }) .then(([client]) => client) } /** * Retrieves a Single Client by the given Client Unique Identifier * @param client_nickname the nickname of the client */ getClientByName(client_nickname: string): Promise<TeamSpeakClient|undefined> { return this.clientList({ client_nickname }) .then(([client]) => client) } /** * Returns General Info of the Client, requires the Client to be online * @param clid one or more client ids to get */ clientInfo(clid: number|number[]): Promise<Response.ClientInfo[]> { return this.execute("clientinfo", { clid }).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: number = 0, duration: number = 1000, count: boolean = true): Promise<Response.ClientDBList[]> { return this.execute("clientdblist", { start, duration }, [count ? "-count" : null]).then(TeamSpeak.toArray) } /** * Returns the Clients Database Info * @param cldbid one or more client database ids to get */ clientDBInfo(cldbid: number|number[]): Promise<Response.ClientDBInfo[]> { return this.execute("clientdbinfo", { cldbid }).then(TeamSpeak.toArray) } /** * Kicks the Client from the Server * @param clid the client id * @param reasonid the reasonid * @param reasonmsg the message the client should receive when getting kicked */ clientKick(clid: number, reasonid: ReasonIdentifier, reasonmsg: string) { return this.execute("clientkick", { clid, reasonid, reasonmsg }) } /** * Moves the Client to a different Channel * @param clid the client id * @param cid channel id in which the client should get moved * @param cpw the channel password */ clientMove(clid: number, cid: number, cpw?: string) { return this.execute("clientmove", { clid, cid, cpw }) } /** * Pokes the Client with a certain message * @param clid the client id * @param msg the message the client should receive */ clientPoke(clid: number, msg: string) { return this.execute("clientpoke", { clid, msg }) } /** * Displays a list of permissions defined for a client * @param cldbid the client database id * @param permsid if the permsid option is set to true the output will contain the permission names */ clientPermList(cldbid: number, permsid: boolean = false): Promise<Response.PermList[]> { return this.execute("clientpermlist", { cldbid }, [permsid ? "-permsid" : null]).then(TeamSpeak.toArray) } /** * Adds a set of specified permissions to a client. * Multiple permissions can be added by providing the three parameters of each permission. * A permission can be specified by permid or permsid. * @param cldbid the client database id * @param perm the permid or permsid * @param value value of the permission * @param skip whether the skip flag should be set * @param negate whether the negate flag should be set */ clientAddPerm(cldbid: number, perm: string|number, value: number, skip: number = 0, negate: number = 0) { const properties: Record<string, any> = { cldbid } properties[typeof perm === "string" ? "permsid": "permid"] = perm properties.permvalue = value properties.permskip = skip properties.permnegated = negate return this.execute("clientaddperm", properties) } /** * 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 cldbid the client database id * @param perm the permid or permsid */ clientDelPerm(cldbid: number, perm: string|number) { const properties: Record<string, any> = { cldbid } 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 */ customSearch(ident: string, pattern: string): Promise<Response.CustomSearch> { return this.execute("customsearch", { ident, pattern }).then(TeamSpeak.singleResponse) } /** * returns a list of custom properties for the client specified with cldbid. * @param cldbid the Client Database ID which should be retrieved */ customInfo(cldbid: number): Promise<Response.CustomInfo[]> { return this.execute("custominfo", { cldbid }) } /** * Removes a custom property from a client specified by the cldbid. * This requires TeamSpeak Server Version 3.2.0 or newer. * @param cldbid the client Database ID which should be changed * @param ident the key which should be deleted */ customDelete(cldbid: number, ident: string) { return this.execute("customdelete", { cldbid, 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 cldbid 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(cldbid: number, ident: string, value: string) { return this.execute("customset", { cldbid, ident, value }) } /** * Sends a text message a specified target. * The type of the target is determined by targetmode while target specifies the ID of the recipient, * whether it be a virtual server, a channel or a client. * @param target target client id which should receive the message * @param targetmode targetmode (1: client, 2: channel, 3: server) * @param msg the message the client should receive */ sendTextMessage(target: number, targetmode: TextMessageTargetMode, msg: string) { return this.execute("sendtextmessage", { target, targetmode, msg}) } /** * Retrieves a single ServerGroup by the given ServerGroup ID * @param sgid the servergroup id */ getServerGroupByID(sgid: number): Promise<TeamSpeakServerGroup|undefined> { return this.serverGroupList({ sgid }).then(([group]) => group) } /** * Retrieves a single ServerGroup by the given ServerGroup Name * @param name the servergroup name */ getServerGroupByName(name: string): Promise<TeamSpeakServerGroup|undefined> { return this.serverGroupList({ name }).then(([group]) => group) } /** * Retrieves a single ChannelGroup by the given ChannelGroup ID * @param cgid the channelgroup Id */ getChannelGroupByID(cgid: number): Promise<TeamSpeakChannelGroup|undefined> { return this.channelGroupList({ cgid }).then(([group]) => group) } /** * Retrieves a single ChannelGroup by the given ChannelGroup Name * @param name the channelGroup name */ getChannelGroupByName(name: string): Promise<TeamSpeakChannelGroup|undefined> { return this.channelGroupList({ name }) .then(([group]) => group) } /** * Sets the channel group of a client * @param cgid the channelgroup which the client should get assigned * @param cid the channel in which the client should be assigned the group * @param cldbid the client database id which should be added to the group */ setClientChannelGroup(cgid: number, cid: number, cldbid: number) { return this.execute("setclientchannelgroup", { cgid, cldbid, cid }) } /** * Deletes the channel group. If force is set to 1, the channel group will be deleted even if there are clients within. * @param cgid the channelgroup id * @param force if set to 1 the channelgroup will be deleted even when clients are in it */ deleteChannelGroup(cgid: number, force: number = 0) { return this.execute("channelgroupdel", { cgid, force }) } /** * Creates a copy of the channel group. * If tcgid is set to 0, the server will create a new group. * To overwrite an existing group, simply set tcgid to the ID of a designated target group. * If a target group is set, the name parameter will be ignored. * @param scgid the source channelgroup * @param tcgid the target channelgroup (0 to create a new group) * @param type the type of the group (0 = Template Group | 1 = Normal Group) * @param name name of the goup */ channelGroupCopy(scgid: number, tcgid: number = 0, type: number = 1, name: string = "foo"): Promise<Response.ChannelGroupCopy> { return this.execute("channelgroupcopy", { scgid, tcgid, type, name }).then(TeamSpeak.singleResponse) } /** * Changes the name of the channel group * @param cgid the channelgroup id to rename * @param name new name of the ghannelgroup */ channelGroupRename(cgid: number, name: string) { return this.execute("channelgrouprename", { cgid, name }) } /** * Displays a list of permissions assigned to the channel group specified with cgid. * @param cgid the channelgroup id to list * @param permsid if the permsid option is set to true the output will contain the permission names. */ channelGroupPermList(cgid: number, permsid: boolean = false): Promise<Response.PermList[]> { return this.execute("channelgrouppermlist", { cgid }, [permsid ? "-permsid" : null]).then(TeamSpeak.toArray) } /** * Adds a specified permissions to the channel group. A permission can be specified by permid or permsid. * @param cgid the channelgroup id * @param perm the permid or permsid * @param value value of the permission * @param skip whether the skip flag should be set * @param negate whether the negate flag should be set */ channelGroupAddPerm(cgid: number, perm: string|number, value: number, skip: number = 0, negate: number = 0) { const properties: Record<string, any> = { cgid } properties[typeof perm === "string" ? "permsid": "permid"] = perm properties.permvalue = value properties.permskip = skip properties.permnegated = negate return this.execute("channelgroupaddperm", properties) } /** * Removes a set of specified permissions from the channel group. A permission can be specified by permid or permsid. * @param cgid the channelgroup id * @param perm the permid or permsid */ channelGroupDelPerm(cgid: number, perm: string|number) { const properties: Record<string, any> = { cgid } properties[typeof perm === "string" ? "permsid" : "permid"] = perm return this.execute("channelgroupdelperm", properties) } /** * Displays the IDs of all clients currently residing in the channel group. * @param cgid the channelgroup id * @param cid the channel id * @param cldbid the client database id to filter */ channelGroupClientList(cgid: number, cid?: number, cldbid?: number): Promise<Response.ChannelGroupClientList[]> { const properties: Record<string, any> = { cgid } if (typeof cid === "number") properties.cid = cid if (typeof cldbid === "number") properties.cldbid = cldbid return this.execute("channelgroupclientlist", properties).then(TeamSpeak.toArray) } /** * Displays all permissions assigned to a client for the channel specified with cid. * If permid is set to 0, all permissions will be displayed. * A permission can be specified by permid or permsid. * @param cldbid the client database id * @param cid one or more permission names * @param permid one or more permission ids * @param permsid one or more permission names */ permOverview(cldbid: n