{"version":3,"sources":["jsdelivr-header.js","/npm/teamspeak-server-query@1.2.2/Serverquery.js"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA,ACNA,aAEA,MAAM,OAAS,QAAQ,UACjB,IAAM,QAAQ,OAEpB,MAAM,oBAAoB,OACxB,WAAA,CAAY,EAAU,CAAC,SAAS,IAC9B,QAEA,KAAK,WAAY,EACjB,KAAK,QAAU,EAAQ,QACvB,KAAK,OAAS,KACd,KAAK,YAAc,CACjB,SACA,YACA,SACA,YACA,UACA,cACA,iBACA,uBACA,uBACA,wBACA,gBACA,gBACA,iBACA,cACA,cACA,kBACA,sBACA,yBACA,mBACA,kBACA,sBACA,mBACA,uBACA,qBACA,cACA,cACA,cACA,kBACA,gBACA,iBACA,eACA,eACA,eACA,eACA,gBACA,aACA,aACA,uBACA,eACA,wBACA,uBACA,uBACA,aACA,aACA,aACA,aACA,iBACA,aACA,4BACA,eACA,cACA,cACA,iBACA,eACA,aACA,eACA,YACA,eACA,cACA,eACA,gBACA,gBACA,iBACA,eACA,SACA,eACA,SACA,KACA,OACA,WACA,eACA,eACA,SACA,QACA,SACA,UACA,aACA,aACA,aACA,cACA,oBACA,WACA,UACA,kBACA,iBACA,eACA,YACA,kBACA,qBACA,mBACA,kBACA,OACA,kBACA,eACA,eACA,aACA,iBACA,uBACA,qBACA,yBACA,yBACA,wBACA,kBACA,iBACA,uBACA,qBACA,kBACA,sBACA,oBACA,yBACA,oBACA,aACA,aACA,uBACA,yBACA,oBACA,8BACA,uBACA,uBACA,cACA,aACA,wBACA,wBACA,yBACA,wBACA,WACA,cACA,YACA,WACA,MACA,UACA,UAGF,KAAK,kBACP,CAEA,OAAA,CAAQ,GACN,OAAO,IAAI,SAAQ,CAAC,EAAS,KAC3B,KAAK,OAAS,IAAI,IAAI,OAEtB,KAAK,kBAAkB,EAAQ,KAE/B,KAAK,OAAO,YAAY,QAExB,KAAK,OAAO,QAAQ,GAEpB,KAAK,OAAO,KAAK,WAAW,IAAM,KAAK,sBAAsB,EAAS,KAEtE,KAAK,OAAO,KAAK,SAAS,GAAO,KAAK,gBAAgB,EAAK,KAE3D,KAAK,OAAO,GAAG,SAAS,IAAM,KAAK,mBAAiB,GAExD,CAOA,qBAAA,CAAsB,EAAS,GAC7B,IAAI,EAAe,IACwB,QAAtC,EAAK,MAAM,MAAM,GAAG,eACrB,KAAK,WAAY,EAEjB,KAAK,oBAEL,EAAQ,KAER,KAAK,WAAY,EAEjB,EAAO,IAAI,MAAM,8BAGnB,KAAK,OAAO,eAAe,OAAQ,EAAY,EAGjD,KAAK,OAAO,GAAG,OAAQ,EACzB,CAOA,eAAA,CAAgB,EAAK,GACnB,KAAK,WAAY,EAEjB,KAAK,OAAO,UACZ,KAAK,OAAO,QAEZ,EAAO,EACT,CAMA,iBAAA,CAAkB,EAAQ,GACxB,YAAW,KACN,KAAK,OAAO,aACb,KAAK,WAAY,EAEjB,KAAK,OAAO,UACZ,KAAK,OAAO,QAEZ,EAAO,IAAI,MAAM,YACnB,GACC,EACL,CAKA,eAAA,GACE,KAAK,WAAY,EAEjB,KAAK,KAAK,QACZ,CAQA,gBAAA,GACE,IAAI,IAAI,KAAW,KAAK,YACtB,OAAO,eAAe,YAAY,UAAW,EAAS,CACpD,KAAA,CAAM,GAGJ,OAFA,KAAK,SAAW,QAAQ,IAAI,GAAG,KAAW,KAAK,gBAAgB,MAExD,KAAK,KAAK,GAAG,KAAW,KAAK,gBAAgB,MAAU,MAAK,GAAO,KAAK,aAAa,IAC9F,EACA,UAAU,EACV,YAAY,EACZ,cAAc,GAGpB,CAQA,IAAA,CAAK,GACH,OAAO,IAAI,SAAQ,CAAC,EAAS,KAC3B,KAAK,OAAO,KAAK,SAAS,GAAO,EAAO,KAExC,IAAI,EAAO,GACP,EAAe,yCACf,EAAmB,IACrB,GAAQ,EAER,IAAI,IAAI,KAAQ,EAAS,MAAM,MAC7B,EAAO,EAAK,OAET,EAAa,KAAK,KACnB,EAAQ,EAAK,MAAM,MAAM,IAGzB,KAAK,OAAO,eAAe,OAAQ,GACnC,KAAK,OAAO,mBAAmB,SAEnC,EAGF,KAAK,OAAO,MAAM,GAAG,MAAS,QAAQ,KACpC,KAAK,OAAO,GAAG,OAAQ,EAAgB,GACxC,GAEL,CAQA,iBAAA,GACE,IAAI,EAAS,UAEb,KAAK,OAAO,GAAG,QAAQ,IAClB,EAAO,KAAK,IACb,KAAK,KAAK,SAAU,KAAK,aAAa,GACxC,GAEJ,CAOA,YAAA,CAAa,GACX,GAAkB,iBAAR,EAER,MAAO,GAGT,IACI,EAAM,GAGN,EAAQ,QAaZ,OAjBW,EAMN,MAAM,KAAK,SAAQ,IACtB,IAAI,EAAM,CAAC,EAEX,EAAS,MAAM,KAAK,SAAQ,IAE1B,EAAI,EAAK,MAAM,GAAO,IAAM,KAAK,YAAY,EAAK,MAAM,GAAO,GAAE,IAGnE,EAAI,KAAK,EAAG,IAGP,CACT,CAQA,WAAA,CAAY,GACV,GAAa,MAAV,EACD,OAAO,KAGT,IAAI,EAAc,EACd,EAAQ,CACV,UAAW,CAAC,WAAY,MACxB,MAAO,CAAC,QAAS,KACjB,WAAY,CAAC,QAAS,KACtB,KAAM,CAAC,QAAS,MAGlB,IAAI,IAAI,KAAQ,EACd,EAAc,EAAY,QAAQ,IAAI,OAAO,EAAM,GAAM,GAAI,KAAM,EAAM,GAAM,IAGjF,OAAO,CACT,CAOA,cAAA,CAAe,GAEb,GAAa,OAAV,EACD,MAAO,GAGT,IAAI,EAAkC,iBAAV,EAAqB,EAAM,WAAa,EAChE,EAAQ,CACV,UAAW,CAAC,MAAO,MAAO,OAAQ,QAClC,WAAY,CAAC,MAAO,MAAO,OAAQ,OACnC,MAAO,CAAC,MAAO,MAAO,OAAQ,KAC9B,KAAM,CAAC,MAAO,KAAM,OAAQ,QAG9B,IAAI,IAAI,KAAQ,EACd,EAAiB,EAAe,QAAQ,EAAM,GAAM,MAAO,EAAM,GAAM,QAGzE,OAAO,CACT,CAOA,eAAA,CAAgB,GACd,IAAI,EAAS,GAEb,GAAqB,iBAAX,GAAuB,OAAO,KAAK,GAAQ,OACnD,IAAI,IAAK,EAAM,KAAU,OAAO,QAAQ,GACtC,GAAU,GAAG,KAAQ,KAAK,eAAe,MAI7C,OAAO,CACT,EAGF,OAAO,QAAU","file":"/npm/teamspeak-server-query@1.2.2/Serverquery.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/teamspeak-server-query@1.2.2/Serverquery.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","'use strict'\r\n\r\nconst events = require('events')\r\nconst net = require('net')\r\n\r\nclass Serverquery extends events {\r\n  constructor(options = {logging: false}) {\r\n    super()\r\n\r\n    this.connected = false\r\n    this.logging = options.logging // Shows the query commands in the console\r\n    this.socket = null\r\n    this.commandlist = [\r\n      'banadd',\r\n      'banclient',\r\n      'bandel',\r\n      'bandelall',\r\n      'banlist',\r\n      'bindinglist',\r\n      'channeladdperm',\r\n      'channelclientaddperm',\r\n      'channelclientdelperm',\r\n      'channelclientpermlist',\r\n      'channelcreate',\r\n      'channeldelete',\r\n      'channeldelperm',\r\n      'channeledit',\r\n      'channelfind',\r\n      'channelgroupadd',\r\n      'channelgroupaddperm',\r\n      'channelgroupclientlist',\r\n      'channelgroupcopy',\r\n      'channelgroupdel',\r\n      'channelgroupdelperm',\r\n      'channelgrouplist',\r\n      'channelgrouppermlist',\r\n      'channelgrouprename',\r\n      'channelinfo',\r\n      'channellist',\r\n      'channelmove',\r\n      'channelpermlist',\r\n      'clientaddperm',\r\n      'clientdbdelete',\r\n      'clientdbedit',\r\n      'clientdbfind',\r\n      'clientdbinfo',\r\n      'clientdblist',\r\n      'clientdelperm',\r\n      'clientedit',\r\n      'clientfind',\r\n      'clientgetdbidfromuid',\r\n      'clientgetids',\r\n      'clientgetnamefromdbid',\r\n      'clientgetnamefromuid',\r\n      'clientgetuidfromclid',\r\n      'clientinfo',\r\n      'clientkick',\r\n      'clientlist',\r\n      'clientmove',\r\n      'clientpermlist',\r\n      'clientpoke',\r\n      'clientsetserverquerylogin',\r\n      'clientupdate',\r\n      'complainadd',\r\n      'complaindel',\r\n      'complaindelall',\r\n      'complainlist',\r\n      'custominfo',\r\n      'customsearch',\r\n      'customset',\r\n      'customdelete',\r\n      'ftcreatedir',\r\n      'ftdeletefile',\r\n      'ftgetfileinfo',\r\n      'ftgetfilelist',\r\n      'ftinitdownload',\r\n      'ftinitupload',\r\n      'ftlist',\r\n      'ftrenamefile',\r\n      'ftstop',\r\n      'gm',\r\n      'help',\r\n      'hostinfo',\r\n      'instanceedit',\r\n      'instanceinfo',\r\n      'logadd',\r\n      'login',\r\n      'logout',\r\n      'logview',\r\n      'messageadd',\r\n      'messagedel',\r\n      'messageget',\r\n      'messagelist',\r\n      'messageupdateflag',\r\n      'permfind',\r\n      'permget',\r\n      'permidgetbyname',\r\n      'permissionlist',\r\n      'permoverview',\r\n      'permreset',\r\n      'privilegekeyadd',\r\n      'privilegekeydelete',\r\n      'privilegekeylist',\r\n      'privilegekeyuse',\r\n      'quit',\r\n      'sendtextmessage',\r\n      'servercreate',\r\n      'serverdelete',\r\n      'serveredit',\r\n      'servergroupadd',\r\n      'servergroupaddclient',\r\n      'servergroupaddperm',\r\n      'servergroupautoaddperm',\r\n      'servergroupautodelperm',\r\n      'servergroupclientlist',\r\n      'servergroupcopy',\r\n      'servergroupdel',\r\n      'servergroupdelclient',\r\n      'servergroupdelperm',\r\n      'servergrouplist',\r\n      'servergrouppermlist',\r\n      'servergrouprename',\r\n      'servergroupsbyclientid',\r\n      'serveridgetbyport',\r\n      'serverinfo',\r\n      'serverlist',\r\n      'servernotifyregister',\r\n      'servernotifyunregister',\r\n      'serverprocessstop',\r\n      'serverrequestconnectioninfo',\r\n      'serversnapshotcreate',\r\n      'serversnapshotdeploy',\r\n      'serverstart',\r\n      'serverstop',\r\n      'servertemppasswordadd',\r\n      'servertemppassworddel',\r\n      'servertemppasswordlist',\r\n      'setclientchannelgroup',\r\n      'tokenadd',\r\n      'tokendelete',\r\n      'tokenlist',\r\n      'tokenuse',\r\n      'use',\r\n      'version',\r\n      'whoami'\r\n    ]\r\n\r\n    this.createProperties()\r\n  }\r\n\r\n  connect(params) {\r\n    return new Promise((resolve, reject) => {\r\n      this.socket = new net.Socket()\r\n\r\n      this.connectionTimeout(reject, 4000)\r\n\r\n      this.socket.setEncoding('utf8')\r\n\r\n      this.socket.connect(params)\r\n\r\n      this.socket.once('connect', () => this.checkTeamspeakVersion(resolve, reject))\r\n\r\n      this.socket.once('error', err => this.connectionError(err, reject))\r\n\r\n      this.socket.on('close', () => this.connectionClose())\r\n    })\r\n  }\r\n\r\n  /**\r\n   * Resolves an error if the first server response is not \"TS3\".\r\n   * @param  {Promise} resolve\r\n   * @param  {Promise} reject\r\n   */\r\n  checkTeamspeakVersion(resolve, reject) {\r\n    let checkVersion = data => {\r\n      if(data.split('\\n')[0].toLowerCase() === 'ts3') {\r\n        this.connected = true\r\n\r\n        this.notificationEvent() // Add the custome \"notify\" event\r\n\r\n        resolve(data)\r\n      } else {\r\n        this.connected = false\r\n\r\n        reject(new Error('Not a teamspeak 3 server'))\r\n      }\r\n\r\n      this.socket.removeListener('data', checkVersion)\r\n    }\r\n\r\n    this.socket.on('data', checkVersion)\r\n  }\r\n\r\n  /**\r\n   * If an error occurs while connecting to a server\r\n   * @param  {object} err The default error object\r\n   * @param  {Promise} reject\r\n   */\r\n  connectionError(err, reject) {\r\n    this.connected = false\r\n\r\n    this.socket.destroy()\r\n    this.socket.unref()\r\n\r\n    reject(err)\r\n  }\r\n\r\n  /**\r\n   * When no connection gets estableshed after a specific time.\r\n   * @param  {Promise} reject Timeout error\r\n   */\r\n  connectionTimeout(reject, milliseconds) {\r\n    setTimeout(() => {\r\n      if(this.socket.connecting) {\r\n        this.connected = false\r\n\r\n        this.socket.destroy()\r\n        this.socket.unref()\r\n\r\n        reject(new Error('Timeout'))\r\n      }\r\n    }, milliseconds)\r\n  }\r\n\r\n  /**\r\n   * When the connection gets closed (either by the teamspeak server itself or because of an error) a \"close\" gets emitted.\r\n   */\r\n  connectionClose() {\r\n    this.connected = false\r\n\r\n    this.emit('close')\r\n  }\r\n\r\n  /**\r\n   * It adds all the available query commands ass methods to this object.\r\n   * The created methods are parsed to a plain string and then send to the query.\r\n   * E.g: this.servergroupclientlist({sgid: 1}) => \"servergroupclientlist sgid=1\"\r\n   * @return {Promise} The returned data from the teamspeak server query as javascript object\r\n   */\r\n  createProperties() {\r\n    for(let command of this.commandlist) {\r\n      Object.defineProperty(Serverquery.prototype, command, {\r\n        value(props) {\r\n          this.logging && console.log(`${command} ${this.convertToString(props)}`)\r\n\r\n          return this.send(`${command} ${this.convertToString(props)}`).then(res => this.dataToObject(res))\r\n        },\r\n        writable: false, // This method can not be overwritten\r\n        enumerable: true, // You can see this method on console.log\r\n        configurable: true // Needs to be set otherwise a cannot redefine error will show\r\n      })\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Sends the command to the teamspeak 3 serverquery and returns the response from the server.\r\n   * Some responses are not getting send at once. So the data listener collects all responses until the last line is emitted by the server query.\r\n   * @param  {String} cmd Normal command as you would write directly over telnet in the server query\r\n   * @return {Promise}     Array with the reponse(s) from the server\r\n   */\r\n  send(cmd) {\r\n    return new Promise((resolve, reject) => {\r\n      this.socket.once('error', err => reject(err))\r\n\r\n      let data = ''\r\n      let errorMessage = /(error)(\\s)(id=[0-9]{1,4})(\\s)(msg=.*)/ // Last line is always an \"error\" response\r\n      let collectResponses = response => {\r\n        data += response\r\n\r\n        for(let line of response.split('\\n')) {\r\n          line = line.trim()\r\n\r\n          if(errorMessage.test(line)) {\r\n            resolve(data.split('\\n')[0])\r\n\r\n            // Needs to be called otherwise a MaxListenersExceededWarning will show up and the RAM usage is rising\r\n            this.socket.removeListener('data', collectResponses)\r\n            this.socket.removeAllListeners('error')\r\n          }\r\n        }\r\n      }\r\n\r\n      this.socket.write(`${cmd}\\n`, 'utf8', () => {\r\n        this.socket.on('data', collectResponses)\r\n      })\r\n    })\r\n  }\r\n\r\n  /**\r\n   * When a servernotifyregister gets send to the server this method creates the event.\r\n   * Then it checks if the data from the server begins with \"notify\" and then the event will be emitted.\r\n   * Otherwise every reponse would be emitted as event.\r\n   * @return {Event} Emits the event\r\n   */\r\n  notificationEvent() {\r\n    let notify = /^notify/\r\n\r\n    this.socket.on('data', data => {\r\n      if(notify.test(data)) {\r\n        this.emit('notify', this.dataToObject(data))\r\n      }\r\n    })\r\n  }\r\n\r\n  /**\r\n   * Converts the raw response from the serverquery into a workable array with objects.\r\n   * @param  {String} raw The reponse from the serverquery\r\n   * @return {Promise}     Array with objects\r\n   */\r\n  dataToObject(raw) {\r\n    if(typeof raw !== 'string') {\r\n      //throw new Error('The raw data has to be a string.')\r\n      return []\r\n    }\r\n\r\n    let data = raw\r\n    let arr = []\r\n    // Only at the first \"=\" character the string gets split. Else e.g. the property client_unique_identifier would be wrong.\r\n    // This is called \"capturing parentheses\"\r\n    let regex = /=(.+)/\r\n\r\n    data.split('|').forEach(response => {\r\n      let obj = {}\r\n\r\n      response.split(' ').forEach(prop => {\r\n        // If property is client_unique_identifier the string will not be escaped\r\n        obj[prop.split(regex)[0]] = this.escapeChars(prop.split(regex)[1])\r\n      })\r\n\r\n      arr.push(obj)\r\n    })\r\n\r\n    return arr\r\n  }\r\n\r\n  /**\r\n   * Escapes backslashes, slashes and whitespace into normal characters.\r\n   * I dont know exacly what happens here with the regular expression, I just added backslashes till it worked.\r\n   * @param  {String} string The channel- or clientname\r\n   * @return {String}        Escaped channel- or clientname\r\n   */\r\n  escapeChars(string) {\r\n    if(string == null) {\r\n      return null\r\n    }\r\n\r\n    let escapedChar = string\r\n    let chars = {\r\n      backslash: ['\\\\\\\\\\\\\\\\', '\\\\'],\r\n      slash: ['\\\\\\\\/', '\\/'],\r\n      whitespace: ['\\\\\\\\s', ' '],\r\n      pipe: ['\\\\\\\\p', '|']\r\n    }\r\n\r\n    for(let prop in chars) {\r\n      escapedChar = escapedChar.replace(new RegExp(chars[prop][0], 'g'), chars[prop][1])\r\n    }\r\n\r\n    return escapedChar\r\n  }\r\n\r\n  /**\r\n   * The opposite of the method escapeChars() for the input values which are getting send by the forms.\r\n   * @param  {String} value The value of the a parameter\r\n   * @return {String}        The serialized value\r\n   */\r\n  serializeInput(value) {\r\n    // Empty values are null by default. To prevent errors null gets converted to an empty string.\r\n    if(value === null) {\r\n      return ''\r\n    }\r\n\r\n    let serializedChar = typeof value === 'number' ? value.toString() : value\r\n    let chars = {\r\n      backslash: {regex: /\\\\/g, string: '\\\\\\\\'},\r\n      whitespace: {regex: /\\s/g, string: '\\\\s'},\r\n      slash: {regex: /\\//g, string: '/'}, // Weird, thought you have to send // (double slash)\r\n      pipe: {regex: /\\|/, string: '\\\\p'}\r\n    }\r\n\r\n    for(let prop in chars) {\r\n      serializedChar = serializedChar.replace(chars[prop].regex, chars[prop].string)\r\n    }\r\n\r\n    return serializedChar\r\n  }\r\n\r\n  /**\r\n   * Converts the given object with the paramters into a plain string so the telnet query can read it\r\n   * @param  {Object} params This {sgid: 1, cldbid: 2} ...\r\n   * @return {String}        ... becomes this \"sgid=1 cldbid=2\"\r\n   */\r\n  convertToString(params) {\r\n    let string = ''\r\n\r\n    if(typeof params === 'object' && Object.keys(params).length) {\r\n      for(let [prop, value] of Object.entries(params)) {\r\n        string += `${prop}=${this.serializeInput(value)} `\r\n      }\r\n    }\r\n\r\n    return string\r\n  }\r\n}\r\n\r\nmodule.exports = Serverquery\r\n"]}