├── .editorconfig ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ ├── CD.yml │ └── CI.yml ├── .gitignore ├── .npmignore ├── .vscode ├── extensions.json ├── settings.json └── tasks.json ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── src ├── index.ts ├── node-ts.ts └── queryStrings.ts └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | [*] 3 | end_of_line = lf 4 | insert_final_newline = true 5 | 6 | [*.{ts,json,js}] 7 | charset = utf-8 8 | 9 | [*.{ts,js}] 10 | indent_style = space 11 | indent_size = 4 12 | 13 | [*.json] 14 | indent_style = tab 15 | tab_width = 4 16 | 17 | [package.json] 18 | indent_style = space 19 | indent_size = 2 20 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: nikeee 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "npm" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: "monthly" 12 | -------------------------------------------------------------------------------- /.github/workflows/CD.yml: -------------------------------------------------------------------------------- 1 | name: CD 2 | 3 | on: 4 | push: 5 | branches: 6 | - "!*" 7 | tags: 8 | - "v*" 9 | 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | 14 | permissions: 15 | contents: read 16 | id-token: write 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | 21 | - uses: actions/setup-node@v4 22 | with: 23 | node-version: 24 24 | cache: npm 25 | registry-url: https://registry.npmjs.org 26 | 27 | - run: npm ci 28 | - run: npm run compile 29 | - run: npm test 30 | env: 31 | CI: true 32 | - run: npm publish --provenance --access public 33 | env: 34 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 35 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | 8 | runs-on: ubuntu-latest 9 | 10 | strategy: 11 | matrix: 12 | node-version: [20.x, 22.x, 24.x] 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | 17 | - name: Use Node.js ${{ matrix.node-version }} 18 | uses: actions/setup-node@v4 19 | with: 20 | node-version: ${{ matrix.node-version }} 21 | cache: npm 22 | 23 | - run: npm ci 24 | - run: npm run compile 25 | - run: npm test 26 | env: 27 | CI: true 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # js files will only be relevant for the released npm package, so don't inclode them 2 | *.js 3 | 4 | # d.ts files can be generated, so don't include them 5 | *.d.ts 6 | 7 | # exclude VS-generated files/folders 8 | bin/ 9 | obj/ 10 | *.user 11 | *.js.map 12 | *.suo 13 | 14 | npm-debug.log 15 | 16 | # nodejs tools dat files 17 | *.dat 18 | 19 | # exclude node modules, they will be installed using npm 20 | node_modules/ 21 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # No log files/DBs 2 | *.log 3 | *.db* 4 | 5 | *.ts 6 | !*.d.ts 7 | *.js.map 8 | 9 | # No ts files are shipped, so we don't need any config 10 | tsconfig.json 11 | 12 | # Make sure js files always get included 13 | !*.js 14 | 15 | # No CI/Editor-Specific files 16 | .editorconfig 17 | .vscode/ 18 | .travis.yml 19 | 20 | # No raw ts source + tests 21 | src/ 22 | tests/ 23 | 24 | # License is stated/linked to in package.json 25 | LICENSE 26 | *.md 27 | 28 | .github/ 29 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "EditorConfig.EditorConfig", 4 | "eg2.tslint" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "editor.formatOnSave": false, 4 | "editor.formatOnType": true 5 | } 6 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "command": "tsc", 4 | "args": [], 5 | "problemMatcher": "$tsc", 6 | "tasks": [ 7 | { 8 | "label": "tsc", 9 | "type": "shell", 10 | "command": "tsc", 11 | "problemMatcher": "$tsc", 12 | "group": { 13 | "_id": "build", 14 | "isDefault": false 15 | } 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-ts [![Build Status](https://travis-ci.com/nikeee/node-ts.svg?branch=master)](https://travis-ci.com/nikeee/node-ts) [![npm version](https://badge.fury.io/js/node-ts.svg)](http://badge.fury.io/js/node-ts) ![Dependency Status](https://david-dm.org/nikeee/node-ts.svg) ![License](https://img.shields.io/npm/l/node-ts.svg) ![Downloads Per Month](https://img.shields.io/npm/dm/node-ts.svg) 2 | 3 | This is a CommonJS module which allows you to connect to any TeamSpeak® 3 server which has the Server Query API enabled. Using the Server Query API, you can do everything a normal TeamSpeak user can do (except sending and receiving voice data) automatically via JavaScript/TypeScript (e. g. listing clients logged in on the server). 4 | 5 | The Server Query specification is available [here](http://media.teamspeak.com/ts3_literature/TeamSpeak%203%20Server%20Query%20Manual.pdf). I also created a script to import the complete query API from a TeamSpeak 3 server using the help command. This (json) dump will later be used to auto genrate some stuff. It is available as Gist [here](https://gist.github.com/nikeee/71e71439dd91999a3692). 6 | 7 | This is a fork of [gwTumm's node-teamspeak](https://github.com/gwTumm/node-teamspeak) which has been ported from JS to TS. 8 | 9 | ## Install 10 | ```bash 11 | npm install -S node-ts # install package 12 | ``` 13 | 14 | ## Example Usage 15 | After registering a Server Query account using your TeamSpeak Client, you can login using node-ts (Alternatively, you can login as the root account "`ServerAdmin`" which is created during the installation of the server). The following code prints out a JSON-array containing all clients that are currently connected to the first virtual server: 16 | 17 | ```TypeScript 18 | import { TeamSpeakClient } from "node-ts"; 19 | // Node.js without ES Modules: 20 | // const { TeamSpeakClient } = require("node-ts"); 21 | 22 | async function main() { 23 | const client = new TeamSpeakClient("server.example.com"); 24 | 25 | try { 26 | await client.connect(); 27 | 28 | await client.send("use", { sid: 1 }); 29 | 30 | const me = await client.send("whoami"); 31 | console.log(me); 32 | 33 | // Log in to use more features 34 | await client.send("login", { 35 | client_login_name: "##USERNAME##", 36 | client_login_password: "##PASSWORD##" 37 | }); 38 | 39 | const clientList = await client.send("clientlist"); 40 | console.log(clientList); 41 | 42 | await client.subscribePrivateTextEvents(); // Tell the server we want to receive private text events 43 | 44 | // Register a callback for these events 45 | client.on("textmessage", data => { 46 | console.log(`Message received: ${data.msg}`); 47 | }); 48 | 49 | } catch (err) { 50 | console.error("An error occurred:") 51 | console.error(err); 52 | } 53 | } 54 | main(); 55 | ``` 56 | 57 | ## Usage information 58 | 59 | * TeamSpeakClient.send is the main method that executes a command. An array with options and an object with parameters can be passed to the send-function. The function returns a `Promise`. See the TypeScript file for more information. 60 | * Every TeamSpeakClient instance is an `EventEmitter`. You can install listeners to the `"close"` and `"error"` event. The error-event will only be fired if there was socket-error, not if a sent command failed. 61 | * If you want to register to notifications sent by the TeamSpeak-Server, you can send a normal command `servernotifyregister` (consider specification). Any event sent by the server that starts with `"notify"` is then fired as an event (e. g. as soon as a `notifyclientmove` notification is sent by the server, the TeamSpeakClient-instance fires the `"clientmove"` event with only one parameter which is an object containing the given parameters). 62 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-ts", 3 | "version": "8.0.5", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "node-ts", 9 | "version": "8.0.5", 10 | "license": "LGPL-3.0", 11 | "dependencies": { 12 | "@rauschma/stringio": "^1.4.0", 13 | "@types/node": "^22.15.29" 14 | }, 15 | "devDependencies": { 16 | "rimraf": "^6.0.1", 17 | "typescript": "^5.8.3" 18 | }, 19 | "engines": { 20 | "node": ">=22.0.0" 21 | } 22 | }, 23 | "node_modules/@isaacs/cliui": { 24 | "version": "8.0.2", 25 | "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", 26 | "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", 27 | "dev": true, 28 | "license": "ISC", 29 | "dependencies": { 30 | "string-width": "^5.1.2", 31 | "string-width-cjs": "npm:string-width@^4.2.0", 32 | "strip-ansi": "^7.0.1", 33 | "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", 34 | "wrap-ansi": "^8.1.0", 35 | "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" 36 | }, 37 | "engines": { 38 | "node": ">=12" 39 | } 40 | }, 41 | "node_modules/@rauschma/stringio": { 42 | "version": "1.4.0", 43 | "resolved": "https://registry.npmjs.org/@rauschma/stringio/-/stringio-1.4.0.tgz", 44 | "integrity": "sha512-3uor2f/MXZkmX5RJf8r+OC3WvZVzpSme0yyL0rQDPEnatE02qRcqwEwnsgpgriEck0S/n4vWtUd6tTtrJwk45Q==", 45 | "dependencies": { 46 | "@types/node": "^10.0.3" 47 | } 48 | }, 49 | "node_modules/@rauschma/stringio/node_modules/@types/node": { 50 | "version": "10.17.60", 51 | "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", 52 | "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", 53 | "license": "MIT" 54 | }, 55 | "node_modules/@types/node": { 56 | "version": "22.15.29", 57 | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.29.tgz", 58 | "integrity": "sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==", 59 | "license": "MIT", 60 | "dependencies": { 61 | "undici-types": "~6.21.0" 62 | } 63 | }, 64 | "node_modules/ansi-regex": { 65 | "version": "6.1.0", 66 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", 67 | "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", 68 | "dev": true, 69 | "license": "MIT", 70 | "engines": { 71 | "node": ">=12" 72 | }, 73 | "funding": { 74 | "url": "https://github.com/chalk/ansi-regex?sponsor=1" 75 | } 76 | }, 77 | "node_modules/ansi-styles": { 78 | "version": "6.2.1", 79 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 80 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", 81 | "dev": true, 82 | "license": "MIT", 83 | "engines": { 84 | "node": ">=12" 85 | }, 86 | "funding": { 87 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 88 | } 89 | }, 90 | "node_modules/balanced-match": { 91 | "version": "1.0.2", 92 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 93 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 94 | "dev": true, 95 | "license": "MIT" 96 | }, 97 | "node_modules/brace-expansion": { 98 | "version": "2.0.1", 99 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 100 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 101 | "dev": true, 102 | "license": "MIT", 103 | "dependencies": { 104 | "balanced-match": "^1.0.0" 105 | } 106 | }, 107 | "node_modules/color-convert": { 108 | "version": "2.0.1", 109 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 110 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 111 | "dev": true, 112 | "license": "MIT", 113 | "dependencies": { 114 | "color-name": "~1.1.4" 115 | }, 116 | "engines": { 117 | "node": ">=7.0.0" 118 | } 119 | }, 120 | "node_modules/color-name": { 121 | "version": "1.1.4", 122 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 123 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 124 | "dev": true, 125 | "license": "MIT" 126 | }, 127 | "node_modules/cross-spawn": { 128 | "version": "7.0.6", 129 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", 130 | "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", 131 | "dev": true, 132 | "license": "MIT", 133 | "dependencies": { 134 | "path-key": "^3.1.0", 135 | "shebang-command": "^2.0.0", 136 | "which": "^2.0.1" 137 | }, 138 | "engines": { 139 | "node": ">= 8" 140 | } 141 | }, 142 | "node_modules/eastasianwidth": { 143 | "version": "0.2.0", 144 | "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", 145 | "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", 146 | "dev": true, 147 | "license": "MIT" 148 | }, 149 | "node_modules/emoji-regex": { 150 | "version": "9.2.2", 151 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 152 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", 153 | "dev": true, 154 | "license": "MIT" 155 | }, 156 | "node_modules/foreground-child": { 157 | "version": "3.3.1", 158 | "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", 159 | "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", 160 | "dev": true, 161 | "license": "ISC", 162 | "dependencies": { 163 | "cross-spawn": "^7.0.6", 164 | "signal-exit": "^4.0.1" 165 | }, 166 | "engines": { 167 | "node": ">=14" 168 | }, 169 | "funding": { 170 | "url": "https://github.com/sponsors/isaacs" 171 | } 172 | }, 173 | "node_modules/glob": { 174 | "version": "11.0.2", 175 | "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.2.tgz", 176 | "integrity": "sha512-YT7U7Vye+t5fZ/QMkBFrTJ7ZQxInIUjwyAjVj84CYXqgBdv30MFUPGnBR6sQaVq6Is15wYJUsnzTuWaGRBhBAQ==", 177 | "dev": true, 178 | "license": "ISC", 179 | "dependencies": { 180 | "foreground-child": "^3.1.0", 181 | "jackspeak": "^4.0.1", 182 | "minimatch": "^10.0.0", 183 | "minipass": "^7.1.2", 184 | "package-json-from-dist": "^1.0.0", 185 | "path-scurry": "^2.0.0" 186 | }, 187 | "bin": { 188 | "glob": "dist/esm/bin.mjs" 189 | }, 190 | "engines": { 191 | "node": "20 || >=22" 192 | }, 193 | "funding": { 194 | "url": "https://github.com/sponsors/isaacs" 195 | } 196 | }, 197 | "node_modules/is-fullwidth-code-point": { 198 | "version": "3.0.0", 199 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 200 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 201 | "dev": true, 202 | "license": "MIT", 203 | "engines": { 204 | "node": ">=8" 205 | } 206 | }, 207 | "node_modules/isexe": { 208 | "version": "2.0.0", 209 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 210 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 211 | "dev": true, 212 | "license": "ISC" 213 | }, 214 | "node_modules/jackspeak": { 215 | "version": "4.1.0", 216 | "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.0.tgz", 217 | "integrity": "sha512-9DDdhb5j6cpeitCbvLO7n7J4IxnbM6hoF6O1g4HQ5TfhvvKN8ywDM7668ZhMHRqVmxqhps/F6syWK2KcPxYlkw==", 218 | "dev": true, 219 | "license": "BlueOak-1.0.0", 220 | "dependencies": { 221 | "@isaacs/cliui": "^8.0.2" 222 | }, 223 | "engines": { 224 | "node": "20 || >=22" 225 | }, 226 | "funding": { 227 | "url": "https://github.com/sponsors/isaacs" 228 | } 229 | }, 230 | "node_modules/lru-cache": { 231 | "version": "11.1.0", 232 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", 233 | "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", 234 | "dev": true, 235 | "license": "ISC", 236 | "engines": { 237 | "node": "20 || >=22" 238 | } 239 | }, 240 | "node_modules/minimatch": { 241 | "version": "10.0.1", 242 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", 243 | "integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==", 244 | "dev": true, 245 | "license": "ISC", 246 | "dependencies": { 247 | "brace-expansion": "^2.0.1" 248 | }, 249 | "engines": { 250 | "node": "20 || >=22" 251 | }, 252 | "funding": { 253 | "url": "https://github.com/sponsors/isaacs" 254 | } 255 | }, 256 | "node_modules/minipass": { 257 | "version": "7.1.2", 258 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", 259 | "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", 260 | "dev": true, 261 | "license": "ISC", 262 | "engines": { 263 | "node": ">=16 || 14 >=14.17" 264 | } 265 | }, 266 | "node_modules/package-json-from-dist": { 267 | "version": "1.0.1", 268 | "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", 269 | "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", 270 | "dev": true, 271 | "license": "BlueOak-1.0.0" 272 | }, 273 | "node_modules/path-key": { 274 | "version": "3.1.1", 275 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 276 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 277 | "dev": true, 278 | "license": "MIT", 279 | "engines": { 280 | "node": ">=8" 281 | } 282 | }, 283 | "node_modules/path-scurry": { 284 | "version": "2.0.0", 285 | "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", 286 | "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", 287 | "dev": true, 288 | "license": "BlueOak-1.0.0", 289 | "dependencies": { 290 | "lru-cache": "^11.0.0", 291 | "minipass": "^7.1.2" 292 | }, 293 | "engines": { 294 | "node": "20 || >=22" 295 | }, 296 | "funding": { 297 | "url": "https://github.com/sponsors/isaacs" 298 | } 299 | }, 300 | "node_modules/rimraf": { 301 | "version": "6.0.1", 302 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", 303 | "integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==", 304 | "dev": true, 305 | "license": "ISC", 306 | "dependencies": { 307 | "glob": "^11.0.0", 308 | "package-json-from-dist": "^1.0.0" 309 | }, 310 | "bin": { 311 | "rimraf": "dist/esm/bin.mjs" 312 | }, 313 | "engines": { 314 | "node": "20 || >=22" 315 | }, 316 | "funding": { 317 | "url": "https://github.com/sponsors/isaacs" 318 | } 319 | }, 320 | "node_modules/shebang-command": { 321 | "version": "2.0.0", 322 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 323 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 324 | "dev": true, 325 | "license": "MIT", 326 | "dependencies": { 327 | "shebang-regex": "^3.0.0" 328 | }, 329 | "engines": { 330 | "node": ">=8" 331 | } 332 | }, 333 | "node_modules/shebang-regex": { 334 | "version": "3.0.0", 335 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 336 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 337 | "dev": true, 338 | "license": "MIT", 339 | "engines": { 340 | "node": ">=8" 341 | } 342 | }, 343 | "node_modules/signal-exit": { 344 | "version": "4.1.0", 345 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", 346 | "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", 347 | "dev": true, 348 | "license": "ISC", 349 | "engines": { 350 | "node": ">=14" 351 | }, 352 | "funding": { 353 | "url": "https://github.com/sponsors/isaacs" 354 | } 355 | }, 356 | "node_modules/string-width": { 357 | "version": "5.1.2", 358 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 359 | "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 360 | "dev": true, 361 | "license": "MIT", 362 | "dependencies": { 363 | "eastasianwidth": "^0.2.0", 364 | "emoji-regex": "^9.2.2", 365 | "strip-ansi": "^7.0.1" 366 | }, 367 | "engines": { 368 | "node": ">=12" 369 | }, 370 | "funding": { 371 | "url": "https://github.com/sponsors/sindresorhus" 372 | } 373 | }, 374 | "node_modules/string-width-cjs": { 375 | "name": "string-width", 376 | "version": "4.2.3", 377 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 378 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 379 | "dev": true, 380 | "license": "MIT", 381 | "dependencies": { 382 | "emoji-regex": "^8.0.0", 383 | "is-fullwidth-code-point": "^3.0.0", 384 | "strip-ansi": "^6.0.1" 385 | }, 386 | "engines": { 387 | "node": ">=8" 388 | } 389 | }, 390 | "node_modules/string-width-cjs/node_modules/ansi-regex": { 391 | "version": "5.0.1", 392 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 393 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 394 | "dev": true, 395 | "license": "MIT", 396 | "engines": { 397 | "node": ">=8" 398 | } 399 | }, 400 | "node_modules/string-width-cjs/node_modules/emoji-regex": { 401 | "version": "8.0.0", 402 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 403 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 404 | "dev": true, 405 | "license": "MIT" 406 | }, 407 | "node_modules/string-width-cjs/node_modules/strip-ansi": { 408 | "version": "6.0.1", 409 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 410 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 411 | "dev": true, 412 | "license": "MIT", 413 | "dependencies": { 414 | "ansi-regex": "^5.0.1" 415 | }, 416 | "engines": { 417 | "node": ">=8" 418 | } 419 | }, 420 | "node_modules/strip-ansi": { 421 | "version": "7.1.0", 422 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", 423 | "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", 424 | "dev": true, 425 | "license": "MIT", 426 | "dependencies": { 427 | "ansi-regex": "^6.0.1" 428 | }, 429 | "engines": { 430 | "node": ">=12" 431 | }, 432 | "funding": { 433 | "url": "https://github.com/chalk/strip-ansi?sponsor=1" 434 | } 435 | }, 436 | "node_modules/strip-ansi-cjs": { 437 | "name": "strip-ansi", 438 | "version": "6.0.1", 439 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 440 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 441 | "dev": true, 442 | "license": "MIT", 443 | "dependencies": { 444 | "ansi-regex": "^5.0.1" 445 | }, 446 | "engines": { 447 | "node": ">=8" 448 | } 449 | }, 450 | "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { 451 | "version": "5.0.1", 452 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 453 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 454 | "dev": true, 455 | "license": "MIT", 456 | "engines": { 457 | "node": ">=8" 458 | } 459 | }, 460 | "node_modules/typescript": { 461 | "version": "5.8.3", 462 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", 463 | "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", 464 | "dev": true, 465 | "license": "Apache-2.0", 466 | "bin": { 467 | "tsc": "bin/tsc", 468 | "tsserver": "bin/tsserver" 469 | }, 470 | "engines": { 471 | "node": ">=14.17" 472 | } 473 | }, 474 | "node_modules/undici-types": { 475 | "version": "6.21.0", 476 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", 477 | "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", 478 | "license": "MIT" 479 | }, 480 | "node_modules/which": { 481 | "version": "2.0.2", 482 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 483 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 484 | "dev": true, 485 | "license": "ISC", 486 | "dependencies": { 487 | "isexe": "^2.0.0" 488 | }, 489 | "bin": { 490 | "node-which": "bin/node-which" 491 | }, 492 | "engines": { 493 | "node": ">= 8" 494 | } 495 | }, 496 | "node_modules/wrap-ansi": { 497 | "version": "8.1.0", 498 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", 499 | "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", 500 | "dev": true, 501 | "license": "MIT", 502 | "dependencies": { 503 | "ansi-styles": "^6.1.0", 504 | "string-width": "^5.0.1", 505 | "strip-ansi": "^7.0.1" 506 | }, 507 | "engines": { 508 | "node": ">=12" 509 | }, 510 | "funding": { 511 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 512 | } 513 | }, 514 | "node_modules/wrap-ansi-cjs": { 515 | "name": "wrap-ansi", 516 | "version": "7.0.0", 517 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 518 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 519 | "dev": true, 520 | "license": "MIT", 521 | "dependencies": { 522 | "ansi-styles": "^4.0.0", 523 | "string-width": "^4.1.0", 524 | "strip-ansi": "^6.0.0" 525 | }, 526 | "engines": { 527 | "node": ">=10" 528 | }, 529 | "funding": { 530 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 531 | } 532 | }, 533 | "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { 534 | "version": "5.0.1", 535 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 536 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 537 | "dev": true, 538 | "license": "MIT", 539 | "engines": { 540 | "node": ">=8" 541 | } 542 | }, 543 | "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { 544 | "version": "4.3.0", 545 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 546 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 547 | "dev": true, 548 | "license": "MIT", 549 | "dependencies": { 550 | "color-convert": "^2.0.1" 551 | }, 552 | "engines": { 553 | "node": ">=8" 554 | }, 555 | "funding": { 556 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 557 | } 558 | }, 559 | "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { 560 | "version": "8.0.0", 561 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 562 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 563 | "dev": true, 564 | "license": "MIT" 565 | }, 566 | "node_modules/wrap-ansi-cjs/node_modules/string-width": { 567 | "version": "4.2.3", 568 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 569 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 570 | "dev": true, 571 | "license": "MIT", 572 | "dependencies": { 573 | "emoji-regex": "^8.0.0", 574 | "is-fullwidth-code-point": "^3.0.0", 575 | "strip-ansi": "^6.0.1" 576 | }, 577 | "engines": { 578 | "node": ">=8" 579 | } 580 | }, 581 | "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { 582 | "version": "6.0.1", 583 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 584 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 585 | "dev": true, 586 | "license": "MIT", 587 | "dependencies": { 588 | "ansi-regex": "^5.0.1" 589 | }, 590 | "engines": { 591 | "node": ">=8" 592 | } 593 | } 594 | } 595 | } 596 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Niklas Mollenhauer ", 3 | "name": "node-ts", 4 | "description": "TeamSpeak® 3 Server Query client for node.js implemented using TypeScript", 5 | "version": "8.0.5", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/nikeee/node-ts.git" 9 | }, 10 | "main": "lib/index.js", 11 | "type": "module", 12 | "types": "lib/index.d.ts", 13 | "dependencies": { 14 | "@rauschma/stringio": "^1.4.0", 15 | "@types/node": "^22.15.29" 16 | }, 17 | "devDependencies": { 18 | "rimraf": "^6.0.1", 19 | "typescript": "^5.8.3" 20 | }, 21 | "scripts": { 22 | "test": "tsc --noEmit", 23 | "clean": "rimraf lib", 24 | "compile": "tsc", 25 | "prepare": "npm run clean && npm run compile" 26 | }, 27 | "keywords": [ 28 | "teamspeak", 29 | "serverquery", 30 | "ts3", 31 | "ts", 32 | "typescript" 33 | ], 34 | "optionalDependencies": {}, 35 | "engines": { 36 | "node": ">=22.0.0" 37 | }, 38 | "license": "LGPL-3.0" 39 | } 40 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./node-ts"; 2 | -------------------------------------------------------------------------------- /src/node-ts.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @autor Niklas Mollenhauer 3 | * @autor Tim Kluge 4 | */ 5 | 6 | import * as net from "node:net"; 7 | import { EventEmitter } from "node:events"; 8 | import { chunksToLinesAsync, chomp } from "@rauschma/stringio"; 9 | 10 | import { escapeQueryString, unescapeQueryString } from "./queryStrings.js" 11 | 12 | /** Represents a Key-Value object. */ 13 | type MapLike = Record; 14 | 15 | /** 16 | * Client that can be used to connect to a TeamSpeak server query API. 17 | */ 18 | export class TeamSpeakClient extends EventEmitter { 19 | private queue: QueryCommand[] = []; 20 | private _executing: QueryCommand | undefined; 21 | 22 | private socket!: net.Socket; 23 | 24 | private isConnected = false; 25 | 26 | private static readonly DefaultHost = "localhost"; 27 | private static readonly DefaultPort = 10011; 28 | 29 | private readonly host: string; 30 | private readonly port: number; 31 | 32 | /** 33 | * Creates a new instance of TeamSpeakClient for a specific remote host:port. 34 | * @param {string = TeamSpeakClient.DefaultHost} host Remote host of the TeamSpeak server. Can be an IP address or a host name. 35 | * @param {number = TeamSpeakClient.DefaultPort} port TCP port of the server query instance of the remote host. 36 | * @constructor 37 | */ 38 | constructor( 39 | host = TeamSpeakClient.DefaultHost, 40 | port = TeamSpeakClient.DefaultPort, 41 | ) { 42 | super(); 43 | this.host = host; 44 | this.port = port; 45 | } 46 | 47 | public connect(): Promise { 48 | this.isConnected = false; 49 | return new Promise((resolve, reject) => { 50 | this.socket = net.connect(this.port, this.host); 51 | this.socket.on("error", err => this.emit("error", err)); 52 | // We'll try to reject the promise if the connection closes, to make sure 53 | // the promise gets rejected if we get an error while connecting. 54 | // (This will just do nothing if the promise is already fulfilled) 55 | this.socket.once("close", err => reject(err)); 56 | this.socket.on("close", () => this.emit("close", this.queue)); 57 | this.socket.on("connect", () => this.onConnect(resolve, reject)); 58 | }); 59 | } 60 | 61 | /** 62 | * Gets called on an opened connection 63 | */ 64 | private async onConnect(connectionEstablished: () => void, error: (e: Error) => void): Promise { 65 | const lineGenerator = chunksToLinesAsync(this.socket); 66 | 67 | let lineCounter = 0; 68 | 69 | for await (const lineWithNewLine of lineGenerator) { 70 | const line = chomp(lineWithNewLine).trim(); 71 | if (line === "") 72 | continue; 73 | ++lineCounter; 74 | 75 | switch (lineCounter) { 76 | case 1: { 77 | if (line !== "TS3") { 78 | this.isConnected = false; 79 | error(new Error("Remove server is not a TS3 Query Server endpoint.")); 80 | return; 81 | } 82 | continue; 83 | } 84 | 85 | case 2: 86 | // We have read a second non-empty line, so we are ready to take commands 87 | this.isConnected = true; 88 | connectionEstablished(); 89 | continue; // Welcome message, followed by empty line (which is skipped) 90 | 91 | default: { 92 | this.handleSingleLine(line); 93 | this.checkQueue(); 94 | } 95 | } 96 | } 97 | } 98 | 99 | private handleSingleLine(line: string): void { 100 | // Server answers with: 101 | // [- One line containing the answer ] 102 | // - "error id=XX msg=YY". ID is zero if command was executed successfully. 103 | if (line.startsWith("error")) { 104 | 105 | const errorResponse = line.substr("error ".length); 106 | 107 | const response = this.parseResponse(errorResponse); 108 | const executing = this._executing; 109 | 110 | if (response !== undefined && executing !== undefined) { 111 | const res = response.shift(); 112 | 113 | if (res !== undefined) { 114 | const currentError: QueryError = { 115 | id: res["id"] || 0, 116 | msg: res["msg"] || "" 117 | }; 118 | 119 | if (currentError.id !== 0) 120 | executing.error = currentError; 121 | 122 | if (executing.rejectFunction && executing.resolveFunction) { 123 | //item: executing || null, 124 | const e = executing; 125 | const data = { 126 | cmd: e.cmd, 127 | options: e.options || [], 128 | text: e.text || null, 129 | parameters: e.parameters || {}, 130 | error: e.error || null, 131 | response: e.response || null, 132 | rawResponse: e.rawResponse || null 133 | }; 134 | if (data.error && data.error.id !== 0) 135 | executing.rejectFunction(data as CallbackData); 136 | else 137 | executing.resolveFunction(data as CallbackData); 138 | } 139 | } 140 | } 141 | 142 | this._executing = undefined; 143 | this.checkQueue(); 144 | 145 | } else if (line.startsWith("notify")) { 146 | const notificationResponse = line.substr("notify".length); 147 | const response = this.parseResponse(notificationResponse); 148 | 149 | const notificationName = notificationResponse.substr(0, notificationResponse.indexOf(" ")); 150 | this.emit(notificationName, response); 151 | } else if (this._executing) { 152 | this._executing.rawResponse = line; 153 | this._executing.response = this.parseResponse(line); 154 | } 155 | } 156 | 157 | /** 158 | * Sends a command to the server 159 | */ 160 | // TODO: Only include constant overloads to force corrent parameterization 161 | 162 | // TODO: help 163 | // TODO: quit 164 | public send(cmd: "login", params: LoginParams): Promise>; 165 | public send(cmd: "logout"): Promise>; 166 | public send(cmd: "version"): Promise>; 167 | public send(cmd: "hostinfo"): Promise>; 168 | public send(cmd: "instanceinfo"): Promise>; 169 | public send(cmd: "instanceedit", params: InstanceEditParams): Promise>; 170 | public send(cmd: "bindinglist"): Promise>; 171 | public send(cmd: "use", params: UseParams): Promise>; 172 | public send(cmd: "serverlist", params: MapLike, options: string[]): Promise>; 173 | // TODO: serveridgetbyport 174 | public send(cmd: "serverdelete", params: ServerDeleteParams): Promise>; 175 | // TODO: servercreate 176 | public send(cmd: "serverstart", params: ServerStartStopParams): Promise>; 177 | public send(cmd: "serverstop", params: ServerStartStopParams): Promise>; 178 | public send(cmd: "serverprocessstop"): Promise>; 179 | public send(cmd: "serverinfo"): Promise>; 180 | public send(cmd: "serverrequestconnectioninfo"): Promise>; 181 | public send(cmd: "serveredit", params: ServerEditParams): Promise>; 182 | // TODO: servergrouplist 183 | // TODO: servergroupadd 184 | // TODO: servergroupdel 185 | // TODO: servergroupcopy 186 | // TODO: servergrouprename 187 | // TODO: servergrouppermlist 188 | // TODO: servergroupaddperm 189 | // TODO: servergroupdelperm 190 | // TODO: servergroupaddclient 191 | // TODO: servergroupdelclient 192 | // TODO: servergroupclientlist 193 | // TODO: servergroupsbyclientid 194 | // TODO: servergroupautoaddperm 195 | // TODO: servergroupautodelperm 196 | // TODO: serversnapshotcreate 197 | // TODO: serversnapshotdeploy 198 | public send(cmd: "servernotifyregister", params: RegisterNotificationsParams): Promise>; 199 | // TODO: servernotifyunregister 200 | public send(cmd: "sendtextmessage", params: SendTextMessageParams): Promise>; 201 | // TODO: logview 202 | public send(cmd: "logadd", params: LogAddParams): Promise>; 203 | public send(cmd: "gm", params: GmParams): Promise>; 204 | public send(cmd: "channellist", params: MapLike, options: string[]): Promise>; //@todo find anything to make signature better typed 205 | public send(cmd: "channelinfo", params: ChannelInfoParams): Promise> 206 | // TODO: channelfind 207 | // TODO: channelmove 208 | // TODO: channelcreate 209 | public send(cmd: "channeldelete", params: ChannelDeleteParams): Promise>; 210 | // TODO: channeledit 211 | // TODO: channelgrouplist 212 | // TODO: channelgroupadd 213 | // TODO: channelgroupdel 214 | // TODO: channelgroupcopy 215 | // TODO: channelgrouprename 216 | // TODO: channelgroupaddperm 217 | // TODO: channelgrouppermlist 218 | // TODO: channelgroupdelperm 219 | // TODO: channelgroupclientlist 220 | // TODO: setclientchannelgroup 221 | // TODO: channelpermlist 222 | // TODO: channeladdperm 223 | // TODO: channeldelperm 224 | public send(cmd: "clientlist", params: ClientListParams): Promise>; 225 | public send(cmd: "clientinfo", params: ClientInfoParams): Promise>; 226 | // TODO: clientfind 227 | // TODO: clientedit 228 | // TODO: clientdblist 229 | // TODO: clientdbinfo 230 | // TODO: clientdbfind 231 | // TODO: clientdbedit 232 | public send(cmd: "clientdbdelete", params: ClientDBDeleteParams): Promise>; 233 | // TODO: clientgetids 234 | // TODO: clientgetdbidfromuid 235 | // TODO: clientgetnamefromuid 236 | // TODO: clientgetnamefromdbid 237 | // TODO: clientsetserverquerylogin 238 | // TODO: clientupdate 239 | public send(cmd: "clientmove", params: ClientMoveParams): Promise>; 240 | public send(cmd: "clientkick", params: ClientKickParams): Promise>; 241 | public send(cmd: "clientpoke", params: ClientPokeParams): Promise>; 242 | public send(cmd: "clientpermlist", params: ClientPermListParams, options: string[]): Promise>; 243 | public send(cmd: "clientaddperm", params: ClientAddPermParams): Promise>; 244 | public send(cmd: "clientdelperm", param: ClientDeleteParams): Promise>; 245 | // TODO: channelclientpermlist 246 | // TODO: channelclientaddperm 247 | // TODO: channelclientdelperm 248 | // TODO: permissionlist 249 | // TODO: permidgetbyname 250 | // TODO: permoverview 251 | // TODO: permget 252 | // TODO: permfind 253 | // TODO: permrest 254 | // TODO: privilegekeylist 255 | // TODO: privilegekeyadd 256 | // TODO: privilegekeydelete 257 | // TODO: privilegekeyuse 258 | // TODO: messageadd 259 | public send(cmd: "messagedel", params: MessageDeleteParams): Promise>; 260 | // TODO: messageget 261 | // TODO: messageupdateflag 262 | // TODO: complainlist 263 | // TODO: complainadd 264 | public send(cmd: "complaindelall", params: ComplainDeleteAllParams): Promise>; 265 | public send(cmd: "complaindel", params: ComplainDeleteParams): Promise>; 266 | public send(cmd: "banclient", params: BanClientParams): Promise>; //@todo test 267 | public send(cmd: "banlist"): Promise>; 268 | public send(cmd: "banadd", params: BanAddParams): Promise>; 269 | public send(cmd: "bandel", params: BanDeleteParams): Promise>; 270 | public send(cmd: "bandelall"): Promise>; 271 | // TODO: ftinitupload 272 | // TODO: ftinitdownload 273 | // TODO: ftlist 274 | // TODO: ftgetfileinfo 275 | public send(cmd: "ftstop", params: FtStopParams): Promise>; 276 | // TODO: ftdeletefile 277 | // TODO: ftrenamefile 278 | // TODO: customsearch 279 | // TODO: custominfo 280 | // TODO: whoami 281 | 282 | //public send(cmd: string): Promise>; 283 | //public send(cmd: string, params: IAssoc): Promise; 284 | public send(cmd: string, params: MapLike, options: string[]): Promise>; 285 | public send(cmd: string, params: MapLike = {}, options: string[] = []): Promise> { 286 | if (!cmd) 287 | return Promise.reject>(new Error("Empty command")); 288 | 289 | if (!this.isConnected) 290 | return Promise.reject(new Error("Not connected to any server. Call \"connect()\" before sending anything.")); 291 | 292 | let tosend = escapeQueryString(cmd); 293 | for (const v of options) 294 | tosend += ` -${escapeQueryString(v)}`; 295 | 296 | for (const key in params) { 297 | if (!params.hasOwnProperty(key)) 298 | continue; 299 | const value = params[key]; 300 | if (!Array.isArray(value)) { 301 | tosend += ` ${escapeQueryString(key.toString())}=${escapeQueryString(value.toString())}`; 302 | } 303 | } 304 | 305 | // Handle multiple arrays correctly 306 | // Get all array in the params 307 | const arrayParamKeys: string[] = []; 308 | for (const key in params) { 309 | if (params.hasOwnProperty(key) && Array.isArray(params[key])) 310 | arrayParamKeys.push(key); 311 | } 312 | 313 | if (arrayParamKeys.length > 0) { 314 | let escapedSegments = ""; 315 | const firstArray = params[arrayParamKeys[0]] as string[]; 316 | for (let i = 0; i < firstArray.length; ++i) { 317 | let segment = ""; 318 | for (const key of arrayParamKeys) { 319 | segment += `${escapeQueryString(key)}=${escapeQueryString(params[key][i])} `; 320 | } 321 | escapedSegments += `${segment.slice(0, -1)}|`; 322 | } 323 | if (escapedSegments.length > 0) 324 | tosend += ` ${escapedSegments.slice(0, -1)}`; 325 | } 326 | 327 | return new Promise>((resolve, reject) => { 328 | this.queue.push({ 329 | cmd: cmd, 330 | options: options, 331 | parameters: params, 332 | text: tosend, 333 | resolveFunction: resolve, 334 | rejectFunction: reject, 335 | }); 336 | 337 | if (this.isConnected) 338 | this.checkQueue(); 339 | }); 340 | } 341 | 342 | public subscribeChannelEvents(channelId: number): Promise> { 343 | return this.send("servernotifyregister", { event: "channel", id: channelId }); 344 | } 345 | public subscribeServerEvents(): Promise> { 346 | return this.send("servernotifyregister", { event: "server" }); 347 | } 348 | public subscribeServerTextEvents(): Promise> { 349 | return this.send("servernotifyregister", { event: "textserver" }); 350 | } 351 | public subscribeChannelTextEvents(): Promise> { 352 | return this.send("servernotifyregister", { event: "textchannel" }); 353 | } 354 | public subscribePrivateTextEvents(): Promise> { 355 | return this.send("servernotifyregister", { event: "textprivate" }); 356 | } 357 | 358 | public on(event: "cliententerview", listener: (data: any) => void): this; 359 | public on(event: "clientleftview", listener: (data: any) => void): this; 360 | // server notifications 361 | public on(event: "serveredited", listener: (data: any) => void): this; 362 | // channel notifications 363 | public on(event: "channeldescriptionchanged", listener: (data: any) => void): this; 364 | public on(event: "channelpasswordchanged", listener: (data: any) => void): this; 365 | public on(event: "channelmoved", listener: (data: any) => void): this; 366 | public on(event: "channeledited", listener: (data: any) => void): this; 367 | public on(event: "channelcreated", listener: (data: any) => void): this; 368 | public on(event: "channeldeleted", listener: (data: any) => void): this; 369 | public on(event: "clientmoved", listener: (data: any) => void): this; 370 | public on(event: "textmessage", listener: (data: TextMessageNotificationData) => void): this; 371 | public on(event: "tokenused", listener: (data: any) => void): this; 372 | public on(event: "error", listener: (err: Error) => void): this; 373 | public on(event: "close", listener: (queue: QueryCommand[]) => void): this; 374 | public on(event: string, listener: (...args: any[]) => void): this { 375 | return super.on(event, listener); 376 | } 377 | 378 | public once(event: "cliententerview", listener: (data: any) => void): this; 379 | public once(event: "clientleftview", listener: (data: any) => void): this; 380 | // server notifications 381 | public once(event: "serveredited", listener: (data: any) => void): this; 382 | // channel notifications 383 | public once(event: "channeldescriptionchanged", listener: (data: any) => void): this; 384 | public once(event: "channelpasswordchanged", listener: (data: any) => void): this; 385 | public once(event: "channelmoved", listener: (data: any) => void): this; 386 | public once(event: "channeledited", listener: (data: any) => void): this; 387 | public once(event: "channelcreated", listener: (data: any) => void): this; 388 | public once(event: "channeldeleted", listener: (data: any) => void): this; 389 | public once(event: "clientmoved", listener: (data: any) => void): this; 390 | public once(event: "textmessage", listener: (data: TextMessageNotificationData) => void): this; 391 | public once(event: "tokenused", listener: (data: any) => void): this; 392 | public once(event: "error", listener: (err: Error) => void): this; 393 | public once(event: "close", listener: (queue: QueryCommand[]) => void): this; 394 | public once(event: string, listener: (...args: any[]) => void): this { 395 | return super.once(event, listener); 396 | } 397 | 398 | /** 399 | * Parses a query API response. 400 | */ 401 | private parseResponse(s: string): QueryResponseItem[] | undefined { 402 | const records = s.split("|"); 403 | // Test this 404 | const response = records.map(currentItem => { 405 | const args = currentItem.split(" "); 406 | const thisrec: QueryResponseItem = {}; 407 | 408 | for (let v of args) { 409 | if (v.indexOf("=") <= -1) { 410 | thisrec[v] = ""; 411 | continue; 412 | } 413 | const key = unescapeQueryString(v.substr(0, v.indexOf("="))); 414 | const value = unescapeQueryString(v.substr(v.indexOf("=") + 1)); 415 | thisrec[key] = (Number.parseInt(value, 10).toString() == value) ? Number.parseInt(value, 10) : value; 416 | } 417 | return thisrec; 418 | }); 419 | 420 | if (response.length === 0) 421 | return undefined; 422 | 423 | return response; 424 | } 425 | 426 | /** 427 | * Gets pending commands that are going to be sent to the server. Note that they have been parsed - Access pending[0].text to get the full text representation of the command. 428 | * @return {QueryCommand[]} Pending commands that are going to be sent to the server. 429 | */ 430 | public get pending(): QueryCommand[] { 431 | return this.queue.slice(0); 432 | } 433 | 434 | /** 435 | * Clears the queue of pending commands so that any command that is currently queued won't be executed. 436 | * @return {QueryCommand[]} Array of commands that have been removed from the queue. 437 | */ 438 | public clearPending(): QueryCommand[] { 439 | const q = this.queue; 440 | this.queue = []; 441 | return q; 442 | } 443 | 444 | /** 445 | * Checks the current command queue and sends them if needed. 446 | */ 447 | private checkQueue(): void { 448 | if (this._executing !== undefined) return; 449 | 450 | const executing = this.queue.shift(); 451 | if (executing) { 452 | this._executing = executing; 453 | this.socket.write(this._executing.text + "\n"); 454 | } 455 | } 456 | 457 | /** 458 | * Sets the socket to timeout after timeout milliseconds of inactivity on the socket. By default net.Socket do not have a timeout. 459 | */ 460 | public setTimeout(timeout: number): void { 461 | this.socket.setTimeout(timeout, () => { 462 | this.socket.destroy(); 463 | this.emit("timeout"); 464 | }); 465 | } 466 | public unsetTimeout(): void { 467 | /* 468 | * If timeout is 0, then the existing idle timeout is disabled. 469 | * See: https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback 470 | */ 471 | return this.setTimeout(0); 472 | } 473 | } 474 | 475 | /** 476 | * Represents common data returned by the api. 477 | */ 478 | export interface CallbackData { 479 | cmd?: string; 480 | options?: string[]; 481 | text?: string; 482 | parameters: MapLike; 483 | //item: QueryCommand; 484 | error: QueryError; 485 | response: T[]; 486 | rawResponse: string; 487 | 488 | // cmd?: string, 489 | // options?: string[]; 490 | // text?: string; 491 | // parameters: Object; 492 | } 493 | 494 | export interface LoginParams extends MapLike { 495 | client_login_name: string; 496 | client_login_password: string; 497 | } 498 | 499 | export interface VersionResponseData extends QueryResponseItem { 500 | version: string; 501 | build: number; 502 | platform: string; 503 | } 504 | 505 | export interface UseParams extends MapLike { 506 | sid: number; 507 | } 508 | export interface ServerListResponseData extends QueryResponseItem { 509 | //@todo 510 | virtualserver_id: number; 511 | virtualserver_port: number; 512 | virtualserver_status: string; 513 | virtualserver_clientsonline: number; 514 | } 515 | export interface ServerDeleteParams extends UseParams { } 516 | 517 | export interface ServerStartStopParams extends UseParams { } 518 | 519 | export interface ClientListResponseData extends QueryResponseItem { 520 | //TODO 521 | } 522 | export interface ClientListParams extends MapLike { } 523 | 524 | /** 525 | * Specialized callback data for a failed request. 526 | */ 527 | export interface ErrorResponseData extends QueryResponseItem { } 528 | 529 | /** 530 | * Represents common data returned by the api during a successful response. 531 | */ 532 | export interface QueryResponseItem extends MapLike { } 533 | 534 | /** 535 | * Item that represents a query error. 536 | */ 537 | export interface QueryError { 538 | /** 539 | * The error id. 540 | * @type {number} 541 | */ 542 | id: number; 543 | /** 544 | * Error message. 545 | * @type {string} 546 | */ 547 | msg: string; 548 | 549 | /** 550 | * Permission that the client does not have. 551 | * @type {number} 552 | */ 553 | failed_permid?: number; 554 | } 555 | 556 | /** 557 | * Represents an item in the processing queue for the api. 558 | */ 559 | export interface QueryCommand { 560 | cmd: string; 561 | options: string[]; 562 | parameters: MapLike; 563 | text: string; 564 | resolveFunction: (data: CallbackData) => void; 565 | rejectFunction: (reason: any) => void; 566 | 567 | response?: QueryResponseItem[]; 568 | rawResponse?: string; 569 | error?: QueryError; 570 | } 571 | 572 | /* 573 | 574 | Mostly generated API interfaces following now. 575 | Field descriptions taken from the official documentation. 576 | http://media.teamspeak.com/ts3_literature/TeamSpeak%203%20Server%20Query%20Manual.pdf 577 | 578 | */ 579 | 580 | 581 | export interface TextMessageNotificationData { 582 | targetmode: TextMessageTargetMode; 583 | msg: string; 584 | /** 585 | * only present in messages of type "textprivate 586 | */ 587 | target?: number; 588 | } 589 | 590 | /** 591 | * @todo move to seperate file 592 | * @todo check for encoding mess up/invisible chars caused by copy/pasting from the documentation PDF 593 | * @todo more discrete typings using enums/interfaces/etc 594 | * @todo lower case imported interfaces 595 | */ 596 | 597 | export interface HostInfoResponseData extends QueryResponseItem { 598 | instance_uptime: number; 599 | host_timestamp_utc: number; 600 | virtualservers_running_total: number; 601 | connection_filetransfer_bandwidth_sent: number; 602 | // TODO 603 | } 604 | 605 | export interface InstanceInfoResponseData extends QueryResponseItem { 606 | // TODO 607 | } 608 | 609 | export interface GenericResponseData extends QueryResponseItem { } 610 | 611 | export interface ServerRequstConnectionInfoResponseData extends QueryResponseItem, ServerConnectionProperties { } 612 | 613 | export interface ServerEditParams extends MapLike, VirtualServerPropertiesChangable { } 614 | 615 | export interface ServerInfoResponseData extends QueryResponseItem, VirtualServerProperties { } 616 | 617 | export interface RegisterNotificationsParamsGeneric extends QueryResponseItem { 618 | event: "server" | "textserver" | "textchannel" | "textprivate"; 619 | } 620 | export interface RegisterNotificationsChannelParams extends QueryResponseItem { 621 | event: "channel"; 622 | id: number; 623 | } 624 | 625 | export type RegisterNotificationsParams = RegisterNotificationsParamsGeneric | RegisterNotificationsChannelParams; 626 | 627 | export interface SendTextMessageParams extends QueryResponseItem { 628 | targetmode: TextMessageTargetMode; 629 | target: number; 630 | msg: string; 631 | } 632 | 633 | export interface InstanceEditParams extends MapLike, InstancePropertiesChangable { } 634 | 635 | export interface GmParams extends MapLike { 636 | msg: string; 637 | } 638 | export interface ChannelListResponseData extends QueryResponseItem { 639 | cid: number; 640 | pid: number; 641 | channel_order: number; 642 | channel_name: string; 643 | channel_topic: string; 644 | total_clients: number; 645 | } 646 | export interface ChannelInfoParams extends MapLike { 647 | cid: number; 648 | } 649 | export interface ChannelInfoResponseData extends QueryResponseItem, ChannelProperties { } 650 | 651 | export interface ChannelDeleteParams extends MapLike, ChannelInfoParams { 652 | force: YesNo; 653 | } 654 | 655 | export interface ClientInfoResponseData extends QueryResponseItem, ClientProperties { } 656 | export interface ClientInfoParams extends MapLike { 657 | clid: number; 658 | } 659 | 660 | export interface ClientDBDeleteParams extends MapLike { 661 | cldbid: number; 662 | } 663 | 664 | export interface ClientMoveParams extends MapLike { 665 | clid: number[]; 666 | cid: number; 667 | cpw?: string; 668 | } 669 | export interface ClientKickParams extends MapLike { 670 | clid: number[]; 671 | reasonid: ReasonIdentifier; 672 | reasonmsg: string; 673 | } 674 | export interface ClientPokeParams extends MapLike { 675 | clid: number; 676 | msg: string; 677 | } 678 | export interface ClientPermListParams extends MapLike { 679 | cldbid: number; 680 | } 681 | export interface ClientPermListResponseData extends QueryResponseItem { 682 | cldbid?: number; 683 | permid: number; 684 | permvalue: number; 685 | permnegated: YesNo; 686 | permskip: number; 687 | } 688 | export interface ClientAddPermParams extends MapLike { 689 | cldbid: number; 690 | permid?: number[]; 691 | permsid?: string[]; 692 | permvalue: number[]; 693 | permskip: YesNo[]; 694 | } 695 | export interface ClientDeleteParams extends MapLike { 696 | cldbid: number; 697 | permid: number[]; 698 | permsid: string[]; 699 | } 700 | 701 | export interface MessageDeleteParams extends MapLike { 702 | msgid: number; 703 | } 704 | 705 | export interface ComplainDeleteAllParams extends MapLike { 706 | tcldbid: number; 707 | } 708 | export interface ComplainDeleteParams extends MapLike { 709 | tcldbid: number; 710 | fcldbid: number; 711 | } 712 | export interface BanClientParams extends MapLike { 713 | clid: number; 714 | time?: number; 715 | banreason?: string; 716 | } 717 | 718 | export interface BanListResponseData extends QueryResponseItem { 719 | banid: number; 720 | ip: string; 721 | created: number; 722 | invokername: string; 723 | invokercldbid: number; 724 | invokeruid: string; 725 | reason: string; 726 | enforcements: number; 727 | } 728 | 729 | export interface BanAddParams extends MapLike { 730 | ip?: string; 731 | name?: string; 732 | uid?: string; 733 | time?: number; 734 | banreason?: string; 735 | } 736 | export interface BanDeleteParams extends MapLike { 737 | banid: number; 738 | } 739 | 740 | export interface FtStopParams extends MapLike { 741 | serverftfid: number; 742 | delete: YesNo; 743 | } 744 | 745 | export interface LogAddParams extends MapLike { 746 | loglevel: LogLevel; 747 | logmsg: string; 748 | } 749 | 750 | export interface InstancePropertiesChangable { 751 | /** 752 | * Default ServerQuery group ID 753 | */ 754 | serverinstance_guest_serverquery_group: any; 755 | /** 756 | * Default template group ID for administrators on new virtual servers (used to create initial token) 757 | */ 758 | serverinstance_template_serveradmin_group: any; 759 | /** 760 | * TCP port used for file transfers 761 | */ 762 | serverinstance_filetransfer_port: number; 763 | /** 764 | * Max bandwidth available for outgoing file transfers (Bytes/s) 765 | */ 766 | serverinstance_max_download_total_bandwitdh: number; 767 | /** 768 | * Max bandwidth available for incoming file transfers (Bytes/s) 769 | */ 770 | serverinstance_max_upload_total_bandwitdh: number; 771 | /** 772 | * Default server group ID used in templates 773 | */ 774 | serverinstance_template_serverdefault_group: any; 775 | /** 776 | * Default channel group ID used in templates 777 | */ 778 | serverinstance_template_channeldefault_group: any; 779 | /** 780 | * Default channel administrator group ID used in templates 781 | */ 782 | serverinstance_template_channeladmin_group: any; 783 | /** 784 | * Max number of commands allowed in seconds 785 | */ 786 | serverinstance_serverquery_flood_commands: number; 787 | /** 788 | * Timeframe in seconds for commands 789 | */ 790 | serverinstance_serverquery_flood_time: number; 791 | /** 792 | * Time in seconds used for automatic bans triggered by the ServerQuery flood protection 793 | */ 794 | serverinstance_serverquery_flood_ban_time: number; 795 | } 796 | 797 | interface InstancePropertiesReadOnly extends ServerConnectionProperties { 798 | /** 799 | * Uptime in seconds 800 | */ 801 | instance_uptime: number; 802 | /** 803 | * Current server date and time as UTC timestamp 804 | */ 805 | host_timestamp_utc: any; 806 | /** 807 | * Number of virtual servers running 808 | */ 809 | virtualservers_running_total: number; 810 | /** 811 | * Database revision number 812 | */ 813 | serverinstance_database_version: any; 814 | /** 815 | * Max number of clients for all virtual servers 816 | */ 817 | virtualservers_total_maxclients: number; 818 | /** 819 | * Number of clients online on all virtual servers 820 | */ 821 | virtualservers_total_clients_online: number; 822 | /** 823 | * Number of channels on all virtual servers 824 | */ 825 | virtualservers_total_channels_online: number; 826 | } 827 | 828 | interface InstanceProperties extends InstancePropertiesReadOnly, InstancePropertiesChangable { } 829 | 830 | export interface BindingListResponseData extends QueryResponseItem { 831 | //TODO 832 | } 833 | 834 | export interface VirtualServerPropertiesChangable { 835 | /** 836 | * Name of the virtual server 837 | */ 838 | virtualserver_name: string; 839 | /** 840 | * Welcome message of the virtual server 841 | */ 842 | virtualserver_welcomemessage: string; 843 | /** 844 | * Number of slots available on the virtual server 845 | */ 846 | virtualserver_maxclients: number; 847 | /** 848 | * Password of the virtual server 849 | */ 850 | virtualserver_password: string; 851 | /** 852 | * Host message of the virtual server 853 | */ 854 | virtualserver_hostmessage: string; 855 | /** 856 | * Host message mode of the virtual server (see Definitions) 857 | */ 858 | virtualserver_hostmessage_mode: any; 859 | /** 860 | * Default server group ID 861 | */ 862 | virtualserver_default_server_group: any; 863 | /** 864 | * Default channel group ID 865 | */ 866 | virtualserver_default_channel_group: any; 867 | /** 868 | * Default channel administrator group ID 869 | */ 870 | virtualserver_default_channel_admin_group: any; 871 | /** 872 | * Max bandwidth for outgoing file transfers on the virtual server (Bytes/s) 873 | */ 874 | virtualserver_max_download_total_bandwidth: number; 875 | /** 876 | * Max bandwidth for incoming file transfers on the virtual server (Bytes/s) 877 | */ 878 | virtualserver_max_upload_total_bandwidth: number; 879 | /** 880 | * Host banner URL opened on click 881 | */ 882 | virtualserver_hostbanner_url: string; 883 | /** 884 | * Host banner URL used as image source 885 | */ 886 | virtualserver_hostbanner_gfx_url: string; 887 | /** 888 | * Interval for reloading the banner on client-side 889 | */ 890 | virtualserver_hostbanner_gfx_interval: any; 891 | /** 892 | * Number of complaints needed to ban a client automatically 893 | */ 894 | virtualserver_complain_autoban_count: number; 895 | /** 896 | * Time in seconds used for automatic bans triggered by complaints 897 | */ 898 | virtualserver_complain_autoban_time: number; 899 | /** 900 | * Time in seconds before a complaint is deleted automatically 901 | */ 902 | virtualserver_complain_remove_time: number; 903 | /** 904 | * Number of clients in the same channel needed to force silence 905 | */ 906 | virtualserver_min_clients_in_channel_before_forced_silence: number; 907 | /** 908 | * Client volume lowered automatically while a priority speaker is talking 909 | */ 910 | virtualserver_priority_speaker_dimm_modificator: any; 911 | /** 912 | * Anti-flood points removed from a client for being good 913 | */ 914 | virtualserver_antiflood_points_tick_reduce: any; 915 | /** 916 | * Anti-flood points needed to block commands being executed by the client 917 | */ 918 | virtualserver_antiflood_points_needed_command_block: any; 919 | /** 920 | * Anti-flood points needed to block incoming connections from the client 921 | */ 922 | virtualserver_antiflood_points_needed_ip_block: any; 923 | /** 924 | * The display mode for the virtual servers hostbanner (see Definitions) 925 | */ 926 | virtualserver_hostbanner_mode: any; 927 | /** 928 | * Text used for the tooltip of the host button on client-side 929 | */ 930 | virtualserver_hostbutton_tooltip: string; 931 | /** 932 | * Text used for the tooltip of the host button on client-side 933 | */ 934 | virtualserver_hostbutton_gfx_url: string; 935 | /** 936 | * URL opened on click on the host button 937 | */ 938 | virtualserver_hostbutton_url: string; 939 | /** 940 | * Download quota for the virtual server (MByte) 941 | */ 942 | virtualserver_download_quota: number; 943 | /** 944 | * Download quota for the virtual server (MByte) 945 | */ 946 | virtualserver_upload_quota: number; 947 | /** 948 | * Machine ID identifying the server instance associated with the virtual server in the database 949 | */ 950 | virtualserver_machine_id: any; 951 | /** 952 | * UDP port the virtual server is listening on 953 | */ 954 | virtualserver_port: number; 955 | /** 956 | * Indicates whether the server starts automatically with the server instance or not 957 | */ 958 | virtualserver_autostart: any; 959 | /** 960 | * Status of the virtual server (online | virtual online | offline | booting up | shutting down | …) 961 | */ 962 | virtualserver_status: string; 963 | /** 964 | * Indicates whether the server logs events related to clients or not 965 | */ 966 | virtualserver_log_client: any; 967 | /** 968 | * Indicates whether the server logs events related to ServerQuery clients or not 969 | */ 970 | virtualserver_log_query: any; 971 | /** 972 | * Indicates whether the server logs events related to channels or not 973 | */ 974 | virtualserver_log_channel: any; 975 | /** 976 | * Indicates whether the server logs events related to permissions or not 977 | */ 978 | virtualserver_log_permissions: any; 979 | /** 980 | * Indicates whether the server logs events related to server changes or not 981 | */ 982 | virtualserver_log_server: any; 983 | /** 984 | * Indicates whether the server logs events related to file transfers or not 985 | */ 986 | virtualserver_log_filetransfer: any; 987 | /** 988 | * Min client version required to connect 989 | */ 990 | virtualserver_min_client_version: any; 991 | /** 992 | * Minimum client identity security level required to connect to the virtual server 993 | */ 994 | virtualserver_needed_identity_security_level: any; 995 | /** 996 | * Phonetic name of the virtual server 997 | */ 998 | virtualserver_name_phonetic: any; 999 | /** 1000 | * CRC32 checksum of the virtual server icon 1001 | */ 1002 | virtualserver_icon_id: any; 1003 | /** 1004 | * Number of reserved slots available on the virtual server 1005 | */ 1006 | virtualserver_reserved_slots: number; 1007 | /** 1008 | * Indicates whether the server appears in the global web server list or not 1009 | */ 1010 | virtualserver_weblist_enabled: any; 1011 | /** 1012 | * The global codec encryption mode of the virtual server 1013 | */ 1014 | virtualserver_codec_encryption_mode: any; 1015 | } 1016 | 1017 | export interface ServerConnectionProperties { 1018 | /** 1019 | * Current bandwidth used for outgoing file transfers (Bytes/s) 1020 | */ 1021 | connection_filetransfer_bandwidth_sent: number; 1022 | /** 1023 | * Current bandwidth used for incoming file transfers (Bytes/s) 1024 | */ 1025 | connection_filetransfer_bandwidth_received: number; 1026 | /** 1027 | * Total amount of packets sent 1028 | */ 1029 | connection_packets_sent_total: number; 1030 | /** 1031 | * Total amount of packets received 1032 | */ 1033 | connection_packets_received_total: number; 1034 | /** 1035 | * Total amount of bytes sent 1036 | */ 1037 | connection_bytes_sent_total: number; 1038 | /** 1039 | * Total amount of bytes received 1040 | */ 1041 | connection_bytes_received_total: number; 1042 | /** 1043 | * Average bandwidth used for outgoing data in the last second (Bytes/s) 1044 | */ 1045 | connection_bandwidth_sent_last_second_total: number; 1046 | /** 1047 | * Average bandwidth used for incoming data in the last second (Bytes/s) 1048 | */ 1049 | connection_bandwidth_received_last_second_total: number; 1050 | /** 1051 | * Average bandwidth used for outgoing data in the last minute (Bytes/s) 1052 | */ 1053 | connection_bandwidth_sent_last_minute_total: number; 1054 | /** 1055 | * Average bandwidth used for incoming data in the last minute (Bytes/s) 1056 | */ 1057 | connection_bandwidth_received_last_minute_total: number; 1058 | } 1059 | 1060 | export interface VirtualServerPropertiesReadOnly extends ServerConnectionProperties { 1061 | /** 1062 | * Indicates whether the server has a password set or not 1063 | */ 1064 | virtualserver_flag_password: any; 1065 | /** 1066 | * Number of clients connected to the virtual server 1067 | */ 1068 | virtualserver_clientsonline: number; 1069 | /** 1070 | * Number of ServerQuery clients connected to the virtual server 1071 | */ 1072 | virtualserver_queryclientsonline: number; 1073 | /** 1074 | * Number of channels created on the virtual server 1075 | */ 1076 | virtualserver_channelsonline: number; 1077 | /** 1078 | * Creation date and time of the virtual server as UTC timestamp 1079 | */ 1080 | virtualserver_created: any; 1081 | /** 1082 | * Uptime in seconds 1083 | */ 1084 | virtualserver_uptime: number; 1085 | /** 1086 | * Operating system the server is running on 1087 | */ 1088 | virtualserver_platform: string; 1089 | /** 1090 | * Server version information including build number 1091 | */ 1092 | virtualserver_version: any; 1093 | /** 1094 | * Indicates whether the initial privilege key for the virtual server has been used or not 1095 | */ 1096 | virtualserver_ask_for_privilegekey: any; 1097 | /** 1098 | * Total number of clients connected to the virtual server since it was last started 1099 | */ 1100 | virtualserver_client_connections: number; 1101 | /** 1102 | * Total number of ServerQuery clients connected to the virtual server since it was last started 1103 | */ 1104 | virtualserver_query_client_connections: number; 1105 | /** 1106 | * Number of bytes downloaded from the virtual server on the current month 1107 | */ 1108 | virtualserver_month_bytes_downloaded: number; 1109 | /** 1110 | * Number of bytes uploaded to the virtual server on the current month 1111 | */ 1112 | virtualserver_month_bytes_uploaded: number; 1113 | /** 1114 | * Number of bytes downloaded from the virtual server since it was last started 1115 | */ 1116 | virtualserver_total_bytes_downloaded: number; 1117 | /** 1118 | * Number of bytes uploaded to the virtual server since it was last started 1119 | */ 1120 | virtualserver_total_bytes_uploaded: number; 1121 | /** 1122 | * Unique ID of the virtual server 1123 | */ 1124 | virtualserver_unique_identifer: any; 1125 | /** 1126 | * Database ID of the virtual server 1127 | */ 1128 | virtualserver_id: any; 1129 | /** 1130 | * The average packet loss for speech data on the virtual server 1131 | */ 1132 | virtualserver_total_packetloss_speech: number; 1133 | /** 1134 | * The average packet loss for keepalive data on the virtual server 1135 | */ 1136 | virtualserver_total_packetloss_keepalive: number; 1137 | /** 1138 | * The average packet loss for control data on the virtual server 1139 | */ 1140 | virtualserver_total_packetloss_control: number; 1141 | /** 1142 | * The average packet loss for all data on the virtual server 1143 | */ 1144 | virtualserver_total_packetloss_total: number; 1145 | /** 1146 | * The average ping of all clients connected to the virtual server 1147 | */ 1148 | virtualserver_total_ping: number; 1149 | /** 1150 | * The IPv4 address the virtual server is listening on 1151 | */ 1152 | virtualserver_ip: any; 1153 | /** 1154 | * The directory where the virtual servers filebase is located 1155 | */ 1156 | virtualserver_filebase: string; 1157 | } 1158 | 1159 | export interface VirtualServerProperties extends VirtualServerPropertiesReadOnly, VirtualServerPropertiesChangable { } 1160 | 1161 | export interface ChannelPropertiesChangable { 1162 | /** 1163 | * Name of the channel 1164 | */ 1165 | channel_name: string; 1166 | /** 1167 | * Topic of the channel 1168 | */ 1169 | channel_topic: string; 1170 | /** 1171 | * Description of the channel 1172 | */ 1173 | channel_description: string; 1174 | /** 1175 | * Password of the channel 1176 | */ 1177 | channel_password: string; 1178 | /** 1179 | * Codec used by the channel (see Definitions) 1180 | */ 1181 | channel_codec: Codec; 1182 | /** 1183 | * Codec quality used by the channel 1184 | */ 1185 | channel_codec_quality: any; 1186 | /** 1187 | * Individual max number of clients for the channel 1188 | */ 1189 | channel_maxclients: number; 1190 | /** 1191 | * Individual max number of clients for the channel family 1192 | */ 1193 | channel_maxfamilyclients: number; 1194 | /** 1195 | * ID of the channel below which the channel is positioned 1196 | */ 1197 | channel_order: number; 1198 | /** 1199 | * Indicates whether the channel is permanent or not 1200 | */ 1201 | channel_flag_permanent: any; 1202 | /** 1203 | * Indicates whether the channel is semi-permanent or not 1204 | */ 1205 | channel_flag_semi_permanent: any; 1206 | /** 1207 | * Indicates whether the channel is temporary or not 1208 | */ 1209 | channel_flag_temporary: any; 1210 | /** 1211 | * Indicates whether the channel is the virtual servers default channel or not 1212 | */ 1213 | channel_flag_default: any; 1214 | /** 1215 | * Indicates whether the channel has a max clients limit or not 1216 | */ 1217 | channel_flag_maxclients_unlimited: any; 1218 | /** 1219 | * Indicates whether the channel has a max family clients limit or not 1220 | */ 1221 | channel_flag_maxfamilyclients_unlimited: any; 1222 | /** 1223 | * Indicates whether the channel inherits the max family clients from his parent channel or not 1224 | */ 1225 | channel_flag_maxfamilyclients_inherited: any; 1226 | /** 1227 | * Needed talk power for this channel 1228 | */ 1229 | channel_needed_talk_power: any; 1230 | /** 1231 | * Phonetic name of the channel 1232 | */ 1233 | channel_name_phonetic: string; 1234 | /** 1235 | * CRC32 checksum of the channel icon 1236 | */ 1237 | channel_icon_id: any; 1238 | /** 1239 | * Indicates whether speech data transmitted in this channel is encrypted or not 1240 | */ 1241 | channel_codec_is_unencrypted: any; 1242 | /** 1243 | * The channels parent ID 1244 | */ 1245 | CPID: number; 1246 | } 1247 | 1248 | export interface ChannelPropertiesReadOnly { 1249 | /** 1250 | * Indicates whether the channel has a password set or not 1251 | */ 1252 | channel_flag_password: any; 1253 | /** 1254 | * Path of the channels file repository 1255 | */ 1256 | channel_filepath: string; 1257 | /** 1258 | * Indicates whether the channel is silenced or not 1259 | */ 1260 | channel_forced_silence: any; 1261 | /** 1262 | * The channels ID 1263 | */ 1264 | cid: number; 1265 | } 1266 | 1267 | export interface ChannelProperties extends ChannelPropertiesReadOnly, ChannelPropertiesChangable { } 1268 | 1269 | export interface ClientPropertiesChangable { 1270 | /** 1271 | * Nickname of the client 1272 | */ 1273 | client_nickname: string; 1274 | /** 1275 | * Indicates whether the client is able to talk or not 1276 | */ 1277 | client_is_talker: any; 1278 | /** 1279 | * Brief description of the client 1280 | */ 1281 | client_description: string; 1282 | /** 1283 | * Indicates whether the client is a channel commander or not 1284 | */ 1285 | client_is_channel_commander: any; 1286 | /** 1287 | * CRC32 checksum of the client icon 1288 | */ 1289 | client_icon_id: any; 1290 | } 1291 | export interface ClientPropertiesReadOnly { 1292 | /** 1293 | * Unique ID of the client 1294 | */ 1295 | client_unique_identifier: any; 1296 | /** 1297 | * Client version information including build number 1298 | */ 1299 | client_version: any; 1300 | /** 1301 | * Operating system the client is running on 1302 | */ 1303 | client_platform: any; 1304 | /** 1305 | * Indicates whether the client has their microphone muted or not 1306 | */ 1307 | client_input_muted: any; 1308 | /** 1309 | * Indicates whether the client has their speakers muted or not 1310 | */ 1311 | client_output_muted: any; 1312 | /** 1313 | * Indicates whether the client has enabled their capture device or not 1314 | */ 1315 | client_input_hardware: any; 1316 | /** 1317 | * Indicates whether the client has enabled their playback device or not 1318 | */ 1319 | client_output_hardware: any; 1320 | /** 1321 | * Default channel of the client 1322 | */ 1323 | client_default_channel: any; 1324 | /** 1325 | * Username of a ServerQuery client 1326 | */ 1327 | client_login_name: any; 1328 | /** 1329 | * Database ID of the client 1330 | */ 1331 | client_database_id: any; 1332 | /** 1333 | * Current channel group ID of the client 1334 | */ 1335 | client_channel_group_id: any; 1336 | /** 1337 | * Current server group IDs of the client separated by a comma 1338 | */ 1339 | client_server_groups: any; 1340 | /** 1341 | * Creation date and time of the clients first connection to the server as UTC timestamp 1342 | */ 1343 | client_created: any; 1344 | /** 1345 | * Creation date and time of the clients last connection to the server as UTC timestamp 1346 | */ 1347 | client_lastconnected: any; 1348 | /** 1349 | * Total number of connections from this client since the server was started 1350 | */ 1351 | client_totalconnections: any; 1352 | /** 1353 | * Indicates whether the client is away or not 1354 | */ 1355 | client_away: any; 1356 | /** 1357 | * Away message of the client 1358 | */ 1359 | client_away_message: any; 1360 | /** 1361 | * Indicates whether the client is a ServerQuery client or not 1362 | */ 1363 | client_type: any; 1364 | /** 1365 | * Indicates whether the client has set an avatar or not 1366 | */ 1367 | client_flag_avatar: any; 1368 | /** 1369 | * The clients current talk power 1370 | */ 1371 | client_talk_power: any; 1372 | /** 1373 | * Indicates whether the client is requesting talk power or not 1374 | */ 1375 | client_talk_request: any; 1376 | /** 1377 | * The clients current talk power request message 1378 | */ 1379 | client_talk_request_msg: any; 1380 | /** 1381 | * Number of bytes downloaded by the client on the current month 1382 | */ 1383 | client_month_bytes_downloaded: any; 1384 | /** 1385 | * Number of bytes uploaded by the client on the current month 1386 | */ 1387 | client_month_bytes_uploaded: any; 1388 | /** 1389 | * Number of bytes downloaded by the client since the server was started 1390 | */ 1391 | client_total_bytes_downloaded: any; 1392 | /** 1393 | * Number of bytes uploaded by the client since the server was started 1394 | */ 1395 | client_total_bytes_uploaded: any; 1396 | /** 1397 | * Indicates whether the client is a priority speaker or not 1398 | */ 1399 | client_is_priority_speaker: any; 1400 | /** 1401 | * Number of unread offline messages in this clients inbox 1402 | */ 1403 | client_unread_messages: any; 1404 | /** 1405 | * Phonetic name of the client 1406 | */ 1407 | client_nickname_phonetic: any; 1408 | /** 1409 | * The clients current ServerQuery view power 1410 | */ 1411 | client_needed_serverquery_view_power: any; 1412 | /** 1413 | * Current bandwidth used for outgoing file transfers (Bytes/s) 1414 | */ 1415 | connection_filetransfer_bandwidth_sent: any; 1416 | /** 1417 | * Current bandwidth used for incoming file transfers (Bytes/s) 1418 | */ 1419 | connection_filetransfer_bandwidth_received: any; 1420 | /** 1421 | * Total amount of packets sent 1422 | */ 1423 | connection_packets_sent_total: any; 1424 | /** 1425 | * Total amount of packets received 1426 | */ 1427 | connection_packets_received_total: any; 1428 | /** 1429 | * Total amount of bytes sent 1430 | */ 1431 | connection_bytes_sent_total: any; 1432 | /** 1433 | * Total amount of bytes received 1434 | */ 1435 | connection_bytes_received_total: any; 1436 | /** 1437 | * Average bandwidth used for outgoing data in the last second (Bytes/s) 1438 | */ 1439 | connection_bandwidth_sent_last_second_total: any; 1440 | /** 1441 | * Average bandwidth used for incoming data in the last second (Bytes/s) 1442 | */ 1443 | connection_bandwidth_received_last_second_total: any; 1444 | /** 1445 | * Average bandwidth used for outgoing data in the last minute (Bytes/s) 1446 | */ 1447 | connection_bandwidth_sent_last_minute_total: any; 1448 | /** 1449 | * Average bandwidth used for incoming data in the last minute (Bytes/s) 1450 | */ 1451 | connection_bandwidth_received_last_minute_total: any; 1452 | /** 1453 | * The IPv4 address of the client 1454 | */ 1455 | connection_client_ip: any; 1456 | /** 1457 | * The country identifier of the client (i.e. DE) 1458 | */ 1459 | client_country: any; 1460 | } 1461 | 1462 | export interface ClientProperties extends ClientPropertiesReadOnly, ClientPropertiesChangable { } 1463 | 1464 | /* 1465 | 1466 | Enums imported from documentation. 1467 | 1468 | */ 1469 | 1470 | export enum YesNo { 1471 | No = 0, 1472 | Yes = 1 1473 | } 1474 | 1475 | export enum HostMessageMode { 1476 | /** 1477 | * 1: display message in chatlog 1478 | */ 1479 | LOG = 1, 1480 | /** 1481 | * 2: display message in modal dialog 1482 | */ 1483 | MODAL, 1484 | /** 1485 | * 3: display message in modal dialog and close connection 1486 | */ 1487 | MODALQUIT, 1488 | } 1489 | 1490 | export enum HostBannerMode { 1491 | /** 1492 | * 0: do not adjust 1493 | */ 1494 | NOADJUST = 0, 1495 | /** 1496 | * 1: adjust but ignore aspect ratio (like TeamSpeak 2) 1497 | */ 1498 | IGNOREASPECT, 1499 | /** 1500 | * 2: adjust and keep aspect ratio 1501 | */ 1502 | KEEPASPECT, 1503 | } 1504 | 1505 | export enum Codec { 1506 | /** 1507 | * 0: speex narrowband (mono, 16bit, 8kHz) 1508 | */ 1509 | SPEEX_NARROWBAND = 0, 1510 | /** 1511 | * 1: speex wideband (mono, 16bit, 16kHz) 1512 | */ 1513 | SPEEX_WIDEBAND, 1514 | /** 1515 | * 2: speex ultra-wideband (mono, 16bit, 32kHz) 1516 | */ 1517 | SPEEX_ULTRAWIDEBAND, 1518 | /** 1519 | * 3: celt mono (mono, 16bit, 48kHz) 1520 | */ 1521 | CELT_MONO, 1522 | } 1523 | 1524 | export enum CodecEncryptionMode { 1525 | /** 1526 | * 0: configure per channel 1527 | */ 1528 | INDIVIDUAL = 0, 1529 | /** 1530 | * 1: globally disabled 1531 | */ 1532 | DISABLED, 1533 | /** 1534 | * 2: globally enabled 1535 | */ 1536 | ENABLED, 1537 | } 1538 | 1539 | export enum TextMessageTargetMode { 1540 | /** 1541 | * 1: target is a client 1542 | */ 1543 | CLIENT = 1, 1544 | /** 1545 | * 2: target is a channel 1546 | */ 1547 | CHANNEL, 1548 | /** 1549 | * 3: target is a virtual server 1550 | */ 1551 | SERVER, 1552 | } 1553 | 1554 | export enum LogLevel { 1555 | /** 1556 | * 1: everything that is really bad 1557 | */ 1558 | ERROR = 1, 1559 | /** 1560 | * 2: everything that might be bad 1561 | */ 1562 | WARNING, 1563 | /** 1564 | * 3: output that might help find a problem 1565 | */ 1566 | DEBUG, 1567 | /** 1568 | * 4: informational output 1569 | */ 1570 | INFO, 1571 | } 1572 | 1573 | export enum ReasonIdentifier { 1574 | /** 1575 | * 4: kick client from channel 1576 | */ 1577 | CHANNEL = 4, 1578 | /** 1579 | * 5: kick client from server 1580 | */ 1581 | SERVER, 1582 | } 1583 | 1584 | export enum PermissionGroupDatabaseTypes { 1585 | /** 1586 | * 0: template group (used for new virtual servers) 1587 | */ 1588 | TEMPLATE = 0, 1589 | /** 1590 | * 1: regular group (used for regular clients) 1591 | */ 1592 | REGULAR, 1593 | /** 1594 | * 2: global query group (used for ServerQuery clients) 1595 | */ 1596 | QUERY, 1597 | } 1598 | 1599 | export enum PermissionGroupTypes { 1600 | /** 1601 | * 0: server group permission 1602 | */ 1603 | SERVER_GROUP = 0, 1604 | /** 1605 | * 1: client specific permission 1606 | */ 1607 | GLOBAL_CLIENT, 1608 | /** 1609 | * 2: channel specific permission 1610 | */ 1611 | CHANNEL, 1612 | /** 1613 | * 3: channel group permission 1614 | */ 1615 | CHANNEL_GROUP, 1616 | /** 1617 | * 4: channel-client specific permission 1618 | */ 1619 | CHANNEL_CLIENT, 1620 | } 1621 | 1622 | export enum TokenType { 1623 | /** 1624 | * 0: server group token (id1={groupID} id2=0) 1625 | */ 1626 | SERVER_GROUP = 0, 1627 | /** 1628 | * 1: channel group token (id1={groupID} id2={channelID}) 1629 | */ 1630 | CHANNEL_GROUP, 1631 | } 1632 | -------------------------------------------------------------------------------- /src/queryStrings.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Escapes a string so it can be safely used for querying the api. 3 | * @param {string} s The string to escape. 4 | * @return {string} An escaped string. 5 | */ 6 | export function escapeQueryString(s: string): string { 7 | let r = String(s); 8 | r = r.replace(/\\/g, "\\\\"); // Backslash 9 | r = r.replace(/\//g, "\\/"); // Slash 10 | r = r.replace(/\|/g, "\\p"); // Pipe 11 | r = r.replace(/\n/g, "\\n"); // Newline 12 | r = r.replace(/\r/g, "\\r"); // Carriage Return 13 | r = r.replace(/\t/g, "\\t"); // Tab 14 | r = r.replace(/\v/g, "\\v"); // Vertical Tab 15 | r = r.replace(/\f/g, "\\f"); // Formfeed 16 | r = r.replace(/ /g, "\\s"); // Whitespace 17 | return r; 18 | } 19 | 20 | /** 21 | * Unescapes a string so it can be used for processing the response of the api. 22 | * @param {string} s The string to unescape. 23 | * @return {string} An unescaped string. 24 | */ 25 | export function unescapeQueryString(s: string): string { 26 | let r = String(s); 27 | r = r.replace(/\\s/g, " "); // Whitespace 28 | r = r.replace(/\\p/g, "|"); // Pipe 29 | r = r.replace(/\\n/g, "\n"); // Newline 30 | r = r.replace(/\\f/g, "\f"); // Formfeed 31 | r = r.replace(/\\r/g, "\r"); // Carriage Return 32 | r = r.replace(/\\t/g, "\t"); // Tab 33 | r = r.replace(/\\v/g, "\v"); // Vertical Tab 34 | r = r.replace(/\\\//g, "\/"); // Slash 35 | r = r.replace(/\\\\/g, "\\"); // Backslash 36 | return r; 37 | } 38 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "esnext", 4 | "moduleResolution": "node", 5 | "target": "es2022", 6 | 7 | "outDir": "lib", 8 | "strict": true, 9 | "declaration": true 10 | } 11 | } 12 | --------------------------------------------------------------------------------