using System.Collections.Generic; using System.Linq; using System.Text; namespace axXez.TS3.Protocol { public partial class QueryClient { /// /// Authenticates with the TeamSpeak 3 Server instance using the given ServerQuery credentials. /// /// Required permission: b_serverquery_login /// The ServerQuery login name (client_login_name). /// The ServerQuery login password (client_login_password). /// true on success, false on error. public bool Login(string loginName, string password) => SendCommand($"login client_login_name={loginName.ToTsFormat()} client_login_password={password.ToTsFormat()}"); /// /// Deselects the active virtual server and logs out from the server instance. /// /// Required permission: b_serverquery_login /// true on success, false on error. public bool Logout() => SendCommand($"logout"); /// /// Displays version, build number, and platform of the server. /// /// /// A object, or null on error. public VersionInfo Version() { if (SendCommand($"version", out QueryResponse res)) return res.Get(); return null; } /// /// Displays detailed connection info about the server instance including uptime, number of /// virtual servers online, and traffic statistics. /// /// Required permission: b_serverinstance_info_view /// A object, or null on error. public HostInfo Hostinfo() { if (SendCommand($"hostinfo", out QueryResponse res)) return res.Get(); return null; } /// /// Displays the server instance configuration including database revision, file transfer /// port, and default group IDs. /// /// Required permission: b_serverinstance_info_view /// An object, or null on error. public InstanceInfo InstanceInfo() { if (SendCommand($"instanceinfo", out QueryResponse res)) return res.Get(); return null; } /// /// Changes the server instance configuration using the given properties. /// /// Required permission: b_serverinstance_modify_settings /// Dictionary of instance property key-value pairs to update. /// true on success, false on error. public bool InstanceEdit(Dictionary properties = null) => SendCommand("instanceedit", properties); /// /// Displays a list of IP addresses used by the server instance on multi-homed machines. /// /// Required permission: b_serverinstance_binding_list /// /// The subsystem to list bindings for: "voice", "query", or /// "filetransfer". Defaults to "voice" when empty. /// /// A list of dictionaries containing IP entries, or null on error. public List> BindingList(string subsystem = "") { string option = !string.IsNullOrEmpty(subsystem) ? $"subsystem={subsystem}" : ""; if (SendCommand($"bindinglist {option}", out QueryResponse res)) return res.ToDictionaryList(); return null; } /// /// Selects the virtual server specified by or . /// The ServerQuery client appears on the server like a real client, but cannot send or receive voice. /// /// Required permission: b_virtualserver_select /// The virtual server database ID (sid). Use -1 to select by port instead. /// The virtual server UDP port (port). Used when is -1. /// /// When true, sends the -virtual flag. Starts the server in virtual mode /// (allows configuration without clients connecting). /// /// /// Sets the ServerQuery client's display name on the virtual server (client_nickname). /// /// true on success, false on error. public bool Use(int serverID = -1, int port = -1, bool virtualServer = false, string clientNickname = null) { var sb = new StringBuilder(); if (serverID != -1) sb.Append($"sid={serverID} "); if (port != -1) sb.Append($"port={port} "); if (virtualServer) sb.Append("-virtual "); if (!string.IsNullOrEmpty(clientNickname)) sb.Append($"client_nickname={clientNickname.ToTsFormat()} "); return SendCommand($"use {sb}"); } /// /// Displays a list of virtual servers including their ID, status, and number of clients online. /// /// Required permission: b_serverinstance_virtualserver_list /// /// When true, sends -short to exclude clients online, max clients, uptime, /// name, autostart, and machine ID fields. /// /// When true, sends -all to list all servers regardless of machine ID. /// When true, sends -onlyoffline to list only offline servers. /// When true, sends -uid to include the unique identifier. /// A list of objects, or null on error. public List ServerList(bool simple = false, bool all = false, bool onlyOffline = false, bool uid = false) { var sb = new StringBuilder(); if (simple) sb.Append("-short "); if (all) sb.Append("-all "); if (onlyOffline) sb.Append("-onlyoffline "); if (uid) sb.Append("-uid "); if (SendCommand($"serverlist {sb}", out QueryResponse res)) return res.GetAll(); return null; } /// /// Displays the database ID of the virtual server running on the given UDP port. /// /// Required permission: b_serverinstance_virtualserver_list /// The virtual server's UDP port (virtualserver_port). /// The server database ID, or -1 on error. public int GetServerIDByPort(int port) { if (SendCommand($"serveridgetbyport virtualserver_port={port}", out QueryResponse res)) return res.Get("server_id"); return -1; } /// /// Deletes the virtual server with the given ID. The server must be in a stopped state. /// /// Required permission: b_virtualserver_delete /// The virtual server database ID (sid). /// true on success, false on error. public bool DeleteServer(int ID) => SendCommand($"serverdelete sid={ID}"); /// /// Creates a new virtual server and returns its ID, port, and initial administrator privilege key. /// If virtualserver_port is not specified in , the first /// available UDP port starting from 9987 is used. /// /// Required permission: b_virtualserver_create /// The name of the new virtual server (virtualserver_name). /// Additional server properties to set on creation. /// A object with sid, port, and token, or null on error. public ServerCreatedInfo CreateServer(string name, EditServerProperties properties) { if (SendCommand($"servercreate virtualserver_name={TsEncoding.Escape(name)}", properties.changes, out QueryResponse res)) return res.Get(); return null; } /// /// Starts the virtual server with the given ID. /// /// Required permissions: b_virtualserver_start_any, b_virtualserver_start /// The virtual server database ID (sid). /// true on success, false on error. public bool StartServer(int ID) => SendCommand($"serverstart sid={ID}"); /// /// Stops the virtual server with the given ID. Optionally sends a reason message to /// connected clients before they are disconnected. /// /// Required permissions: b_virtualserver_stop_any, b_virtualserver_stop /// The virtual server database ID (sid). /// /// Text message sent to all connected clients before disconnect (reasonmsg). /// Leave empty to send no message. /// /// true on success, false on error. public bool StopServer(int ID, string reasonMsg = "") { string option = !string.IsNullOrEmpty(reasonMsg) ? $"reasonmsg={reasonMsg.ToTsFormat()}" : ""; return SendCommand($"serverstop sid={ID} {option}"); } /// /// Stops the entire TeamSpeak 3 Server instance by shutting down the process. Optionally /// sends a reason message to all connected clients before disconnect. /// /// Required permission: b_serverinstance_stop /// /// Text message sent to all connected clients before disconnect (reasonmsg). /// Leave empty to send no message. /// /// true on success, false on error. public bool StopServerProcess(string reasonMsg = "") { string option = !string.IsNullOrEmpty(reasonMsg) ? $"reasonmsg={reasonMsg.ToTsFormat()}" : ""; return SendCommand($"serverprocessstop {option}"); } /// /// Displays detailed configuration of the currently selected virtual server. /// /// Required permission: b_virtualserver_info_view /// A object, or null on error. public ServerInfo ServerInfo() { if (SendCommand($"serverinfo", out QueryResponse res)) return res.Get(); return null; } /// /// Displays detailed connection info of the selected virtual server including uptime and traffic. /// /// Required permission: b_virtualserver_connectioninfo_view /// A object, or null on error. public ConnectionInfo ServerRequestConnectionInfo() { if (SendCommand($"serverrequestconnectioninfo", out QueryResponse res)) return res.Get(); return null; } /// /// Changes the selected virtual server's configuration using the given properties. /// /// Requires various b_virtualserver_modify_* permissions. /// Server properties to modify. /// true on success, false on error. public bool EditServer(EditServerProperties properties) => SendCommand("serveredit", properties.changes); /// /// Displays a list of server groups available on the selected virtual server. /// /// /// Required permissions: b_serverinstance_modify_querygroup, /// b_serverinstance_modify_templates, b_virtualserver_servergroup_list /// /// A list of objects, or null on error. public List ListServerGroups() { if (SendCommand($"servergrouplist", out QueryResponse res)) return res.GetAll(); return null; } /// /// Creates a new server group with the given name and returns its ID. /// /// Required permission: b_virtualserver_servergroup_create /// The name of the new server group (name). /// The new group ID (sgid), or -1 on error. public int AddServerGroup(string name) { if (SendCommand($"servergroupadd name={name.ToTsFormat()}", out QueryResponse res)) return res.Get("sgid"); return -1; } /// /// Creates a new server group with the given name and type, and returns its ID. /// /// Required permission: b_virtualserver_servergroup_create /// The name of the new server group (name). /// /// The group database type (type): "0" = template, "1" = regular, /// "2" = query. Default is 1. /// /// The new group ID (sgid), or -1 on error. public int AddServerGroup(string name, string type) { if (SendCommand($"servergroupadd name={name.ToTsFormat()} type={type}", out QueryResponse res)) return res.Get("sgid"); return -1; } /// /// Deletes the server group with the given ID. /// /// Required permission: b_virtualserver_servergroup_delete /// The server group ID (sgid). /// /// Set to 1 to delete even if clients are assigned to the group (force). /// /// true on success, false on error. public bool DeleteServerGroup(int sgid, int force = 0) => SendCommand($"servergroupdel sgid={sgid} force={force}"); /// /// Creates a copy of the server group into . /// If is 0, a new group is created. If a target group is set, the /// parameter is ignored. /// /// /// Required permissions: b_virtualserver_servergroup_create, /// i_group_modify_power, i_group_needed_modify_power /// /// The source server group ID (ssgid). /// The target server group ID (tsgid). Use 0 to create a new group. /// The name of the new group (name). Ignored if is set. /// /// The group database type (type): "0" = template, "1" = regular, "2" = query. /// /// The new group ID (sgid), or -1 on error. public int CopyServerGroup(int ssgid, int tsgid, string name, string type) { if (SendCommand($"servergroupcopy ssgid={ssgid} tsgid={tsgid} name={name.ToTsFormat()} type={type}", out QueryResponse res)) return res.Get("sgid"); return -1; } /// /// Changes the name of the server group with the given ID. /// /// /// Required permissions: i_group_modify_power, i_group_needed_modify_power /// /// The server group ID (sgid). /// The new name for the group (name). /// true on success, false on error. public bool SetServerGroupName(int sgid, string name) => SendCommand($"servergrouprename sgid={sgid} name={name.ToTsFormat()}"); /// /// Displays a list of permissions assigned to the given server group. /// /// Required permission: b_virtualserver_servergroup_permission_list /// The server group ID (sgid). /// /// When true, sends -permsid to include permission name strings instead of /// numeric IDs in the response. /// /// A list of objects, or null on error. public List ListServerGroupPermissions(int sgid, bool permsid = false) { if (SendCommand($"servergrouppermlist sgid={sgid} {(permsid ? "-permsid" : "")}", out QueryResponse res)) return res.GetAll(); return null; } /// /// Adds a permission to the given server group. /// /// /// Required permissions: i_group_modify_power, i_group_needed_modify_power, /// i_permission_modify_power /// /// The server group ID (sgid). /// The numeric permission ID (permid). /// The permission value (permvalue). /// Set to 1 to negate the permission (permnegated). /// Set to 1 to skip the permission check (permskip). /// true on success, false on error. public bool AddPermissionToServerGroup(int sgid, int permid, int permValue, int permNegated, int permSkip) => SendCommand($"servergroupaddperm sgid={sgid} permid={permid} permvalue={permValue} permnegated={permNegated} permskip={permSkip}"); /// /// Removes a permission from the given server group. /// /// /// Required permissions: i_group_modify_power, i_group_needed_modify_power, /// i_permission_modify_power /// /// The server group ID (sgid). /// The numeric permission ID to remove (permid). /// true on success, false on error. public bool RemovePermissionFromServerGroup(int sgid, int permid) => SendCommand($"servergroupdelperm sgid={sgid} permid={permid}"); /// /// Adds a client to the given server group. /// /// /// Required permissions: i_group_member_add_power, i_group_needed_member_add_power /// /// The server group ID (sgid). /// The client's database ID (cldbid). /// true on success, false on error. public bool AddClientToServerGroup(int sgid, int clientDBID) => SendCommand($"servergroupaddclient sgid={sgid} cldbid={clientDBID}"); /// /// Removes a client from the given server group. /// /// /// Required permissions: i_group_member_remove_power, i_group_needed_member_remove_power /// /// The server group ID (sgid). /// The client's database ID (cldbid). /// true on success, false on error. public bool RemoveClientFromServerGroup(int sgid, int clientDBID) => SendCommand($"servergroupdelclient sgid={sgid} cldbid={clientDBID}"); /// /// Displays the database IDs of all clients currently in the given server group. /// /// Required permission: b_virtualserver_servergroup_client_list /// The server group ID (sgid). /// /// When true, sends -names to also include last nickname and UID in the response. /// Note: extra fields are not reflected in the returned List<int>. /// /// A list of client database IDs (cldbid), or null on error. public List ListClientsWithServerGroup(int sgid, bool names = false) { string option = names ? "-names" : ""; if (SendCommand($"servergroupclientlist sgid={sgid} {option}", out QueryResponse res)) return res.GetAll("cldbid"); return null; } /// /// Displays all server groups the client with the given database ID is currently in. /// /// /// The client's database ID (cldbid). /// A list of server group IDs (sgid), or null on error. public List GetServerGroupsByClientID(int clientDBID) { if (SendCommand($"servergroupsbyclientid cldbid={clientDBID}", out QueryResponse res)) return res.GetAll("sgid"); return null; } /// /// Globally adds a permission to ALL regular server groups of the given auto-update type on /// all virtual servers. The target groups are identified by their /// i_group_auto_update_type permission value. /// /// Required permission: b_permission_modify_power_ignore /// /// The auto-update type value (sgtype), NOT a group ID: /// 10=Channel Guest, 15=Server Guest, 20=Query Guest, /// 25=Channel Voice, 30=Server Normal, 35=Channel Operator, /// 40=Channel Admin, 45=Server Admin, 50=Query Admin. /// /// The numeric permission ID (permid). /// The permission value (permvalue). /// Set to 1 to negate the permission (permnegated). /// Set to 1 to skip the permission check (permskip). /// true on success, false on error. public bool AutoAddPermissionForServerGroup(int sgtype, int permid, int permValue, int permNegated, int permSkip) => SendCommand($"servergroupautoaddperm sgtype={sgtype} permid={permid} permvalue={permValue} permnegated={permNegated} permskip={permSkip}"); /// /// Globally removes a permission from ALL regular server groups of the given auto-update type /// on all virtual servers. /// /// Required permission: b_permission_modify_power_ignore /// /// The auto-update type value (sgtype), NOT a group ID. /// See for valid values. /// /// The numeric permission ID to remove (permid). /// true on success, false on error. public bool AutoDeletePermissionForServerGroup(int sgtype, int permid) => SendCommand($"servergroupautodelperm sgtype={sgtype} permid={permid}"); /// /// Creates and displays a snapshot of the selected virtual server containing all settings, /// groups, and known client identities. The data can be used with /// to restore the server. /// /// Required permission: b_virtualserver_snapshot_create /// /// When set, the snapshot data will be encrypted with this password (password). /// The same password must be provided when deploying the snapshot. /// /// /// A dictionary with version and data keys (and salt if a password was set), /// or null on error. /// public Dictionary CreateServerSnapshot(string password = "") { string option = !string.IsNullOrEmpty(password) ? $"password={password.ToTsFormat()}" : ""; if (SendCommand($"serversnapshotcreate {option}", out QueryResponse res)) return res.ToDictionary(); return null; } /// /// Restores the selected virtual server from a previously created snapshot. /// Pass the raw snapshot data string as returned by /// (e.g. "version=3 data=KLUv/..." or "version=3 salt=... data=..." for encrypted). /// /// Required permission: b_virtualserver_snapshot_deploy /// /// The raw snapshot data to restore from. Contains the full output of /// as a single string. /// /// /// When true, sends -mapping flag. The response will include old-to-new /// channel ID mappings (ocid/ncid). /// /// /// When true, sends -keepfiles flag. Channels present in both the virtual /// server and the snapshot will have their files preserved. /// /// /// The decryption password (password) if the snapshot was created with one. /// /// /// A dictionary (empty on normal deploy, or with channel mappings if /// is true), or null on error. /// public Dictionary DeployServerSnapshot(string snapshot, bool mapping = false, bool keepFiles = false, string password = "") { var sb = new StringBuilder(); if (mapping) sb.Append("-mapping "); if (keepFiles) sb.Append("-keepfiles "); if (!string.IsNullOrEmpty(password)) sb.Append($"password={password.ToTsFormat()} "); if (SendCommand($"serversnapshotdeploy {sb}{snapshot}", out QueryResponse res)) return res.ToDictionary(); return null; } /// /// Registers for a specified category of event notifications. The server will send /// notification messages for each matching event in the ServerQuery client's view. /// /// Required permission: b_virtualserver_notify_register /// /// The event category to subscribe to (event): /// "server", "channel", "textserver", "textchannel", /// or "textprivate". /// /// /// Limits notifications to a specific channel (id). Required for /// "channel" event type; use -1 to omit. /// /// true on success, false on error. public bool ServerNotifyRegister(string eventType, int channelID = -1) { string option = channelID != -1 ? $"id={channelID}" : ""; return SendCommand($"servernotifyregister event={eventType} {option}"); } /// /// Unregisters from all event notifications previously registered with /// . /// /// Required permission: b_virtualserver_notify_unregister /// true on success, false on error. public bool ServerNotifyUnregister() => SendCommand($"servernotifyunregister"); /// /// Sends a text message to the specified target. /// /// /// Required permissions: i_client_private_textmessage_power, /// i_client_needed_private_textmessage_power, /// b_client_server_textmessage_send, b_client_channel_textmessage_send /// /// /// The target mode (targetmode): 1 = client, 2 = channel, 3 = server. /// /// /// The target client ID (target). Ignored when is 2 or 3. /// /// The message text (msg). /// true on success, false on error. public bool SendTextMessage(MessageTargetMode targetmode, int target, string text) => SendCommand($"sendtextmessage targetmode={(int)targetmode} target={target} msg={text.ToTsMessageFormat()}"); /// /// Displays a specified number of entries from the server log. /// /// /// Required permissions: b_serverinstance_log_view, b_virtualserver_log_view /// /// Number of log lines to return (lines), max 100. Leave empty for default. /// Set to "1" to reverse the line order (reverse). /// Set to "1" to read from the master instance log instead of the virtual server log (instance). /// Number of lines to skip from the beginning (begin_pos). Leave empty to start from the current end. /// A list of log entry dictionaries, or null on error. public List> ViewLog(string lines = "", string reverse = "", string instance = "", string beginPos = "") { var sb = new StringBuilder(); if (!string.IsNullOrEmpty(lines)) sb.Append($"lines={lines} "); if (!string.IsNullOrEmpty(reverse)) sb.Append($"reverse={reverse} "); if (!string.IsNullOrEmpty(instance)) sb.Append($"instance={instance} "); if (!string.IsNullOrEmpty(beginPos)) sb.Append($"begin_pos={beginPos} "); if (SendCommand($"logview {sb}", out QueryResponse res)) return res.ToDictionaryList(); return null; } /// /// Writes a custom entry into the server log. /// /// /// Required permissions: b_serverinstance_log_add, b_virtualserver_log_add /// /// /// The log level (loglevel): "1" = error, "2" = warning, /// "3" = debug, "4" = info. /// /// The log message text (logmsg). /// true on success, false on error. public bool AddLog(string loglevel, string text) => SendCommand($"logadd loglevel={loglevel} logmsg={text.ToTsFormat()}"); /// /// Sends a global text message to all clients on all virtual servers in the instance. /// Alias for . /// /// Required permission: b_serverinstance_textmessage_send /// The message text. /// true on success, false on error. public bool SendGlobalTextMessage(string text) => GM(text); /// /// Sends a global text message to all clients on all virtual servers in the instance. /// /// Required permission: b_serverinstance_textmessage_send /// The message text (msg). /// true on success, false on error. public bool GM(string text) => SendCommand($"gm msg={text.ToTsMessageFormat()}"); /// /// Displays a list of channels on the current virtual server. /// Each flag adds extra fields to the response. /// /// Required permission: b_virtualserver_channel_list /// When true, sends -topic to include channel_topic. /// When true, sends -secondsempty to include seconds_empty. /// When true, sends -flags to include default/password/permanent/semi-permanent flags. /// When true, sends -voice to include codec, codec quality, and talk power. /// When true, sends -limits to include total_clients_family. /// When true, sends -icon to include channel_icon_id. /// When true, sends -banners to include banner URL and mode. /// A list of objects, or null on error. public List ListChannels(bool secondsEmpty = false, bool topic = false, bool flags = false, bool voice = false, bool limits = false, bool icon = false, bool banners = false) { var sb = new StringBuilder(); if (topic) sb.Append("-topic "); if (secondsEmpty) sb.Append("-secondsempty "); if (flags) sb.Append("-flags "); if (voice) sb.Append("-voice "); if (limits) sb.Append("-limits "); if (icon) sb.Append("-icon "); if (banners) sb.Append("-banners "); if (SendCommand($"channellist {sb}", out QueryResponse res)) return res.GetAll(); return null; } /// /// Displays detailed configuration of the given channel including topic, description, and codec. /// /// Required permission: b_channel_info_view /// The channel ID (cid). /// A object with ID set, or null on error. public ChannelInfo GetChannelInfo(int channelID) { if (SendCommand($"channelinfo cid={channelID}", out QueryResponse res)) { var ch = res.Get(); if (ch != null) ch.Update("cid", channelID.ToString()); return ch; } return null; } /// /// Displays a list of channels matching the given name pattern (case-insensitive). /// /// Required permission: b_virtualserver_channel_search /// /// Pattern that must be part of the channel name (pattern). Case-insensitive. /// Leave empty to match all channels. /// /// A list of matching channel IDs (cid), or null on error. public List ChannelFind(string pattern = "") { string option = !string.IsNullOrEmpty(pattern) ? $"pattern={pattern.ToTsFormat()}" : ""; if (SendCommand($"channelfind {option}", out QueryResponse res)) return res.GetAll("cid"); return null; } /// /// Moves a channel to a new parent channel. /// /// /// Required permissions: i_channel_min_depth, i_channel_max_depth, /// b_channel_modify_parent, b_channel_modify_sortorder /// /// The channel to move (cid). /// The new parent channel ID (cpid). /// /// Sort order: ID of the sibling channel this channel will be placed directly below (order). /// Use "0" to place it as the first child of the new parent. /// Leave empty to omit. /// /// true on success, false on error. public bool MoveChannel(int channelID, int targetID, string order = "") { string option = !string.IsNullOrEmpty(order) ? $"order={order}" : ""; return SendCommand($"channelmove cid={channelID} cpid={targetID} {option}"); } /// /// Creates a new channel and returns its ID. /// /// Requires various b_channel_create_* permissions. /// The channel name (channel_name). /// Additional channel properties to set on creation. /// The new channel ID (cid), or -1 on error. public int CreateChannel(EditChannelProperties properties) { if (SendCommand("channelcreate", properties.changes, out QueryResponse res)) return res.Get("cid"); return -1; } /// /// Deletes the given channel. If clients are present, use to kick /// them to the default channel. /// /// /// Required permissions: b_channel_delete_permanent, b_channel_delete_semi_permanent, /// b_channel_delete_temporary, b_channel_delete_flag_force /// /// The channel ID (cid). /// /// Set to "1" to delete even if clients are in the channel (force). /// Clients are kicked to the default channel. /// /// true on success, false on error. public bool DeleteChannel(int channelID, string force = "0") => SendCommand($"channeldelete cid={channelID} force={force}"); /// /// Changes a channel's configuration. All properties in are applied at once. /// /// Requires various b_channel_modify_* and i_channel_* permissions. /// The channel ID (cid). /// Channel properties to modify. /// true on success, false on error. public bool EditChannel(int channelID, EditChannelProperties properties) => SendCommand($"channeledit cid={channelID}", properties.changes); /// /// Displays a list of channel groups available on the selected virtual server. /// /// /// Required permissions: b_virtualserver_channelgroup_list, /// b_serverinstance_modify_templates /// /// A list of objects, or null on error. public List ListChannelGroups() { if (SendCommand($"channelgrouplist", out QueryResponse res)) return res.GetAll(); return null; } /// /// Creates a new channel group and returns its ID. /// /// Required permission: b_virtualserver_channelgroup_create /// The name of the new channel group (name). /// The new group ID (cgid), or -1 on error. public int AddChannelGroup(string groupName) { if (SendCommand($"channelgroupadd name={groupName.ToTsFormat()}", out QueryResponse res)) return res.Get("cgid"); return -1; } /// /// Creates a new channel group with the given type and returns its ID. /// /// Required permission: b_virtualserver_channelgroup_create /// The name of the new channel group (name). /// /// The group database type (type): "0" = template, "1" = regular, /// "2" = query. Default is 1. /// /// The new group ID (cgid), or -1 on error. public int AddChannelGroup(string groupName, string type) { if (SendCommand($"channelgroupadd name={groupName.ToTsFormat()} type={type}", out QueryResponse res)) return res.Get("cgid"); return -1; } /// /// Deletes the given channel group. /// /// Required permission: b_virtualserver_channelgroup_delete /// The channel group ID (cgid). /// /// Set to 1 to delete even if clients are assigned to the group (force). /// /// true on success, false on error. public bool DeleteChannelGroup(int groupID, int force = 0) => SendCommand($"channelgroupdel cgid={groupID} force={force}"); /// /// Creates a copy of channel group into . /// If is 0, a new group is created. If a target group is set, the /// parameter is ignored. /// /// /// Required permissions: b_virtualserver_channelgroup_create, /// i_group_modify_power, i_group_needed_modify_power /// /// The source channel group ID (scgid). /// The target channel group ID (tcgid). Use 0 to create a new group. /// The name for the new group (name). Ignored if is set. /// /// The group database type (type): "0" = template, "1" = regular, "2" = query. /// /// The new group ID (cgid), or -1 on error. public int CopyChannelGroup(int scgid, int tsgid, string name, string type) { if (SendCommand($"channelgroupcopy scgid={scgid} tcgid={tsgid} name={name.ToTsFormat()} type={type}", out QueryResponse res)) return res.Get("cgid"); return -1; } /// /// Changes the name of the given channel group. /// /// /// Required permissions: i_group_modify_power, i_group_needed_modify_power /// /// The channel group ID (cgid). /// The new name for the group (name). /// true on success, false on error. public bool SetChannelGroupName(int groupID, string name) => SendCommand($"channelgrouprename cgid={groupID} name={name.ToTsFormat()}"); /// /// Adds a permission to the given channel group. /// /// /// Required permissions: i_group_modify_power, i_group_needed_modify_power, /// i_permission_modify_power /// /// The channel group ID (cgid). /// The numeric permission ID (permid). /// The permission value (permvalue). /// true on success, false on error. public bool AddPermissionToChannelGroup(int groupID, int permid, string permValue) => SendCommand($"channelgroupaddperm cgid={groupID} permid={permid} permvalue={permValue}"); /// /// Displays a list of permissions assigned to the given channel group. /// /// Required permission: b_virtualserver_channelgroup_permission_list /// The channel group ID (cgid). /// /// When true, sends -permsid to include permission name strings instead of /// numeric IDs in the response. /// /// A list of objects, or null on error. public List ListChannelGroupPermissions(int groupID, bool permsid = false) { string option = permsid ? "-permsid" : ""; if (SendCommand($"channelgrouppermlist cgid={groupID} {option}", out QueryResponse res)) return res.GetAll(); return null; } /// /// Removes a permission from the given channel group. /// /// /// Required permissions: i_group_modify_power, i_group_needed_modify_power, /// i_permission_modify_power /// /// The channel group ID (cgid). /// The numeric permission ID to remove (permid). /// true on success, false on error. public bool RemovePermissionFromChannelGroup(int groupID, int permid) => SendCommand($"channelgroupdelperm cgid={groupID} permid={permid}"); /// /// Displays all client/channel/group assignments for channel groups. All parameters are /// optional — omit all to return every assignment on the server. /// /// Required permission: b_virtualserver_channelgroup_client_list /// Filter by channel ID (cid). Use -1 to omit. /// Filter by client database ID (cldbid). Use -1 to omit. /// Filter by channel group ID (cgid). Use -1 to omit. /// /// A list of tuples with (ChannelID, ClientDBID, ChannelGroupID), or null on error. /// public List<(int ChannelID, int ClientDBID, int ChannelGroupID)> ListClientsByChannelGroup(int channelID = -1, int clientDBID = -1, int groupID = -1) { var sb = new StringBuilder(); if (channelID != -1) sb.Append($"cid={channelID} "); if (clientDBID != -1) sb.Append($"cldbid={clientDBID} "); if (groupID != -1) sb.Append($"cgid={groupID} "); if (SendCommand($"channelgroupclientlist {sb}", out QueryResponse res)) return res.Entries.Select(x => (x.GetValue("cid"), x.GetValue("cldbid"), x.GetValue("cgid"))).ToList(); return null; } /// /// Sets the channel group of a client in a specific channel. /// /// /// Required permissions: i_group_member_add_power, i_group_needed_member_add_power, /// i_group_member_remove_power, i_group_needed_member_remove_power /// /// The channel group ID to assign (cgid). /// The channel in which to set the group (cid). /// The client's database ID (cldbid). /// true on success, false on error. public bool SetClientChannelGroup(int groupID, int channelID, int clientDBID) => SendCommand($"setclientchannelgroup cgid={groupID} cid={channelID} cldbid={clientDBID}"); /// /// Displays a list of permissions defined for the given channel. /// /// Required permission: b_virtualserver_channel_permission_list /// The channel ID (cid). /// /// When true, sends -permsid to include permission name strings instead of /// numeric IDs in the response. /// /// A list of objects, or null on error. public List ListChannelPermissions(int channelID, bool permsid = false) { string option = permsid ? "-permsid" : ""; if (SendCommand($"channelpermlist cid={channelID} {option}", out QueryResponse res)) return res.GetAll(); return null; } /// /// Adds a permission to the given channel. /// /// /// Required permissions: i_group_modify_power, i_group_needed_modify_power, /// i_permission_modify_power /// /// The channel ID (cid). /// The numeric permission ID (permid). /// The permission value (permvalue). /// true on success, false on error. public bool AddChannelPermission(int channelID, int permid, string permvalue) => SendCommand($"channeladdperm cid={channelID} permid={permid} permvalue={permvalue}"); /// /// Removes a permission from the given channel. /// /// /// Required permissions: i_group_modify_power, i_group_needed_modify_power, /// i_permission_modify_power /// /// The channel ID (cid). /// The numeric permission ID to remove (permid). /// true on success, false on error. public bool DeleteChannelPermission(int channelID, int permid) => SendCommand($"channeldelperm cid={channelID} permid={permid}"); /// /// Displays a list of clients currently online. Each flag adds extra fields to the server /// response. Note: only returns a list of client IDs regardless of flags used. /// /// /// Required permissions: b_virtualserver_client_list, /// i_channel_subscribe_power, i_channel_needed_subscribe_power /// /// When true, sends -uid to include client unique identifiers. /// When true, sends -away to include away status and message. /// When true, sends -voice to include talking/mute/recording status. /// When true, sends -times to include idle, created, and last connected times. /// When true, sends -groups to include server and channel group info. /// When true, sends -info to include client version and platform. /// When true, sends -country to include country code. /// When true, sends -ip to include client IP (requires b_client_remoteaddress_view). /// When true, sends -icon to include client icon ID. /// When true, sends -badges to include client badges. /// A list of objects, or null on error. public List ClientList(bool uid = false, bool away = false, bool voice = false, bool times = false, bool groups = false, bool info = false, bool country = false, bool ip = false, bool icon = false, bool badges = false) { var sb = new StringBuilder(); if (uid) sb.Append("-uid "); if (away) sb.Append("-away "); if (voice) sb.Append("-voice "); if (times) sb.Append("-times "); if (groups) sb.Append("-groups "); if (info) sb.Append("-info "); if (country) sb.Append("-country "); if (ip) sb.Append("-ip "); if (icon) sb.Append("-icon "); if (badges) sb.Append("-badges "); if (!SendCommand($"clientlist {sb}", out QueryResponse res)) return null; return res.GetAll(); } /// /// Displays detailed configuration of a single client including UID, nickname, version, and groups. /// /// Required permission: b_client_info_view /// The online client ID (clid). /// A object with ID set, or null on error. public ClientInfo GetClientInfo(int clientID) { if (SendCommand($"clientinfo clid={clientID}", out QueryResponse res)) { var client = res.Get(); if (client != null) client.Update("clid", clientID.ToString()); return client; } return null; } /// /// Displays detailed configuration for multiple clients in a single batch request. /// /// Required permission: b_client_info_view /// One or more online client IDs (clid). /// /// A list of objects in the same order as , /// or null on error or count mismatch. /// public List GetClientInfo(params IEnumerable clientIDs) { string cmd = "clientinfo " + string.Join("|", clientIDs.Select(id => $"clid={id}")); if (!SendCommand(cmd, out QueryResponse res)) return null; var entries = res.GetAll(); if (entries.Count != clientIDs.Count()) { GlobalLogger.Log("ServerQuery", "GetClientInfo response mismatch!", LogType.Warning); return null; } for (int i = 0; i < clientIDs.Count(); i++) entries[i].Update("clid", clientIDs.ElementAt(i).ToString()); return entries; } /// /// Displays a list of clients matching the given nickname pattern. /// /// Required permission: b_virtualserver_client_search /// Regex pattern to match against client nicknames (pattern). /// A list of matching client IDs (clid), or null on error. public List ClientFind(string pattern) { if (SendCommand($"clientfind pattern={pattern.ToTsFormat()}", out QueryResponse res)) return res.GetAll("clid"); return null; } /// /// Changes a connected client's settings such as description, talk power, and channel commander status. /// /// /// Required permissions: b_client_modify_description, b_client_set_talk_power /// /// The online client ID (clid). /// Client properties to modify. /// true on success, false on error. public bool EditClient(int clientID, EditClientProperties properties) => SendCommand($"clientedit clid={clientID}", properties.changes); /// /// Displays a list of client database entries known by the server. /// /// Required permission: b_virtualserver_client_dblist /// Skip the first n entries (start). Leave empty to start from the beginning. /// Return at most n entries (duration). Leave empty for default. /// When true, sends -count to also return total number of entries. /// A list of objects, or null on error. public List ListDBClients(string start = "", string duration = "", bool count = false) { var sb = new StringBuilder(); if (!string.IsNullOrEmpty(start)) sb.Append($"start={start} "); if (!string.IsNullOrEmpty(duration)) sb.Append($"duration={duration} "); if (count) sb.Append("-count "); if (SendCommand($"clientdblist {sb}", out QueryResponse res)) return res.GetAll(); return null; } /// /// Displays detailed database information about the client with the given database ID. /// /// Required permission: b_virtualserver_client_dbinfo /// The client's database ID (cldbid). /// A object, or null on error. public ClientDBInfo GetClientDBInfo(int clientDBID) { if (SendCommand($"clientdbinfo cldbid={clientDBID}", out QueryResponse res)) return res.Get(); return null; } /// /// Displays a list of client database IDs matching the given pattern. /// /// Required permission: b_virtualserver_client_dbsearch /// /// Pattern to match against client nickname or UID (pattern). /// SQL wildcard characters (e.g. %) are supported. /// /// /// When true, sends -uid to search by unique identifier instead of nickname. /// /// A list of matching client database IDs (cldbid), or null on error. public List ClientDBFind(string pattern, bool uid) { string option = uid ? "-uid" : ""; if (SendCommand($"clientdbfind pattern={pattern} {option}", out QueryResponse res)) return res.GetAll("cldbid"); return null; } /// /// Changes a client's database properties such as description. /// /// /// Required permissions: b_client_modify_dbproperties, b_client_modify_description, /// b_client_set_talk_power /// /// The client's database ID (cldbid). /// Dictionary of client database property key-value pairs to update. /// true on success, false on error. public bool EditDBClient(int clientDBID, Dictionary properties = null) => SendCommand($"clientdbedit cldbid={clientDBID}", properties); /// /// Deletes the client's properties from the database. /// /// Required permission: b_client_delete_dbproperties /// The client's database ID (cldbid). /// true on success, false on error. public bool DeleteDBClient(int clientDBID) => SendCommand($"clientdbdelete cldbid={clientDBID}"); /// /// Displays all online client IDs matching the given unique identifier. /// /// /// The client's unique identifier (cluid). /// A list of matching online client IDs (clid), or null on error. public List ClientGetIDs(string clientUID) { if (SendCommand($"clientgetids cluid={clientUID.ToTsFormat()}", out QueryResponse res)) return res.GetAll("clid"); return null; } /// /// Displays the database ID of the client with the given unique identifier. /// /// /// The client's unique identifier (cluid). /// The client database ID (cldbid), or -1 on error. public int GetClientDBIDFromUID(string clientUID) { if (SendCommand($"clientgetdbidfromuid cluid={clientUID.ToTsFormat()}", out QueryResponse res)) return res.Get("cldbid"); return -1; } /// /// Displays the database ID and last known nickname of the client with the given unique identifier. /// /// /// The client's unique identifier (cluid). /// The last known nickname (name), or null on error. public string GetClientNameFromUID(string clientUID) { if (SendCommand($"clientgetnamefromuid cluid={clientUID.ToTsFormat()}", out QueryResponse res)) return res["name"]; return null; } /// /// Displays the unique identifier and last known nickname of the client with the given database ID. /// /// /// The client's database ID (cldbid). /// The last known nickname (name), or null on error. public string GetClientNameFromDBID(int clientDBID) { if (SendCommand($"clientgetnamefromdbid cldbid={clientDBID}", out QueryResponse res)) return res["name"]; return null; } /// /// Displays the unique identifier of the online client with the given client ID. /// /// /// The online client ID (clid). /// The client's unique identifier (cluid), or null on error. public string ClientGetUIDFromClientID(int clientID) { if (SendCommand($"clientgetuidfromclid clid={clientID}", out QueryResponse res)) return res["cluid"]; return null; } /// /// Updates the ServerQuery login credentials using the given username. The password is /// auto-generated by the server. /// /// Required permission: b_client_create_modify_serverquery_login /// The requested login name (client_login_name). /// The auto-generated password (client_login_password), or null on error. public string SetClientServerQueryLogin(string username) { if (SendCommand($"clientsetserverquerylogin client_login_name={username.ToTsFormat()}", out QueryResponse res)) return res["client_login_password"]; return null; } /// /// Changes your own ServerQuery client settings such as nickname. /// /// /// Client properties to update (e.g. client_nickname). /// true on success, false on error. public bool UpdateClient(EditClientProperties properties) => SendCommand("clientupdate", properties.changes); /// /// Moves a client to the specified channel. /// /// /// Required permissions: i_client_move_power, i_client_needed_move_power /// /// The online client ID (clid). /// The target channel ID (cid). /// true on success, false on error. public bool MoveClient(int clientID, int channelID) => SendCommand($"clientmove clid={clientID} cid={channelID}"); /// /// Moves a client to a password-protected channel. /// /// /// Required permissions: i_client_move_power, i_client_needed_move_power /// /// The online client ID (clid). /// The target channel ID (cid). /// The channel password (cpw). /// true on success, false on error. public bool MoveClient(int clientID, int channelID, string password) => SendCommand($"clientmove clid={clientID} cid={channelID} cpw={password.ToTsFormat()}"); /// /// Kicks a client from their current channel or from the server. /// /// /// Required permissions: i_client_kick_from_server_power, /// i_client_kick_from_channel_power, i_client_needed_kick_from_server_power, /// i_client_needed_kick_from_channel_power /// /// The online client ID (clid). /// /// The kick target: or . /// /// true on success, false on error. public bool KickClient(int clientID, EventReason reasonID) => SendCommand($"clientkick clid={clientID} reasonid={(int)reasonID}"); /// /// Kicks a client from their current channel or from the server with a reason message. /// /// /// Required permissions: i_client_kick_from_server_power, /// i_client_kick_from_channel_power, i_client_needed_kick_from_server_power, /// i_client_needed_kick_from_channel_power /// /// The online client ID (clid). /// /// The kick target: or . /// /// Reason message displayed to the kicked client (reasonmsg). Max 40 characters. /// true on success, false on error. public bool KickClient(int clientID, EventReason reasonID, string reasonMsg) => SendCommand($"clientkick clid={clientID} reasonid={(int)reasonID} reasonmsg={reasonMsg.ToTsMessageFormat()}"); /// /// Sends a poke message to the given client. /// /// /// Required permissions: i_client_poke_power, i_client_needed_poke_power /// /// The online client ID (clid). /// The poke message (msg). /// true on success, false on error. public bool PokeClient(int clientID, string msg) => SendCommand($"clientpoke clid={clientID} msg={msg.ToTsMessageFormat()}"); /// /// Displays permissions assigned to the given client. /// /// Required permission: b_virtualserver_client_permission_list /// The client's database ID (cldbid). /// /// When true, sends -permsid to include permission name strings instead of /// numeric IDs in the response. /// /// A list of objects, or null on error. public List ListClientPermissions(int clientDBID, bool permsid = false) { string option = permsid ? "-permsid" : ""; if (SendCommand($"clientpermlist cldbid={clientDBID} {option}", out QueryResponse res)) return res.GetAll(); return null; } /// /// Adds a permission to the given client. /// /// /// Required permissions: i_group_modify_power, i_group_needed_modify_power, /// i_permission_modify_power /// /// The client's database ID (cldbid). /// The numeric permission ID (permid). /// The permission value (permvalue). /// Set to "1" to skip the permission check (permskip). /// true on success, false on error. public bool AddClientPermission(int clientDBID, int permid, string permvalue, string permSkip = "0") => SendCommand($"clientaddperm cldbid={clientDBID} permid={permid} permvalue={permvalue} permskip={permSkip}"); /// /// Removes a permission from the given client. /// /// /// Required permissions: i_group_modify_power, i_group_needed_modify_power, /// i_permission_modify_power /// /// The client's database ID (cldbid). /// The numeric permission ID to remove (permid). /// true on success, false on error. public bool DeleteClientPermission(int clientDBID, int permid) => SendCommand($"clientdelperm cldbid={clientDBID} permid={permid}"); /// /// Displays channel-specific permissions assigned to the given client in the given channel. /// /// Required permission: b_virtualserver_channelclient_permission_list /// The channel ID (cid). /// The client's database ID (cldbid). /// /// When true, sends -permsid to include permission name strings instead of /// numeric IDs in the response. /// /// A list of objects, or null on error. public List ListChannelClientPermissions(int channelID, int clientDBID, bool permsid = false) { string option = permsid ? "-permsid" : ""; if (SendCommand($"channelclientpermlist cid={channelID} cldbid={clientDBID} {option}", out QueryResponse res)) return res.GetAll(); return null; } /// /// Adds a channel-specific permission to a client in a specific channel. /// /// /// Required permissions: i_group_modify_power, i_group_needed_modify_power, /// i_permission_modify_power /// /// The channel ID (cid). /// The client's database ID (cldbid). /// The numeric permission ID (permid). /// The permission value (permvalue). /// true on success, false on error. public bool AddChannelClientPermission(int channelID, int clientDBID, int permid, string permvalue) => SendCommand($"channelclientaddperm cid={channelID} cldbid={clientDBID} permid={permid} permvalue={permvalue}"); /// /// Removes a channel-specific permission from a client in a specific channel. /// /// /// Required permissions: i_group_modify_power, i_group_needed_modify_power, /// i_permission_modify_power /// /// The channel ID (cid). /// The client's database ID (cldbid). /// The numeric permission ID to remove (permid). /// true on success, false on error. public bool DeleteChannelClientPermission(int channelID, int clientDBID, int permid) => SendCommand($"channelclientdelperm cid={channelID} cldbid={clientDBID} permid={permid}"); /// /// Displays a list of all permissions available on the server instance including ID, name, /// and description. /// /// Required permission: b_serverinstance_permission_list /// A list of objects, or null on error. public List ListPermissions() { if (SendCommand($"permissionlist", out QueryResponse res)) return res.GetAll(); return null; } /// /// Displays the numeric database ID of the permission with the given name string. /// /// Required permission: b_serverinstance_permission_list /// The permission name string (permsid), e.g. "b_serverquery_login". /// The numeric permission ID (permid), or -1 on error. public int GetPermissionIDByName(string name) { if (SendCommand($"permidgetbyname permsid={name}", out QueryResponse res)) return res.Get("permid"); return -1; } /// /// Displays all permissions assigned to a client for the given channel. /// Pass permid=0 to return all permissions. /// /// Required permission: b_client_permissionoverview_view /// The channel ID (cid). /// The client's database ID (cldbid). /// /// The numeric permission ID to look up (permid). Set to 0 to return all permissions. /// /// A list of permission assignment dictionaries, or null on error. public List> GetPermissionOverview(int channelID, int clientDBID, int permID) { if (SendCommand($"permoverview cid={channelID} cldbid={clientDBID} permid={permID}", out QueryResponse res)) return res.ToDictionaryList(); return null; } /// /// Displays the current value of the given permission for your own connection. /// /// Required permission: b_client_permissionoverview_own /// The numeric permission ID (permid). /// A object with Name, ID, and Value populated, or null on error. public SetPermissionInfo GetPermissionInfo(int permID) { if (SendCommand($"permget permid={permID}", out QueryResponse res)) return res.Get(); return null; } /// /// Displays all assignments of the given permission across clients, channels, and groups. /// /// /// Required permissions: b_virtualserver_permission_find, /// b_serverinstance_permission_find /// /// The numeric permission ID (permid). /// A list of assignment dictionaries, or null on error. public List> FindPermission(int permID) { if (SendCommand($"permfind permid={permID}", out QueryResponse res)) return res.ToDictionaryList(); return null; } /// /// Restores default permission settings on the selected virtual server and creates a new /// initial administrator token. WARNING: Deletes all server and channel groups. /// /// Required permission: b_virtualserver_permission_reset /// true on success, false on error. public bool ResetPermissions() => SendCommand($"permreset"); /// /// Displays a list of privilege keys (tokens) available on the current virtual server. /// /// Required permission: b_virtualserver_token_list /// A list of token dictionaries, or null on error. public List> ListPrivilegeKeys() { if (SendCommand($"privilegekeylist", out QueryResponse res)) return res.ToDictionaryList(); return null; } /// /// Creates a new privilege key (token) to grant access to a server or channel group. /// /// /// Required permissions: b_virtualserver_token_add, /// i_group_needed_member_add_power, i_group_member_add_power /// /// /// Token type (tokentype): "0" = server group token (use as server group ID, /// set to 0); "1" = channel group token (use /// as channel group ID, must be a valid channel). /// /// The server or channel group ID (tokenid1). /// The channel ID (tokenid2). Required for channel group tokens; set to 0 for server group tokens. /// Optional description for the token (tokendescription). /// /// Optional custom client property set (tokencustomset). Format: /// "ident=key1 value=val1|ident=key2 value=val2". /// /// A dictionary with the generated token string, or null on error. public Dictionary AddPrivilegeKey(string tokentype, int groupID, int channelID, string description = "", string customFields = "") { var sb = new StringBuilder($"privilegekeyadd tokentype={tokentype} tokenid1={groupID} tokenid2={channelID}"); if (!string.IsNullOrEmpty(description)) sb.Append($" tokendescription={description.ToTsFormat()}"); if (!string.IsNullOrEmpty(customFields)) sb.Append($" tokencustomset={customFields.ToTsFormat()}"); if (SendCommand(sb.ToString(), out QueryResponse res)) return res.ToDictionary(); return null; } /// /// Deletes the privilege key (token) with the given token string. /// /// Required permission: b_virtualserver_token_delete /// The token string to delete (token). /// true on success, false on error. public bool DeletePrivilegeKey(string tokenKey) => SendCommand($"privilegekeydelete token={tokenKey}"); /// /// Redeems a privilege key (token) to gain access to the associated server or channel group. /// The token is automatically deleted after use. /// /// Required permission: b_virtualserver_token_use /// The token string to redeem (token). /// true on success, false on error. public bool UsePrivilegeKey(string tokenKey) => SendCommand($"privilegekeyuse token={tokenKey}"); /// /// Displays a list of offline messages in your inbox including sender UID, subject, timestamp, /// and read flag. /// /// /// A list of message dictionaries, or null on error. public List> ListMessages() { if (SendCommand($"messagelist", out QueryResponse res)) return res.ToDictionaryList(); return null; } /// /// Sends an offline message to the client with the given unique identifier. /// /// /// The recipient's unique identifier (cluid). /// The message subject (subject). /// The message body (message). /// true on success, false on error. public bool AddMessage(string clientUID, string subject, string message) => SendCommand($"messageadd cluid={clientUID.ToTsFormat()} subject={subject.ToTsMessageFormat()} message={message.ToTsMessageFormat()}"); /// /// Deletes the offline message with the given ID from your inbox. /// /// /// The message ID (msgid). /// true on success, false on error. public bool DeleteMessage(int messageID) => SendCommand($"messagedel msgid={messageID}"); /// /// Displays an offline message from your inbox. Does not automatically mark it as read. /// /// /// The message ID (msgid). /// A dictionary with msgid, cluid, subject, and message, or null on error. public Dictionary GetMessage(int messageID) { if (SendCommand($"messageget msgid={messageID}", out QueryResponse res)) return res.ToDictionary(); return null; } /// /// Updates the read flag of the given offline message. /// /// /// The message ID (msgid). /// Set to "1" to mark as read, "0" to mark as unread (flag). /// true on success, false on error. public bool UpdateMessageFlag(int messageID, string flag) => SendCommand($"messageupdateflag msgid={messageID} flag={flag}"); /// /// Displays a list of complaints on the selected virtual server. If /// is specified, only complaints about that client are shown. /// /// Required permission: b_client_complain_list /// /// The database ID of the client to filter complaints for (tcldbid). /// Use -1 to list all complaints on the server. /// /// A list of complaint dictionaries, or null on error. public List> ListComplaints(int targetClientDBID = -1) { string option = targetClientDBID != -1 ? $"tcldbid={targetClientDBID}" : ""; if (SendCommand($"complainlist {option}", out QueryResponse res)) return res.ToDictionaryList(); return null; } /// /// Submits a complaint about the client with the given database ID. /// /// /// Required permissions: i_client_complain_power, i_client_needed_complain_power /// /// The database ID of the client to complain about (tcldbid). /// The complaint message (message). /// true on success, false on error. public bool AddComplaint(int targetClientDBID, string message) => SendCommand($"complainadd tcldbid={targetClientDBID} message={message.ToTsFormat()}"); /// /// Deletes all complaints about the client with the given database ID. /// /// Required permission: b_client_complain_delete /// The database ID of the target client (tcldbid). /// true on success, false on error. public bool DeleteAllComplaints(int targetClientDBID) => SendCommand($"complaindelall tcldbid={targetClientDBID}"); /// /// Deletes a specific complaint about submitted by /// . /// /// /// Required permissions: b_client_complain_delete, b_client_complain_delete_own /// /// The database ID of the client who was complained about (tcldbid). /// The database ID of the client who submitted the complaint (fcldbid). /// true on success, false on error. public bool DeleteComplaint(int targetClientDBID, int formClientDBID) => SendCommand($"complaindel tcldbid={targetClientDBID} fcldbid={formClientDBID}"); /// /// Bans one or more clients by ID. Creates separate ban rules for the client's IP address, /// unique identifier, and mytsid (if available). /// /// /// Required permissions: i_client_ban_power, i_client_needed_ban_power /// /// The online client ID (clid). /// Ban duration in seconds (time). Leave empty for a permanent ban. /// Reason for the ban (banreason). /// A list of created ban IDs (one per rule: IP, UID, mytsid), or null on error. public List BanClient(int clientID, string time = "", string reason = "") { var sb = new StringBuilder(); if (!string.IsNullOrEmpty(time)) sb.Append($"time={time} "); if (!string.IsNullOrEmpty(reason)) sb.Append($"banreason={reason.ToTsFormat()} "); if (SendCommand($"banclient clid={clientID} {sb}", out QueryResponse res)) return res.GetAll("banid"); return null; } /// /// Displays a list of active ban rules on the current virtual server. /// /// Required permission: b_client_ban_list /// Skip the first n entries (start). Use -1 to omit. /// Return at most n entries (duration), capped at 200. Use -1 to omit. /// When true, sends -count to also return the total number of entries. /// A list of objects, or null on error. public List ListBans(int start = -1, int duration = -1, bool count = false) { var sb = new StringBuilder(); if (start != -1) sb.Append($"start={start} "); if (duration != -1) sb.Append($"duration={duration} "); if (count) sb.Append("-count "); if (SendCommand($"banlist {sb}", out QueryResponse res)) return res.GetAll(); return null; } /// /// Creates a ban rule matching by client unique identifier (UID). /// At least one of uid, ip, name, or mytsid must be set. /// /// Required permission: b_client_ban_create /// The client's unique identifier to ban (uid). /// Ban duration in seconds (time). Leave empty for a permanent ban. /// Reason for the ban (banreason). /// Last known nickname to associate with the ban rule (lastnickname). /// The created ban rule ID (banid), or -1 on error. public int AddBan(string clientUID, string time = "", string reason = "", string lastNickname = "") { var sb = new StringBuilder(); if (!string.IsNullOrEmpty(time)) sb.Append($"time={time} "); if (!string.IsNullOrEmpty(reason)) sb.Append($"banreason={reason.ToTsFormat()} "); if (!string.IsNullOrEmpty(lastNickname)) sb.Append($"lastnickname={lastNickname.ToTsFormat()} "); if (SendCommand($"banadd uid={clientUID} {sb}", out QueryResponse res)) return res.Get("banid"); return -1; } /// /// Creates a ban rule matching by IP address regex. /// At least one of uid, ip, name, or mytsid must be set. /// /// Required permission: b_client_ban_create /// Regular expression matching the client's IP address (ip). /// Ban duration in seconds (time). Leave empty for a permanent ban. /// Reason for the ban (banreason). /// Last known nickname to associate with the ban rule (lastnickname). /// The created ban rule ID (banid), or -1 on error. public int AddBanIP(string ipRegExp, string time = "", string reason = "", string lastNickname = "") { var sb = new StringBuilder(); if (!string.IsNullOrEmpty(time)) sb.Append($"time={time} "); if (!string.IsNullOrEmpty(reason)) sb.Append($"banreason={reason.ToTsFormat()} "); if (!string.IsNullOrEmpty(lastNickname)) sb.Append($"lastnickname={lastNickname.ToTsFormat()} "); if (SendCommand($"banadd ip={ipRegExp} {sb}", out QueryResponse res)) return res.Get("banid"); return -1; } /// /// Creates a ban rule matching by client nickname regex. /// At least one of uid, ip, name, or mytsid must be set. /// /// Required permission: b_client_ban_create /// Regular expression matching the client's nickname (name). /// Ban duration in seconds (time). Leave empty for a permanent ban. /// Reason for the ban (banreason). /// Last known nickname to associate with the ban rule (lastnickname). /// The created ban rule ID (banid), or -1 on error. public int AddBanName(string nameRegExp, string time = "", string reason = "", string lastNickname = "") { var sb = new StringBuilder(); if (!string.IsNullOrEmpty(time)) sb.Append($"time={time} "); if (!string.IsNullOrEmpty(reason)) sb.Append($"banreason={reason.ToTsFormat()} "); if (!string.IsNullOrEmpty(lastNickname)) sb.Append($"lastnickname={lastNickname.ToTsFormat()} "); if (SendCommand($"banadd name={nameRegExp} {sb}", out QueryResponse res)) return res.Get("banid"); return -1; } /// /// Creates a ban rule matching by myTeamSpeak ID. /// At least one of uid, ip, name, or mytsid must be set. Pass "empty" to match /// clients without a myTS ID. /// /// Required permission: b_client_ban_create /// The myTeamSpeak ID to ban (mytsid), or "empty" to match clients without one. /// Ban duration in seconds (time). Leave empty for a permanent ban. /// Reason for the ban (banreason). /// Last known nickname to associate with the ban rule (lastnickname). /// The created ban rule ID (banid), or -1 on error. public int AddBanMyTsID(string myTsID, string time = "", string reason = "", string lastNickname = "") { var sb = new StringBuilder(); if (!string.IsNullOrEmpty(time)) sb.Append($"time={time} "); if (!string.IsNullOrEmpty(reason)) sb.Append($"banreason={reason.ToTsFormat()} "); if (!string.IsNullOrEmpty(lastNickname)) sb.Append($"lastnickname={lastNickname.ToTsFormat()} "); if (SendCommand($"banadd mytsid={myTsID} {sb}", out QueryResponse res)) return res.Get("banid"); return -1; } /// /// Deletes the ban rule with the given ID. /// /// /// Required permissions: b_client_ban_delete, b_client_ban_delete_own /// /// The ban rule ID (banid). /// true on success, false on error. public bool DeleteBan(int banID) => SendCommand($"bandel banid={banID}"); /// /// Deletes all active ban rules from the current virtual server. /// /// Required permission: b_client_ban_delete /// true on success, false on error. public bool DeleteAllBans() => SendCommand($"bandelall"); /// /// Displays information about the current ServerQuery connection including login name, /// virtual server status, client ID, and channel ID. /// /// /// A object with the current session details, or null on error. public WhoAmIInfo WhoAmI() { if (SendCommand($"whoami", out QueryResponse res)) return res.Get(); return null; } /// /// Creates a new API key for the invoking user with the specified access scope. /// A default lifetime of 14 days is used if not specified. A zero lifetime means no expiration. /// /// /// Required permissions: b_virtualserver_apikey_add, b_virtualserver_apikey_manage /// /// The access scope (scope): "manage", "write", or "read". /// Lifetime of the key in days (lifetime). Use 0 for unlimited. Use -1 to omit (server default of 14 days applies). /// Create the key for another client by their database ID (cldbid). Requires b_virtualserver_apikey_manage. Use -1 to create for the invoking user. /// An with the created key (including the token), or null on error. public ApiKeyInfo AddApiKey(string scope, int lifetime = -1, int cldbid = -1) { var sb = new StringBuilder($"apikeyadd scope={scope}"); if (lifetime != -1) sb.Append($" lifetime={lifetime}"); if (cldbid != -1) sb.Append($" cldbid={cldbid}"); if (SendCommand(sb.ToString(), out QueryResponse res)) return res.Get(); return null; } /// /// Deletes the API key with the given numeric ID. Any key owned by the current user can /// always be deleted. Deleting keys of other users requires b_virtualserver_apikey_manage. /// /// Required permission: b_virtualserver_apikey_manage /// The numeric API key ID (id). /// true on success, false on error. public bool DeleteApiKey(int id) => SendCommand($"apikeydel id={id}"); /// /// Lists API keys. By default lists only keys owned by the invoking user. /// /// Required permission: b_virtualserver_apikey_manage /// /// Filter by owner client database ID (cldbid). Pass "*" to list keys of all /// clients (requires b_virtualserver_apikey_manage). Leave empty for invoking user's keys. /// /// Skip the first n entries (start). Use -1 to omit. /// Return at most n entries (duration). Use -1 to omit. /// When true, sends -count to also return the total number of entries. /// A list of objects, or null on error. public List ListApiKeys(string cldbid = "", int start = -1, int duration = -1, bool count = false) { var sb = new StringBuilder("apikeylist"); if (!string.IsNullOrEmpty(cldbid)) sb.Append($" cldbid={cldbid}"); if (start != -1) sb.Append($" start={start}"); if (duration != -1) sb.Append($" duration={duration}"); if (count) sb.Append(" -count"); if (SendCommand(sb.ToString(), out QueryResponse res)) return res.GetAll(); return null; } /// /// Adds a new ServerQuery login or enables query login for an existing client. /// Without a selected virtual server, creates a global query login. /// With a selected virtual server, must be specified to enable /// query login for an existing client. /// /// Required permission: b_serverquery_login_create /// The requested login name (client_login_name). /// /// The client's database ID to enable query login for (cldbid). /// Required when a virtual server is selected. Use -1 to omit (global login). /// /// /// A dictionary with cldbid, sid, client_login_name, and /// client_login_password, or null on error. /// public Dictionary AddQueryLogin(string loginName, int cldbid = -1) { var sb = new StringBuilder($"queryloginadd client_login_name={loginName.ToTsFormat()}"); if (cldbid != -1) sb.Append($" cldbid={cldbid}"); if (SendCommand(sb.ToString(), out QueryResponse res)) return res.ToDictionary(); return null; } /// /// Deletes the ServerQuery login for the client with the given database ID. When no virtual /// server is selected, deletes global query logins instead. /// /// Required permission: b_serverquery_login_delete /// The client's database ID (cldbid). /// true on success, false on error. public bool DeleteQueryLogin(int cldbid) => SendCommand($"querylogindel cldbid={cldbid}"); /// /// Lists existing ServerQuery logins. Shows only logins for the selected virtual server, /// or all logins when no virtual server is selected. /// /// Required permission: b_serverquery_login_list /// /// Filter by login name pattern (pattern). SQL wildcard characters (e.g. %) /// are supported. Leave empty to list all. /// /// Skip the first n entries (start). Use -1 to omit. /// Return at most n entries (duration). Use -1 to omit. /// When true, sends -count to also return the total number of entries. /// A list of login dictionaries with cldbid, sid, and client_login_name, or null on error. public List> ListQueryLogins(string pattern = "", int start = -1, int duration = -1, bool count = false) { var sb = new StringBuilder("queryloginlist"); if (!string.IsNullOrEmpty(pattern)) sb.Append($" pattern={pattern.ToTsFormat()}"); if (start != -1) sb.Append($" start={start}"); if (duration != -1) sb.Append($" duration={duration}"); if (count) sb.Append(" -count"); if (SendCommand(sb.ToString(), out QueryResponse res)) return res.ToDictionaryList(); return null; } /// /// Creates a new temporary server password. Clients connecting with this password will /// automatically join the specified channel. /// /// Required permission: b_virtualserver_modify_password /// The temporary password (pw). /// A descriptive label for the password (desc). /// The number of seconds the password is valid for (duration). /// /// The channel clients will automatically join when using this password (tcid). /// Set to 0 to use the server's default channel. /// /// The password of the target channel (tcpw). Leave empty if the channel has no password. /// true on success, false on error. public bool AddTempServerPassword(string password, string description, int duration, int channelID = 0, string channelPW = "") => SendCommand($"servertemppasswordadd pw={password.ToTsFormat()} desc={description.ToTsFormat()} duration={duration} tcid={channelID} tcpw={channelPW.ToTsFormat()}"); /// /// Deletes the temporary server password with the given plain-text password string. /// /// Required permission: b_virtualserver_modify_password /// The temporary password to delete (pw). /// true on success, false on error. public bool DeleteTempServerPassword(string password) => SendCommand($"servertemppassworddel pw={password.ToTsFormat()}"); /// /// Returns a list of active temporary server passwords including their clear-text value, /// creator nickname/UID, expiry time, and target channel. /// /// Required permission: b_virtualserver_modify_password /// A list of temporary password dictionaries, or null on error. public List> ListTempServerPasswords() { if (SendCommand($"servertemppasswordlist", out QueryResponse res)) return res.ToDictionaryList(); return null; } } }