@honeybbq/teamspeak 0.0.1 → 1.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (428) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +749 -2
  3. package/dist/client/abort.d.ts +5 -0
  4. package/dist/client/abort.d.ts.map +1 -0
  5. package/dist/client/abort.js +23 -0
  6. package/dist/client/abort.js.map +1 -0
  7. package/dist/client/address.d.ts +17 -0
  8. package/dist/client/address.d.ts.map +1 -0
  9. package/dist/client/address.js +66 -0
  10. package/dist/client/address.js.map +1 -0
  11. package/dist/client/api/avatars.d.ts +65 -0
  12. package/dist/client/api/avatars.d.ts.map +1 -0
  13. package/dist/client/api/avatars.js +118 -0
  14. package/dist/client/api/avatars.js.map +1 -0
  15. package/dist/client/api/voice.d.ts +59 -0
  16. package/dist/client/api/voice.d.ts.map +1 -0
  17. package/dist/client/api/voice.js +110 -0
  18. package/dist/client/api/voice.js.map +1 -0
  19. package/dist/client/capabilities.d.ts +68 -0
  20. package/dist/client/capabilities.d.ts.map +1 -0
  21. package/dist/client/capabilities.js +59 -0
  22. package/dist/client/capabilities.js.map +1 -0
  23. package/dist/client/client.d.ts +226 -0
  24. package/dist/client/client.d.ts.map +1 -0
  25. package/dist/client/client.js +1634 -0
  26. package/dist/client/client.js.map +1 -0
  27. package/dist/client/commands.d.ts +66 -0
  28. package/dist/client/commands.d.ts.map +1 -0
  29. package/dist/client/commands.js +168 -0
  30. package/dist/client/commands.js.map +1 -0
  31. package/dist/client/connection-info.d.ts +14 -0
  32. package/dist/client/connection-info.d.ts.map +1 -0
  33. package/dist/client/connection-info.js +47 -0
  34. package/dist/client/connection-info.js.map +1 -0
  35. package/dist/client/crypto/crypt-ops.d.ts +7 -0
  36. package/dist/client/crypto/crypt-ops.d.ts.map +1 -0
  37. package/dist/client/crypto/crypt-ops.js +2 -0
  38. package/dist/client/crypto/crypt-ops.js.map +1 -0
  39. package/dist/client/crypto/crypt.d.ts +37 -0
  40. package/dist/client/crypto/crypt.d.ts.map +1 -0
  41. package/dist/client/crypto/crypt.js +203 -0
  42. package/dist/client/crypto/crypt.js.map +1 -0
  43. package/dist/client/crypto/eax.d.ts +12 -0
  44. package/dist/client/crypto/eax.d.ts.map +1 -0
  45. package/dist/client/crypto/eax.js +118 -0
  46. package/dist/client/crypto/eax.js.map +1 -0
  47. package/dist/client/crypto/identity.d.ts +97 -0
  48. package/dist/client/crypto/identity.d.ts.map +1 -0
  49. package/dist/client/crypto/identity.js +412 -0
  50. package/dist/client/crypto/identity.js.map +1 -0
  51. package/dist/client/crypto/index.d.ts +7 -0
  52. package/dist/client/crypto/index.d.ts.map +1 -0
  53. package/dist/client/crypto/index.js +5 -0
  54. package/dist/client/crypto/index.js.map +1 -0
  55. package/dist/client/crypto/primitives.d.ts +43 -0
  56. package/dist/client/crypto/primitives.d.ts.map +1 -0
  57. package/dist/client/crypto/primitives.js +116 -0
  58. package/dist/client/crypto/primitives.js.map +1 -0
  59. package/dist/client/diagnostics.d.ts +45 -0
  60. package/dist/client/diagnostics.d.ts.map +1 -0
  61. package/dist/client/diagnostics.js +30 -0
  62. package/dist/client/diagnostics.js.map +1 -0
  63. package/dist/client/discovery/index.d.ts +2 -0
  64. package/dist/client/discovery/index.d.ts.map +1 -0
  65. package/dist/client/discovery/index.js +2 -0
  66. package/dist/client/discovery/index.js.map +1 -0
  67. package/dist/client/discovery/resolver.d.ts +26 -0
  68. package/dist/client/discovery/resolver.d.ts.map +1 -0
  69. package/dist/client/discovery/resolver.js +275 -0
  70. package/dist/client/discovery/resolver.js.map +1 -0
  71. package/dist/client/errors.d.ts +82 -0
  72. package/dist/client/errors.d.ts.map +1 -0
  73. package/dist/client/errors.js +201 -0
  74. package/dist/client/errors.js.map +1 -0
  75. package/dist/client/events.d.ts +3 -0
  76. package/dist/client/events.d.ts.map +1 -0
  77. package/dist/client/events.js +8 -0
  78. package/dist/client/events.js.map +1 -0
  79. package/dist/client/handshake/crypt-handshake.d.ts +17 -0
  80. package/dist/client/handshake/crypt-handshake.d.ts.map +1 -0
  81. package/dist/client/handshake/crypt-handshake.js +128 -0
  82. package/dist/client/handshake/crypt-handshake.js.map +1 -0
  83. package/dist/client/handshake/crypt-init2.d.ts +7 -0
  84. package/dist/client/handshake/crypt-init2.d.ts.map +1 -0
  85. package/dist/client/handshake/crypt-init2.js +37 -0
  86. package/dist/client/handshake/crypt-init2.js.map +1 -0
  87. package/dist/client/handshake/index.d.ts +4 -0
  88. package/dist/client/handshake/index.d.ts.map +1 -0
  89. package/dist/client/handshake/index.js +4 -0
  90. package/dist/client/handshake/index.js.map +1 -0
  91. package/dist/client/handshake/license.d.ts +35 -0
  92. package/dist/client/handshake/license.d.ts.map +1 -0
  93. package/dist/client/handshake/license.js +169 -0
  94. package/dist/client/handshake/license.js.map +1 -0
  95. package/dist/client/handshake.d.ts +27 -0
  96. package/dist/client/handshake.d.ts.map +1 -0
  97. package/dist/client/handshake.js +126 -0
  98. package/dist/client/handshake.js.map +1 -0
  99. package/dist/client/helpers.d.ts +6 -0
  100. package/dist/client/helpers.d.ts.map +1 -0
  101. package/dist/client/helpers.js +13 -0
  102. package/dist/client/helpers.js.map +1 -0
  103. package/dist/client/hooks.d.ts +7 -0
  104. package/dist/client/hooks.d.ts.map +1 -0
  105. package/dist/client/hooks.js +28 -0
  106. package/dist/client/hooks.js.map +1 -0
  107. package/dist/client/index.d.ts +27 -0
  108. package/dist/client/index.d.ts.map +1 -0
  109. package/dist/client/index.js +29 -0
  110. package/dist/client/index.js.map +1 -0
  111. package/dist/client/reconnect.d.ts +12 -0
  112. package/dist/client/reconnect.d.ts.map +1 -0
  113. package/dist/client/reconnect.js +44 -0
  114. package/dist/client/reconnect.js.map +1 -0
  115. package/dist/client/throttle.d.ts +20 -0
  116. package/dist/client/throttle.d.ts.map +1 -0
  117. package/dist/client/throttle.js +83 -0
  118. package/dist/client/throttle.js.map +1 -0
  119. package/dist/client/trace.d.ts +223 -0
  120. package/dist/client/trace.d.ts.map +1 -0
  121. package/dist/client/trace.js +13 -0
  122. package/dist/client/trace.js.map +1 -0
  123. package/dist/client/transfer.d.ts +111 -0
  124. package/dist/client/transfer.d.ts.map +1 -0
  125. package/dist/client/transfer.js +243 -0
  126. package/dist/client/transfer.js.map +1 -0
  127. package/dist/client/transport/generation-window.d.ts +30 -0
  128. package/dist/client/transport/generation-window.d.ts.map +1 -0
  129. package/dist/client/transport/generation-window.js +97 -0
  130. package/dist/client/transport/generation-window.js.map +1 -0
  131. package/dist/client/transport/handler.d.ts +79 -0
  132. package/dist/client/transport/handler.d.ts.map +1 -0
  133. package/dist/client/transport/handler.js +868 -0
  134. package/dist/client/transport/handler.js.map +1 -0
  135. package/dist/client/transport/index.d.ts +6 -0
  136. package/dist/client/transport/index.d.ts.map +1 -0
  137. package/dist/client/transport/index.js +5 -0
  138. package/dist/client/transport/index.js.map +1 -0
  139. package/dist/client/transport/packet.d.ts +36 -0
  140. package/dist/client/transport/packet.d.ts.map +1 -0
  141. package/dist/client/transport/packet.js +55 -0
  142. package/dist/client/transport/packet.js.map +1 -0
  143. package/dist/client/transport/quicklz.d.ts +24 -0
  144. package/dist/client/transport/quicklz.d.ts.map +1 -0
  145. package/dist/client/transport/quicklz.js +179 -0
  146. package/dist/client/transport/quicklz.js.map +1 -0
  147. package/dist/client/transport/traffic.d.ts +43 -0
  148. package/dist/client/transport/traffic.d.ts.map +1 -0
  149. package/dist/client/transport/traffic.js +90 -0
  150. package/dist/client/transport/traffic.js.map +1 -0
  151. package/dist/client/types.d.ts +382 -0
  152. package/dist/client/types.d.ts.map +1 -0
  153. package/dist/client/types.js +111 -0
  154. package/dist/client/types.js.map +1 -0
  155. package/dist/core/api/avatars.d.ts +26 -0
  156. package/dist/core/api/avatars.d.ts.map +1 -0
  157. package/dist/core/api/avatars.js +37 -0
  158. package/dist/core/api/avatars.js.map +1 -0
  159. package/dist/core/api/channels.d.ts +191 -0
  160. package/dist/core/api/channels.d.ts.map +1 -0
  161. package/dist/core/api/channels.js +174 -0
  162. package/dist/core/api/channels.js.map +1 -0
  163. package/dist/core/api/clients.d.ts +558 -0
  164. package/dist/core/api/clients.d.ts.map +1 -0
  165. package/dist/core/api/clients.js +431 -0
  166. package/dist/core/api/clients.js.map +1 -0
  167. package/dist/core/api/command.d.ts +400 -0
  168. package/dist/core/api/command.d.ts.map +1 -0
  169. package/dist/core/api/command.js +462 -0
  170. package/dist/core/api/command.js.map +1 -0
  171. package/dist/core/api/credentials.d.ts +186 -0
  172. package/dist/core/api/credentials.d.ts.map +1 -0
  173. package/dist/core/api/credentials.js +144 -0
  174. package/dist/core/api/credentials.js.map +1 -0
  175. package/dist/core/api/files.d.ts +153 -0
  176. package/dist/core/api/files.d.ts.map +1 -0
  177. package/dist/core/api/files.js +185 -0
  178. package/dist/core/api/files.js.map +1 -0
  179. package/dist/core/api/groups.d.ts +301 -0
  180. package/dist/core/api/groups.d.ts.map +1 -0
  181. package/dist/core/api/groups.js +339 -0
  182. package/dist/core/api/groups.js.map +1 -0
  183. package/dist/core/api/icons.d.ts +67 -0
  184. package/dist/core/api/icons.d.ts.map +1 -0
  185. package/dist/core/api/icons.js +125 -0
  186. package/dist/core/api/icons.js.map +1 -0
  187. package/dist/core/api/instance.d.ts +197 -0
  188. package/dist/core/api/instance.d.ts.map +1 -0
  189. package/dist/core/api/instance.js +160 -0
  190. package/dist/core/api/instance.js.map +1 -0
  191. package/dist/core/api/moderation.d.ts +266 -0
  192. package/dist/core/api/moderation.d.ts.map +1 -0
  193. package/dist/core/api/moderation.js +258 -0
  194. package/dist/core/api/moderation.js.map +1 -0
  195. package/dist/core/api/parse.d.ts +36 -0
  196. package/dist/core/api/parse.d.ts.map +1 -0
  197. package/dist/core/api/parse.js +109 -0
  198. package/dist/core/api/parse.js.map +1 -0
  199. package/dist/core/api/server.d.ts +334 -0
  200. package/dist/core/api/server.d.ts.map +1 -0
  201. package/dist/core/api/server.js +324 -0
  202. package/dist/core/api/server.js.map +1 -0
  203. package/dist/core/command/command.d.ts +20 -0
  204. package/dist/core/command/command.d.ts.map +1 -0
  205. package/dist/core/command/command.js +112 -0
  206. package/dist/core/command/command.js.map +1 -0
  207. package/dist/core/command/ids.d.ts +131 -0
  208. package/dist/core/command/ids.d.ts.map +1 -0
  209. package/dist/core/command/ids.js +87 -0
  210. package/dist/core/command/ids.js.map +1 -0
  211. package/dist/core/command/parser.d.ts +17 -0
  212. package/dist/core/command/parser.d.ts.map +1 -0
  213. package/dist/core/command/parser.js +65 -0
  214. package/dist/core/command/parser.js.map +1 -0
  215. package/dist/core/command/request.d.ts +61 -0
  216. package/dist/core/command/request.d.ts.map +1 -0
  217. package/dist/core/command/request.js +64 -0
  218. package/dist/core/command/request.js.map +1 -0
  219. package/dist/core/command/responses.d.ts +70 -0
  220. package/dist/core/command/responses.d.ts.map +1 -0
  221. package/dist/core/command/responses.js +88 -0
  222. package/dist/core/command/responses.js.map +1 -0
  223. package/dist/core/command-name.d.ts +349 -0
  224. package/dist/core/command-name.d.ts.map +1 -0
  225. package/dist/core/command-name.js +347 -0
  226. package/dist/core/command-name.js.map +1 -0
  227. package/dist/core/enums.d.ts +188 -0
  228. package/dist/core/enums.d.ts.map +1 -0
  229. package/dist/core/enums.js +172 -0
  230. package/dist/core/enums.js.map +1 -0
  231. package/dist/core/errorcode.d.ts +413 -0
  232. package/dist/core/errorcode.d.ts.map +1 -0
  233. package/dist/core/errorcode.js +410 -0
  234. package/dist/core/errorcode.js.map +1 -0
  235. package/dist/core/errors.d.ts +119 -0
  236. package/dist/core/errors.d.ts.map +1 -0
  237. package/dist/core/errors.js +241 -0
  238. package/dist/core/errors.js.map +1 -0
  239. package/dist/core/events.d.ts +391 -0
  240. package/dist/core/events.d.ts.map +1 -0
  241. package/dist/core/events.js +6 -0
  242. package/dist/core/events.js.map +1 -0
  243. package/dist/core/helpers.d.ts +42 -0
  244. package/dist/core/helpers.d.ts.map +1 -0
  245. package/dist/core/helpers.js +156 -0
  246. package/dist/core/helpers.js.map +1 -0
  247. package/dist/core/index.d.ts +40 -0
  248. package/dist/core/index.d.ts.map +1 -0
  249. package/dist/core/index.js +39 -0
  250. package/dist/core/index.js.map +1 -0
  251. package/dist/core/internal.d.ts +24 -0
  252. package/dist/core/internal.d.ts.map +1 -0
  253. package/dist/core/internal.js +21 -0
  254. package/dist/core/internal.js.map +1 -0
  255. package/dist/core/middleware.d.ts +14 -0
  256. package/dist/core/middleware.d.ts.map +1 -0
  257. package/dist/core/middleware.js +18 -0
  258. package/dist/core/middleware.js.map +1 -0
  259. package/dist/core/notification-name.d.ts +160 -0
  260. package/dist/core/notification-name.d.ts.map +1 -0
  261. package/dist/core/notification-name.js +158 -0
  262. package/dist/core/notification-name.js.map +1 -0
  263. package/dist/core/notifications.d.ts +93 -0
  264. package/dist/core/notifications.d.ts.map +1 -0
  265. package/dist/core/notifications.js +301 -0
  266. package/dist/core/notifications.js.map +1 -0
  267. package/dist/core/permission-name.d.ts +1046 -0
  268. package/dist/core/permission-name.d.ts.map +1 -0
  269. package/dist/core/permission-name.js +1045 -0
  270. package/dist/core/permission-name.js.map +1 -0
  271. package/dist/core/permission.d.ts +31 -0
  272. package/dist/core/permission.d.ts.map +1 -0
  273. package/dist/core/permission.js +20 -0
  274. package/dist/core/permission.js.map +1 -0
  275. package/dist/core/property-name.d.ts +403 -0
  276. package/dist/core/property-name.d.ts.map +1 -0
  277. package/dist/core/property-name.js +405 -0
  278. package/dist/core/property-name.js.map +1 -0
  279. package/dist/core/reason.d.ts +39 -0
  280. package/dist/core/reason.d.ts.map +1 -0
  281. package/dist/core/reason.js +36 -0
  282. package/dist/core/reason.js.map +1 -0
  283. package/dist/core/reconnect.d.ts +59 -0
  284. package/dist/core/reconnect.d.ts.map +1 -0
  285. package/dist/core/reconnect.js +55 -0
  286. package/dist/core/reconnect.js.map +1 -0
  287. package/dist/core/types.d.ts +122 -0
  288. package/dist/core/types.d.ts.map +1 -0
  289. package/dist/core/types.js +27 -0
  290. package/dist/core/types.js.map +1 -0
  291. package/dist/query/client.d.ts +244 -0
  292. package/dist/query/client.d.ts.map +1 -0
  293. package/dist/query/client.js +1093 -0
  294. package/dist/query/client.js.map +1 -0
  295. package/dist/query/errors.d.ts +61 -0
  296. package/dist/query/errors.d.ts.map +1 -0
  297. package/dist/query/errors.js +100 -0
  298. package/dist/query/errors.js.map +1 -0
  299. package/dist/query/index.d.ts +36 -0
  300. package/dist/query/index.d.ts.map +1 -0
  301. package/dist/query/index.js +34 -0
  302. package/dist/query/index.js.map +1 -0
  303. package/dist/query/knownhosts.d.ts +61 -0
  304. package/dist/query/knownhosts.d.ts.map +1 -0
  305. package/dist/query/knownhosts.js +223 -0
  306. package/dist/query/knownhosts.js.map +1 -0
  307. package/dist/query/lines.d.ts +14 -0
  308. package/dist/query/lines.d.ts.map +1 -0
  309. package/dist/query/lines.js +29 -0
  310. package/dist/query/lines.js.map +1 -0
  311. package/dist/query/options.d.ts +202 -0
  312. package/dist/query/options.d.ts.map +1 -0
  313. package/dist/query/options.js +251 -0
  314. package/dist/query/options.js.map +1 -0
  315. package/dist/query/reconnect.d.ts +29 -0
  316. package/dist/query/reconnect.d.ts.map +1 -0
  317. package/dist/query/reconnect.js +87 -0
  318. package/dist/query/reconnect.js.map +1 -0
  319. package/dist/query/ssh.d.ts +385 -0
  320. package/dist/query/ssh.d.ts.map +1 -0
  321. package/dist/query/ssh.js +257 -0
  322. package/dist/query/ssh.js.map +1 -0
  323. package/dist/query/stream.d.ts +38 -0
  324. package/dist/query/stream.d.ts.map +1 -0
  325. package/dist/query/stream.js +70 -0
  326. package/dist/query/stream.js.map +1 -0
  327. package/dist/query/tcp.d.ts +38 -0
  328. package/dist/query/tcp.d.ts.map +1 -0
  329. package/dist/query/tcp.js +53 -0
  330. package/dist/query/tcp.js.map +1 -0
  331. package/dist/query/transport.d.ts +36 -0
  332. package/dist/query/transport.d.ts.map +1 -0
  333. package/dist/query/transport.js +2 -0
  334. package/dist/query/transport.js.map +1 -0
  335. package/dist/query/web.d.ts +78 -0
  336. package/dist/query/web.d.ts.map +1 -0
  337. package/dist/query/web.js +157 -0
  338. package/dist/query/web.js.map +1 -0
  339. package/dist/versions/index.d.ts +3094 -0
  340. package/dist/versions/index.d.ts.map +1 -0
  341. package/dist/versions/index.js +9237 -0
  342. package/dist/versions/index.js.map +1 -0
  343. package/package.json +119 -4
  344. package/src/client/abort.ts +24 -0
  345. package/src/client/address.ts +74 -0
  346. package/src/client/api/avatars.ts +164 -0
  347. package/src/client/api/voice.ts +177 -0
  348. package/src/client/capabilities.ts +106 -0
  349. package/src/client/client.ts +1942 -0
  350. package/src/client/commands.ts +201 -0
  351. package/src/client/connection-info.ts +52 -0
  352. package/src/client/crypto/crypt-ops.ts +6 -0
  353. package/src/client/crypto/crypt.ts +275 -0
  354. package/src/client/crypto/eax.ts +152 -0
  355. package/src/client/crypto/identity.ts +484 -0
  356. package/src/client/crypto/index.ts +21 -0
  357. package/src/client/crypto/primitives.ts +141 -0
  358. package/src/client/diagnostics.ts +58 -0
  359. package/src/client/discovery/index.ts +1 -0
  360. package/src/client/discovery/resolver.ts +325 -0
  361. package/src/client/errors.ts +217 -0
  362. package/src/client/events.ts +12 -0
  363. package/src/client/handshake/crypt-handshake.ts +157 -0
  364. package/src/client/handshake/crypt-init2.ts +48 -0
  365. package/src/client/handshake/index.ts +3 -0
  366. package/src/client/handshake/license.ts +208 -0
  367. package/src/client/handshake.ts +150 -0
  368. package/src/client/helpers.ts +10 -0
  369. package/src/client/hooks.ts +30 -0
  370. package/src/client/index.ts +95 -0
  371. package/src/client/reconnect.ts +43 -0
  372. package/src/client/throttle.ts +92 -0
  373. package/src/client/trace.ts +237 -0
  374. package/src/client/transfer.ts +436 -0
  375. package/src/client/transport/generation-window.ts +108 -0
  376. package/src/client/transport/handler.ts +1021 -0
  377. package/src/client/transport/index.ts +14 -0
  378. package/src/client/transport/packet.ts +69 -0
  379. package/src/client/transport/quicklz.ts +209 -0
  380. package/src/client/transport/traffic.ts +116 -0
  381. package/src/client/types.ts +458 -0
  382. package/src/core/api/avatars.ts +40 -0
  383. package/src/core/api/channels.ts +420 -0
  384. package/src/core/api/clients.ts +1094 -0
  385. package/src/core/api/command.ts +737 -0
  386. package/src/core/api/credentials.ts +335 -0
  387. package/src/core/api/files.ts +411 -0
  388. package/src/core/api/groups.ts +730 -0
  389. package/src/core/api/icons.ts +175 -0
  390. package/src/core/api/instance.ts +369 -0
  391. package/src/core/api/moderation.ts +632 -0
  392. package/src/core/api/parse.ts +139 -0
  393. package/src/core/api/server.ts +769 -0
  394. package/src/core/command/command.ts +125 -0
  395. package/src/core/command/ids.ts +153 -0
  396. package/src/core/command/parser.ts +68 -0
  397. package/src/core/command/request.ts +119 -0
  398. package/src/core/command/responses.ts +140 -0
  399. package/src/core/command-name.ts +350 -0
  400. package/src/core/enums.ts +215 -0
  401. package/src/core/errorcode.ts +412 -0
  402. package/src/core/errors.ts +266 -0
  403. package/src/core/events.ts +418 -0
  404. package/src/core/helpers.ts +161 -0
  405. package/src/core/index.ts +152 -0
  406. package/src/core/internal.ts +24 -0
  407. package/src/core/middleware.ts +24 -0
  408. package/src/core/notification-name.ts +161 -0
  409. package/src/core/notifications.ts +404 -0
  410. package/src/core/permission-name.ts +1162 -0
  411. package/src/core/permission.ts +34 -0
  412. package/src/core/property-name.ts +411 -0
  413. package/src/core/reason.ts +38 -0
  414. package/src/core/reconnect.ts +98 -0
  415. package/src/core/types.ts +150 -0
  416. package/src/query/client.ts +1274 -0
  417. package/src/query/errors.ts +108 -0
  418. package/src/query/index.ts +66 -0
  419. package/src/query/knownhosts.ts +257 -0
  420. package/src/query/lines.ts +28 -0
  421. package/src/query/options.ts +448 -0
  422. package/src/query/reconnect.ts +84 -0
  423. package/src/query/ssh.ts +674 -0
  424. package/src/query/stream.ts +91 -0
  425. package/src/query/tcp.ts +85 -0
  426. package/src/query/transport.ts +35 -0
  427. package/src/query/web.ts +234 -0
  428. package/src/versions/index.ts +10774 -0
package/README.md CHANGED
@@ -1,3 +1,750 @@
1
- # Temporary Holding Version
1
+ <div align="center">
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ # @honeybbq/teamspeak
4
+
5
+ **A clean-room TeamSpeak client protocol library written in pure TypeScript.**
6
+
7
+ Works with TeamSpeak 3 and TeamSpeak 6 servers. No proprietary SDK, no copied code.
8
+
9
+ [![CI](https://github.com/honeybbq/teamspeak-js/actions/workflows/ci.yml/badge.svg)](https://github.com/honeybbq/teamspeak-js/actions/workflows/ci.yml)
10
+ [![npm](https://img.shields.io/npm/v/@honeybbq/teamspeak)](https://www.npmjs.com/package/@honeybbq/teamspeak)
11
+ [![npm beta](https://img.shields.io/npm/v/@honeybbq/teamspeak/beta?label=beta)](https://www.npmjs.com/package/@honeybbq/teamspeak?activeTab=versions)
12
+ [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/HoneyBBQ/teamspeak-js/badge)](https://scorecard.dev/viewer/?uri=github.com/HoneyBBQ/teamspeak-js)
13
+ [![Node Version](https://img.shields.io/node/v/@honeybbq/teamspeak)](https://github.com/HoneyBBQ/teamspeak-js/blob/main/package.json)
14
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/HoneyBBQ/teamspeak-js/blob/main/LICENSE)
15
+
16
+ </div>
17
+
18
+ **[API reference](https://honeybbq.github.io/teamspeak-js/)**
19
+
20
+ Upgrading from 0.x? The package was renamed; see the [migration guide](https://github.com/HoneyBBQ/teamspeak-js/blob/main/docs/migrating-to-1.0.md).
21
+
22
+ ## Features
23
+
24
+ - **Full protocol handshake** — ECDH key exchange, RSA puzzle, EAX-encrypted transport
25
+ - **Command & notification system** — Send commands, receive server events
26
+ - **Event-driven API** — Register handlers for text messages, client enter/leave, channel moves, kicks, etc.
27
+ - **Voice data** — Send Opus voice packets (codec 4 & 5)
28
+ - **File transfers** — Upload, download, and delete files on the server
29
+ - **Address resolution** — SRV records, TSDNS, and direct addresses; server nicknames on request (`nicknameLookup: true`), since that lookup goes to named.myteamspeak.com
30
+ - **Middleware** — Pluggable command and event middleware chains
31
+ - **Built-in rate limiter** — Token-bucket throttling to prevent server-side flood kicks
32
+ - **Identity management** — Generate, import/export, and upgrade security level of identities
33
+ - **Full command set** — 111 typed functions covering every command the voice protocol answers
34
+ - **Reconnection** — Opt-in retry with backoff, tuned for TeamSpeak's antiflood ban
35
+ - **Server capabilities** — Reports the server version and the uid hash it uses (SHA-1 on TS3, SHA-256 on TS6), and the server's name, icon, banner and welcome message
36
+ - **Custom transports** — Supply your own socket, for proxies, tunnels or tests
37
+ - **ESM with types** — Ships ES modules with full TypeScript declarations
38
+ - **Zero native deps** — Pure TypeScript, no native addons required
39
+
40
+ ## Installation
41
+
42
+ 1.0 is in beta, published under the `beta` tag. A plain `npm install` still
43
+ gets 0.3, so ask for the beta:
44
+
45
+ ```bash
46
+ npm install @honeybbq/teamspeak@beta
47
+ # or
48
+ pnpm add @honeybbq/teamspeak@beta
49
+ ```
50
+
51
+ Everything in this README is the 1.0 API. You need Node.js 22.12 or newer.
52
+
53
+ ## Quick Start
54
+
55
+ ```typescript
56
+ import { Client, generateIdentity } from "@honeybbq/teamspeak/client";
57
+
58
+ // Generate a new identity (or load an existing one)
59
+ const identity = await generateIdentity(8);
60
+
61
+ // Create the client
62
+ const client = new Client(identity, "localhost", "TSBot", {
63
+ serverPassword: process.env.TEAMSPEAK_SERVER_PASSWORD,
64
+ defaultChannel: "Lobby",
65
+ defaultChannelPassword: process.env.TEAMSPEAK_DEFAULT_CHANNEL_PASSWORD,
66
+ });
67
+
68
+ // Register event handlers
69
+ client.on("connected", ({ reconnected }) => {
70
+ console.log(reconnected ? "Reconnected to server!" : "Connected to server!");
71
+ });
72
+
73
+ client.on("textMessage", (msg) => {
74
+ console.log(`[${msg.invokerName}]: ${msg.message}`);
75
+ });
76
+
77
+ client.on("disconnected", ({ error, willReconnect }) => {
78
+ console.log("Disconnected:", error?.message ?? "clean", willReconnect ? "(reconnecting)" : "");
79
+ });
80
+
81
+ // Connect; resolves once the handshake completes.
82
+ await client.connect({ signal: AbortSignal.timeout(15_000) });
83
+
84
+ // Stay connected until interrupted
85
+ process.on("SIGINT", async () => {
86
+ await client.disconnect();
87
+ });
88
+ ```
89
+
90
+ ## API Overview
91
+
92
+ ### Client Lifecycle
93
+
94
+ | Method | Description |
95
+ | --------------------------------------------- | ------------------------------------------------- |
96
+ | `new Client(identity, addr, nickname, opts?)` | Create a new client |
97
+ | `connect({ signal? })` | Connect; resolves once the handshake completes |
98
+ | `disconnect({ signal? })` | Leave the server and close the connection |
99
+ | `status` | `"disconnected"`, `"connecting"` or `"connected"` |
100
+ | `clientID` | Our clid, assigned by the server |
101
+ | `channelID` | The channel we are in |
102
+ | `serverCapabilities` | Server version, family and uid hash |
103
+ | `uid` | Our own uid, hashed as the server does |
104
+
105
+ `connect()` rejects with an `InvalidAddressError` for an address that cannot be
106
+ one — no host, or a port outside 1–65535 — before anything starts; a host name
107
+ that does not resolve fails with a `TeamspeakError` whose `cause` is the lookup's
108
+ error. A `connect()` called while `disconnect()` is still saying goodbye waits
109
+ for it to finish, then connects.
110
+
111
+ Commands, raw `exec`/`execNoWait`, voice and whispers need a connected client:
112
+ until `connect()` resolves, and from the moment `disconnect()` begins, they fail
113
+ with a `NotConnectedError` and send nothing.
114
+
115
+ ### Events
116
+
117
+ Name an event with an `EventName` constant, or with its string: the two are the
118
+ same, and the listener's payload type follows either.
119
+
120
+ ```typescript
121
+ import { EventName } from "@honeybbq/teamspeak/client";
122
+
123
+ client.on(EventName.TextMessage, (message) => console.log(message.message));
124
+ client.on("textMessage", (message) => console.log(message.message)); // the same
125
+ ```
126
+
127
+ | Method | Description |
128
+ | ------------------------------------------ | -------------------------------------------------------------- |
129
+ | `on("connected", handler)` | Fires when fully connected (`ConnectedEvent`) |
130
+ | `on("disconnected", handler)` | Fires on disconnect (`DisconnectedEvent`) |
131
+ | `on("textMessage", handler)` | Fires on text messages |
132
+ | `on("clientEnter", handler)` | Fires when a client joins |
133
+ | `on("clientLeave", handler)` | Fires when a client leaves |
134
+ | `on("clientMoved", handler)` | Fires when a client moves channels |
135
+ | `on("clientUpdated", handler)` | Fires when a client's properties change (`ClientUpdatedEvent`) |
136
+ | `on("clientServerGroupAdded", handler)` | Fires when a client joins a server group |
137
+ | `on("clientServerGroupRemoved", handler)` | Fires when a client leaves a server group |
138
+ | `on("clientChannelGroupChanged", handler)` | Fires when a client's channel group changes |
139
+ | `on("channelCreated", handler)` | Fires when a channel is created |
140
+ | `on("channelEdited", handler)` | Fires when a channel's properties are edited |
141
+ | `on("channelMoved", handler)` | Fires when a channel is moved or reordered |
142
+ | `on("channelDeleted", handler)` | Fires when a channel is deleted |
143
+ | `on("channelDescriptionChanged", handler)` | Fires when a channel's description changes |
144
+ | `on("channelPasswordChanged", handler)` | Fires when a channel's password changes |
145
+ | `on("serverEdited", handler)` | Fires when the server's settings are edited |
146
+ | `on("channelSubscribed", handler)` | Fires when the bot is subscribed to a channel |
147
+ | `on("channelUnsubscribed", handler)` | Fires when the bot is unsubscribed from a channel |
148
+ | `on("pluginCommand", handler)` | Fires on a plugin command (`sendPluginCommand`) |
149
+ | `on("clientChatComposing", handler)` | Fires when a client is typing a private message |
150
+ | `on("kicked", handler)` | Fires when the bot is kicked |
151
+ | `on("poked", handler)` | Fires when poked by a client |
152
+ | `on("voiceData", handler)` | Fires on incoming voice data |
153
+
154
+ `on()` and `once()` return a function that removes the listener, which is also
155
+ a `Disposable` (`using listener = client.on(...)`). Listeners run one at a
156
+ time, in the order their events arrived, so a listener may call the client and
157
+ await an answer. `disconnected` delivers `undefined` after `disconnect()`, and
158
+ the cause otherwise — a `ConnectionTimeoutError`, or a `RemovedError` for a kick, a ban
159
+ or a server stopping. `await using client = new Client(...)` disconnects when
160
+ the scope ends.
161
+
162
+ `connected` is delivered after `connect()` resolves, so a listener added right
163
+ after `await client.connect()` still hears it. `disconnect()` waits a second at
164
+ most for the server to acknowledge its goodbye, less if its `signal` aborts
165
+ sooner, and resolves once `disconnected` has been delivered. A `connect()` waits
166
+ for an earlier session's `disconnected` to be delivered before it starts, so no
167
+ listener or `events()` iterator of the new session hears the old one end.
168
+
169
+ A listener that throws does not stop the others: the event still reaches the
170
+ listeners after it, and the exception surfaces as an `uncaughtException`, as an
171
+ EventEmitter listener's would.
172
+
173
+ Voice is the exception to "every event in order": while more than 256
174
+ deliveries are waiting, voice frames are dropped (and counted in a warning at
175
+ most every ten seconds) rather than queued without bound.
176
+
177
+ `events(name, { signal })` is the same as an async iterator, buffering events
178
+ that arrive while the loop body runs. The buffer is unbounded (voice excepted,
179
+ as above), so stop iterating when you stop reading. Aborting `signal` stops
180
+ listening and makes the pending and later `next()` calls reject with the
181
+ signal's reason, as Node's `events.on` does; `break`ing out of the loop, or a
182
+ disconnect, ends it normally:
183
+
184
+ ```typescript
185
+ for await (const msg of client.events("textMessage", { signal })) {
186
+ await reply(msg);
187
+ }
188
+ ```
189
+
190
+ `notification` is the catch-all: it delivers every notification the server
191
+ sends, as it arrived, the ones that also have a typed event among them, after
192
+ that event. It is how to reach one the SDK does not model; `NotificationName`
193
+ names the known ones:
194
+
195
+ ```typescript
196
+ import { NotificationName } from "@honeybbq/teamspeak";
197
+
198
+ client.on("notification", (n) => {
199
+ if (n.name === NotificationName.ChannelEdited) console.log(n.params);
200
+ });
201
+ ```
202
+
203
+ ### Commands
204
+
205
+ Every command the voice protocol answers is a typed function, grouped by area.
206
+ Each is addressed by branded ids, so a `ChannelID` cannot be passed where a
207
+ `ClientID` is meant. The constructors — `asChannelID(5)`, `asClientID(3)` and
208
+ the rest — throw a `RangeError` for anything but an integer in the id's wire
209
+ range: 0–65535 for a `ClientID` and the file transfer ids, 0–2^32−1 for a
210
+ `PermissionID` (an `IconID` also takes the signed form), 0–2^64−1 for the
211
+ `bigint` ids. Required arguments are positional; everything optional
212
+ goes in one options object, always the last argument, which also carries
213
+ `signal` and `timeoutMs` to abandon the command or bound how long it waits.
214
+
215
+ ```typescript
216
+ import {
217
+ listChannels,
218
+ createChannel,
219
+ moveClient,
220
+ kickClient,
221
+ sendChannelMessage,
222
+ addServerGroupPermission,
223
+ iterateClientDatabase,
224
+ permissionByName,
225
+ PermissionName,
226
+ asClientID,
227
+ Codec,
228
+ Reason,
229
+ } from "@honeybbq/teamspeak";
230
+
231
+ const channels = await listChannels(client, { signal: AbortSignal.timeout(5_000) });
232
+
233
+ const cid = await createChannel(client, {
234
+ name: "Lounge",
235
+ topic: "the quiet one",
236
+ codec: Codec.OpusVoice,
237
+ isPermanent: true,
238
+ });
239
+
240
+ await moveClient(client, client.clientID, cid, { password: "channel-password" });
241
+ await sendChannelMessage(client, "hello");
242
+ await kickClient(client, someone, Reason.KickChannel, { reasonMessage: "take a break" });
243
+
244
+ await addServerGroupPermission(client, sgid, permissionByName(PermissionName.ClientTalkPower), 50, {
245
+ skip: true,
246
+ });
247
+
248
+ for await (const entry of iterateClientDatabase(client)) {
249
+ console.log(entry.nickname, entry.lastConnectedAt);
250
+ }
251
+ ```
252
+
253
+ A command that sends content — `createChannel`'s channel, `editChannel`'s
254
+ settings, `updateClient`, `editClient`, `editClientDatabase`,
255
+ `addBan`'s `BanFields` — takes it as its own
256
+ argument, and `{ signal, timeoutMs }` as a separate one after it: set among the
257
+ content, they are not read.
258
+
259
+ Options objects use camelCase names (`maxClients` for `channel_maxclients`),
260
+ and only the fields you set are sent: an unset field leaves the setting alone,
261
+ while `""` sends it empty — `editChannel(client, cid, { password: "" })` clears
262
+ a password. A key an options type does not name is never sent. The exceptions
263
+ are `editServer` and `editInstance`, which take the raw `virtualserver_*` and
264
+ `serverinstance_*` properties as `getServerInfo` reports them; `PropertyName` names
265
+ the keys.
266
+
267
+ Results are camelCase too. Timestamps are `Date`s (`undefined` where the server
268
+ sends 0 for "never"), durations are milliseconds with an `Ms` suffix
269
+ (`idleTimeMs`, `durationMs`), and a permission is a `Permission`, built with
270
+ `permissionByID` or `permissionByName`. Small enumerations — `GroupType`,
271
+ `Codec`, `PrivilegeKeyType`, `LogLevel` and the rest — are objects of named values with
272
+ a type of the same name.
273
+
274
+ | Module | Covers |
275
+ | ------------ | -------------------------------------------------------------- |
276
+ | `channels` | Create, edit, move, delete, subscribe, channel permissions |
277
+ | `clients` | List, move, kick, poke, edit, the client database, permissions |
278
+ | `server` | Server and instance settings, groups, temp passwords, bindings |
279
+ | `groups` | Channel groups, the permission catalogue, privilege keys |
280
+ | `moderation` | Bans, complaints, offline messages, text messages, the log |
281
+ | `files` | List, delete, rename, create directories, transfer negotiation |
282
+
283
+ Many of these commands are answered over the voice protocol with a
284
+ notification rather than data rows — `servergrouplist` with
285
+ `notifyservergrouplist`, `ftinitupload` with `notifystartupload` after the
286
+ command has already succeeded. The client pairs each answer with its command,
287
+ so this is invisible to callers; [docs/voice-protocol-responses.md](https://github.com/HoneyBBQ/teamspeak-js/blob/main/docs/voice-protocol-responses.md)
288
+ has the measured table. A refusal is always thrown, never returned as an empty
289
+ result. A list or find with nothing to report answers `[]`. A command that
290
+ exists to return something — `createChannel`'s id, `initFileUpload`'s key,
291
+ `getClientProperties`'s fields — throws a `NoDataError` when the server answers
292
+ without it, rather than returning an id of 0 or an empty object.
293
+
294
+ For anything outside the typed set, `client.exec(line, { signal?, timeoutMs? })`
295
+ sends a raw command line and resolves to the rows that answer it.
296
+
297
+ ### File Transfers
298
+
299
+ Negotiate with the `files` module, then move the bytes over TCP:
300
+
301
+ ```typescript
302
+ import { Readable } from "node:stream";
303
+ import { initFileUpload } from "@honeybbq/teamspeak";
304
+
305
+ const info = await initFileUpload(client, cid, "/notes.txt", BigInt(data.length));
306
+ await client.uploadFileData(host, info, Readable.from([data]));
307
+ ```
308
+
309
+ An upload does not replace a file already at the path unless passed
310
+ `{ overwrite: true }`.
311
+
312
+ | Function | Description |
313
+ | ---------------------------------------------------- | --------------------------------- |
314
+ | `initFileUpload(client, ...)` | Negotiate an upload |
315
+ | `initFileDownload(client, ...)` | Negotiate a download |
316
+ | `client.uploadFileData(host, info, data, options?)` | Transfer file data to the server |
317
+ | `client.downloadFileData(host, info, out, options?)` | Receive file data from the server |
318
+
319
+ The transfer functions take `FileTransferOptions`:
320
+
321
+ | Option | Description |
322
+ | --------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
323
+ | `signal` | An `AbortSignal` that abandons the transfer; it rejects with the signal's reason |
324
+ | `socketFactory` | Opens the connection instead of a direct TCP dial, to route it through a proxy or tunnel |
325
+ | `trace` | Hooks called at each milestone of the transfer (`dialStart`, `dialDone`, `progress`, `done`, `failed`); none sees the transfer key |
326
+ | `idleTimeoutMs` | The longest, in milliseconds, a transfer may go without moving a byte, the key write included. Default 30 000; `0` disables it |
327
+
328
+ A transfer that goes idle for `idleTimeoutMs` fails with a `FileTransferError`
329
+ whose `cause` is a `TimeoutError`, and its connection is destroyed. A download
330
+ that sends more bytes than the negotiated size, or ends short of it, fails with
331
+ a `FileTransferError` too; bytes past the announced size are never written.
332
+
333
+ ### Identity
334
+
335
+ ```typescript
336
+ import { generateIdentity, parseIdentity } from "@honeybbq/teamspeak/client";
337
+
338
+ // Generate a new identity with security level 8
339
+ const identity = await generateIdentity(8);
340
+
341
+ // Export to string for persistent storage
342
+ const exported = identity.export();
343
+
344
+ // Import from a previously exported string
345
+ const restored = parseIdentity(exported);
346
+
347
+ // Raise the security level (CPU-intensive). Identities are immutable: this
348
+ // returns a new one with the same key.
349
+ const stronger = await identity.upgradeToLevel(10, { signal });
350
+
351
+ // The unique identifier, hashed as a TS3 (sha1) or TS6 (sha256) server does
352
+ const uid = identity.uid("sha1");
353
+ ```
354
+
355
+ The private key never leaves the identity except through `export()`:
356
+ `toString()`, `toJSON()` and `util.inspect()` describe it without the key.
357
+ `parseIdentity` takes exactly what `export()` writes — the key as canonical
358
+ base64 of at most 32 bytes, a colon, and a decimal offset that fits in 64 bits
359
+ — and throws an `InvalidIdentityError` for anything else.
360
+
361
+ ### Options
362
+
363
+ ```typescript
364
+ import { Client } from "@honeybbq/teamspeak/client";
365
+ import { consoleLogger } from "@honeybbq/teamspeak";
366
+
367
+ const client = new Client(identity, "ts.example.com", "Bot", {
368
+ logger: consoleLogger, // silent unless set
369
+ resolver: customResolver,
370
+ commandMiddleware: [timing],
371
+ eventMiddleware: [filterMiddleware],
372
+ serverPassword: process.env.TEAMSPEAK_SERVER_PASSWORD,
373
+ defaultChannel: "Lobby",
374
+ defaultChannelPassword: process.env.TEAMSPEAK_DEFAULT_CHANNEL_PASSWORD,
375
+ });
376
+ ```
377
+
378
+ Address resolution — the built-in one or a custom `resolver` — has ten seconds
379
+ in all: the `signal` a resolver is given aborts then, and the client connects
380
+ to the address as given.
381
+
382
+ `commandMiddleware` wraps the typed commands: each middleware receives the
383
+ request (its command name and parameters) with its options and returns the
384
+ answering rows, so it can time, retry or answer a command itself. Raw `exec`
385
+ and `execNoWait` lines do not pass through it.
386
+
387
+ ```typescript
388
+ import type { CommandMiddleware } from "@honeybbq/teamspeak";
389
+
390
+ const timing: CommandMiddleware = (next) => async (request, options) => {
391
+ const started = Date.now();
392
+ try {
393
+ return await next(request, options);
394
+ } finally {
395
+ console.log(request.command, Date.now() - started, "ms");
396
+ }
397
+ };
398
+ ```
399
+
400
+ Connection auth options:
401
+
402
+ - `serverPassword`: plain-text server password; sent as the TeamSpeak protocol hash during `clientinit`
403
+ - `defaultChannel`: default channel name requested during `clientinit`
404
+ - `defaultChannelPassword`: plain-text password for `defaultChannel`; sent as the TeamSpeak protocol hash
405
+
406
+ ### Client version
407
+
408
+ By default `clientinit` sends a recent Windows version. The `version` option
409
+ sends another, and `@honeybbq/teamspeak/versions` has one export for each
410
+ version that is known to work, named `<Platform>_<version>_<build>`:
411
+
412
+ ```typescript
413
+ import { Client } from "@honeybbq/teamspeak/client";
414
+ import { Windows_3_6_2_1695203293 } from "@honeybbq/teamspeak/versions";
415
+
416
+ const client = new Client(identity, "ts.example.com", "Bot", {
417
+ version: Windows_3_6_2_1695203293,
418
+ });
419
+ ```
420
+
421
+ A `ClientVersion` is a platform, a version string and a signature, and only
422
+ the ones in that entry carry a signature a server accepts. A server refuses a
423
+ build below its configured minimum, so an old version fails to connect on a
424
+ server that has raised it. `new Client` throws when a field is empty or the
425
+ signature is not the base64 of 64 bytes. Importing `@honeybbq/teamspeak/client`
426
+ does not load the table; only the entry you import it from does.
427
+
428
+ ### Tracing
429
+
430
+ `trace` takes hooks that are called at each milestone of the client's life, for timing, metrics, logs or a progress display. For each connection attempt, the one `connect()` starts and each one the reconnect loop makes, the milestones come in this order: `resolveStart`, `resolveDone`, `connectStart`, `connectDone`, `handshakeDone`, `sessionStart`, `welcomeDone`. An attempt that never gets a session ends with `attemptFailed` instead, which says in which phase (`"open"`, `"handshake"` or `"join"`) and why. When a session ends, `sessionEnd` is called with the cause (`undefined` after `disconnect()`), preceded on a `disconnect()` by `disconnectStart` and `disconnectDone`, which says whether the server acknowledged the goodbye. `reconnectScheduled` fires when the reconnect loop is about to wait for its next attempt, and `reconnectStopped` when it ends without a session. Every attempt ends with exactly one of `sessionStart` and `attemptFailed`, and every session with exactly one `sessionEnd`.
431
+
432
+ The infos carry what each milestone knows: the resolver's candidates, the local address, the RSA puzzle's level and how long it took, how many packets were sent again, the server's public key (to pin a server's identity), the nickname the server accepted, the server's `initserver` parameters without any secret, and where the client landed with how many channels and clients the welcome delivered. Durations are in milliseconds.
433
+
434
+ ```ts
435
+ const client = new Client(identity, "ts.example.com", "Bot", {
436
+ trace: {
437
+ resolveDone: (i) => console.log(`resolved to ${i.target} in ${i.durationMs.toFixed(0)} ms`),
438
+ handshakeDone: (i) =>
439
+ console.log(`encrypted after ${i.durationMs.toFixed(0)} ms, ${i.resends} resends`),
440
+ sessionStart: (i) => console.log(`joined as ${i.nickname} after ${i.durationMs.toFixed(0)} ms`),
441
+ welcomeDone: (i) => console.log(`${i.channels} channels, ${i.clients} clients in view`),
442
+ attemptFailed: (i) => console.log(`attempt ${i.attempt} failed while ${i.phase}:`, i.error),
443
+ sessionEnd: (i) => console.log(`session over after ${(i.durationMs / 1000).toFixed(0)} s`),
444
+ reconnectScheduled: (i) => console.log(`retry ${i.attempt} in ${i.delayMs} ms`),
445
+ },
446
+ });
447
+ ```
448
+
449
+ A file transfer has a trace of its own, given in the options of `uploadFileData`, `downloadFileData` and `dialFileTransfer` (and of the client's methods that forward to them): `dialStart`, `dialDone`, `progress` (at most once per 64 KiB, and once more at the end with the final count), then exactly one of `done` and `failed`, which names the stage (`"dial"` or `"transfer"`). The transfer key never appears in any of it.
450
+
451
+ The rules for a hook, in both traces:
452
+
453
+ - It runs synchronously, at the moment of the milestone, and the client waits for it. Keep it quick and hand slow work to your own task.
454
+ - What it returns is ignored. A promise it returns is not awaited.
455
+ - It must not call `connect()` or `disconnect()`. To give up on an attempt, abort the signal you passed to `connect()`; to leave once connected, call `disconnect()` from a `connected` listener.
456
+ - It may read `client.status`, `client.clientID` and the like. `sessionStart` runs before `connect()` resolves and before `connected` is delivered, and `sessionEnd` before `disconnected`.
457
+ - If it throws, or the promise it returns rejects, the error is reported the way a throwing event listener's is, as an uncaught exception, and the client carries on as if nothing happened.
458
+
459
+ The object is copied when the client is made (or the transfer call starts), so changing it afterwards has no effect.
460
+
461
+ ### Diagnostics
462
+
463
+ The client logs nothing unless given a `logger`. For tracing, it publishes on
464
+ two [`diagnostics_channel`](https://nodejs.org/api/diagnostics_channel.html)
465
+ channels, which cost nothing without a subscriber:
466
+
467
+ - `honeybbq:teamspeak:command` (`commandChannel`), a tracing channel: `start`
468
+ when a command is sent, `asyncEnd` when its answer arrives, `error` when it
469
+ fails.
470
+ - `honeybbq:teamspeak:incoming` (`incomingChannel`): every command the server sends.
471
+
472
+ Both carry the command's name, never its parameters, which hold password hashes
473
+ and privilege keys.
474
+
475
+ ### Reconnection
476
+
477
+ Off by default: a silent reconnect makes an outage look like a healthy session.
478
+ An explicit `disconnect()` never reconnects, whatever the policy says.
479
+
480
+ ```typescript
481
+ const client = new Client(identity, "ts.example.com", "Bot", {
482
+ reconnect: {
483
+ backoff: { initialDelayMs: 1_000, maxDelayMs: 60_000, factor: 2, jitter: 0.2 },
484
+ // Optional: decide for yourself which failures are worth retrying.
485
+ shouldRetry: (err, attempt) => attempt < 10,
486
+ },
487
+ });
488
+ ```
489
+
490
+ The defaults are conservative because TeamSpeak **bans an IP after roughly
491
+ three rapid connects** — a retry loop without a delay bans itself, and the ban
492
+ outlasts the outage it was recovering from. Recovery is also not instant even
493
+ when it succeeds: the server holds the dropped session for a while and refuses a
494
+ reconnect with `521 too many clones already connected` until it reaps it, so the
495
+ loop keeps trying rather than giving up on the first refusal. It stops once a
496
+ `connect()` of your own has connected the client, and it does not retry an
497
+ address that cannot be one (`InvalidAddressError`).
498
+
499
+ ### Custom transports
500
+
501
+ `fileTransferSocketFactory` and `socketFactory` are the only seams into the
502
+ network layer. Without them the SDK always creates its own sockets, so an
503
+ application running behind a proxy has no way through. `socketFactory` returns
504
+ a `DatagramSocket` — a `node:dgram` socket, or anything with the few methods
505
+ it names — and `fileTransferSocketFactory` any `Duplex` stream, such as the
506
+ socket a SOCKS library returns.
507
+
508
+ ```typescript
509
+ const client = new Client(identity, "ts.example.com", "Bot", {
510
+ // UDP, for the voice and command channel.
511
+ socketFactory: (family) => createSocket(family === 6 ? "udp6" : "udp4"),
512
+ // TCP, dialled separately by each file transfer.
513
+ fileTransferSocketFactory: (host, port) => createConnection({ host, port }),
514
+ });
515
+ ```
516
+
517
+ ### Server capabilities
518
+
519
+ ```typescript
520
+ const caps = client.serverCapabilities;
521
+ // {
522
+ // version: "6.0.0-beta13.1 [Build: 1790080330]", major: 6, family: "ts6",
523
+ // uidAlgorithm: "sha256", name: "TeamSpeak 6 Server", iconID: undefined,
524
+ // hostBannerImageURL: undefined, welcomeMessage: "…"
525
+ // }
526
+ ```
527
+
528
+ Read from `initserver` during the handshake, so it costs no extra round trip.
529
+ The uid hash matters because TS3 hashes a client's public key with SHA-1 and TS6
530
+ with SHA-256 — a client that assumes either one computes an identifier the other
531
+ server never sends.
532
+
533
+ ## ServerQuery
534
+
535
+ The `@experimental` subpath `@honeybbq/teamspeak/query` administers a server
536
+ the way the voice protocol cannot: the same typed commands the core exports,
537
+ plus the ones only an administrator may run, over the three transports a
538
+ ServerQuery speaks.
539
+
540
+ | Transport | Where | Server | Login | Notifications |
541
+ | --------- | ------------ | ---------------- | ------------------- | ------------- |
542
+ | `tcp` | 10011 | TeamSpeak 3 only | the `login` command | yes |
543
+ | `ssh` | 10022 | both | the SSH login | yes |
544
+ | `web` | 10080 (HTTP) | TeamSpeak 6 | the api key | **no** |
545
+
546
+ Only raw TCP and SSH carry notifications: the server pushes them down the same
547
+ connection. WebQuery has no session to push to and refuses to register, so the
548
+ client never tries, and a listener for a server event there throws rather than
549
+ sitting silent. `connected` and `disconnected` work on every transport, since
550
+ they come from the client itself.
551
+
552
+ ```typescript
553
+ import { QueryClient } from "@honeybbq/teamspeak/query";
554
+ import { listChannels } from "@honeybbq/teamspeak";
555
+
556
+ const client = new QueryClient({
557
+ transport: { kind: "tcp", host: "ts.example.com" }, // 10011
558
+ login: { name: "serveradmin", password: process.env.QUERY_PASSWORD! },
559
+ server: { id: 1 },
560
+ nickname: "bot",
561
+ events: { categories: ["textserver", "textprivate"] },
562
+ reconnect: { backoff: { initialDelayMs: 1_000 } },
563
+ });
564
+
565
+ client.on("textMessage", (message) => console.log(message.invokerName, message.message));
566
+
567
+ await client.connect();
568
+
569
+ for (const channel of await listChannels(client)) console.log(channel.name);
570
+
571
+ await client.disconnect();
572
+ ```
573
+
574
+ The three transports are figures of speech the client rebuilds on every
575
+ connection, which is what makes reconnecting possible; `custom` opens one
576
+ itself, for a proxy, a tunnel or a test. Each built-in transport also offers
577
+ the seam into its own connection — `connect` for `tcp`, returning a `Duplex`,
578
+ and `connection` for `ssh`, taking a client or a factory for one — so an
579
+ application behind a TLS terminator or a SOCKS proxy, or one that already
580
+ holds an SSH client, can supply it. `ssh2` is an optional peer dependency:
581
+ without it the other two transports still work, and an `ssh` transport throws
582
+ a `MissingDependencyError` naming the package.
583
+
584
+ A query client delivers the events its categories carry: `serverEdited` comes
585
+ under `server`; the channel events, `clientEnter`, `clientLeave` and
586
+ `clientMoved` under `channel`; and `textMessage` under the three text
587
+ categories. `QueryEventsOption` has the table. The voice client's events about
588
+ clients' updates, group changes, subscriptions, plugin commands and typing are
589
+ not sent to a ServerQuery connection by TeamSpeak 3 or by TeamSpeak 6 over SSH,
590
+ so the query client does not offer them.
591
+
592
+ `serverFamily` reports which generation the server is, read from its own
593
+ `version` answer, and `transport` reads back the live connection for metrics.
594
+
595
+ ### SSH host keys
596
+
597
+ The `ssh` transport checks the server's host key before it sends the login, and
598
+ there is no default for how: the login is a credential, normally
599
+ `serveradmin`'s, and a client that accepts any key hands it to whatever answers
600
+ the port. Give exactly one of these, or the client refuses to be built, naming
601
+ all three:
602
+
603
+ ```typescript
604
+ const client = new QueryClient({
605
+ transport: {
606
+ kind: "ssh",
607
+ host: "ts.example.com",
608
+ username: "serveradmin",
609
+ password: process.env.QUERY_PASSWORD!,
610
+ knownHosts: "/etc/ssh/ssh_known_hosts",
611
+ },
612
+ });
613
+ ```
614
+
615
+ - `knownHosts`: the path of an OpenSSH `known_hosts` file, read each time a
616
+ connection is attempted and never found on its own: `~/.ssh/known_hosts` is
617
+ used only if you name it. The check is `StrictHostKeyChecking=yes`: a host the
618
+ file does not mention is refused, so is one recorded with another key, and so
619
+ is a key a `@revoked` line names. Plain, `[host]:port` and hashed
620
+ (`ssh-keygen -H`) entries are read. The query port is not 22, so record it as
621
+ `ssh-keyscan -p 10022 ts.example.com`, which writes `[ts.example.com]:10022`;
622
+ an entry for port 22 does not vouch for 10022.
623
+ - `hostKey`: your own check, `(key) => void`, that throws to refuse. `key` has
624
+ the host, port, `keyType`, the key's bytes and its `fingerprint`, the
625
+ `SHA256:…` that `ssh-keygen -lf` prints. It has to be synchronous and return
626
+ nothing: a returned value, a `false` included, or a promise is refused rather
627
+ than guessed at.
628
+ - `insecureIgnoreHostKey: true`: accept any key. It gives up what the host key
629
+ is for, and is for a test or a throwaway server.
630
+
631
+ A key that is refused fails the connection with an `SshHostKeyError`, whose
632
+ `cause` says why, and nothing was sent: the password has not left the process.
633
+ Reconnection does not retry it. A connection you supply yourself through
634
+ `connection` is checked by whoever made it, so these options are refused there.
635
+
636
+ **`@experimental`**: this entry point is new, and its API may change in a
637
+ minor release — the options, the transport union and the event map are all
638
+ still settling. Pin a version and read the changelog if you depend on it.
639
+
640
+ ## Compatibility
641
+
642
+ The package follows semver from 1.0. A few sets are open by nature and may
643
+ gain members in a minor release: the events (`EventMap`, `ServerEventName`),
644
+ `ClientStatus`, `ServerFamily`, `UIDAlgorithm`, `ErrorCode`, `Reason` and the
645
+ enumeration tables. Write a `switch` over any of them with a default case. A
646
+ field the server sends as a number that one of those tables names — a codec, a
647
+ text message's target mode, a group type — is a plain `number`, since a server
648
+ may send a value newer than the table.
649
+
650
+ `DatagramSocket` describes the part of a socket the client uses; should a
651
+ later release use more, the new members will be optional.
652
+
653
+ ### Supported environments
654
+
655
+ | Environment | Supported |
656
+ | ----------- | ------------------------------------------------------------------------------ |
657
+ | Node.js | The active and maintenance LTS releases, from 22.12; CI tests 22.12, 24 and 26 |
658
+ | TypeScript | 5.2 and newer, for the published types |
659
+ | Modules | ESM only |
660
+
661
+ When a Node.js release reaches end of life, a minor release may raise
662
+ `engines.node` past it; that is not a breaking change. The published types use
663
+ `Disposable`, so the `lib` option must include `esnext.disposable` (or `es2026`
664
+ or `esnext`), and the subpath exports need `moduleResolution` set to `node16`,
665
+ `nodenext` or `bundler`. CI type-checks a consumer of the packed package with
666
+ TypeScript 5.2. Raising that minimum follows TypeScript's own support window,
667
+ happens in a minor release, and comes with a changelog note.
668
+
669
+ ### Differences from the Go SDK
670
+
671
+ The [Go SDK](https://github.com/honeybbq/teamspeak-go) makes the same calls
672
+ with the same semantics, apart from what the languages make differ:
673
+
674
+ - Backoff fields: JavaScript takes `undefined` as "the default" and `0` as 0.
675
+ Go cannot tell an unset field from 0, so there a zero field takes the default
676
+ and a negative jitter disables it.
677
+ - A listener that throws: here the exception is rethrown from a microtask, an
678
+ uncaught exception as an EventEmitter listener's would be, and the other
679
+ listeners still get the event. Go recovers a panicking handler, logs it at
680
+ Error, and keeps delivering.
681
+ - Durations are milliseconds with an `Ms` suffix here, `time.Duration` in Go;
682
+ `listClients`' `uid` flag (on by default) is Go's `OmitUID`.
683
+
684
+ ## Entry points
685
+
686
+ | Import from | What it is |
687
+ | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
688
+ | `@honeybbq/teamspeak` | What every TeamSpeak connection shares: the command language, ids, errors, the typed commands, the event types and the status and reconnection types |
689
+ | `@honeybbq/teamspeak/client` | The voice client, identities, file transfers, diagnostics and its retry policy |
690
+ | `@honeybbq/teamspeak/versions` | Client versions a server accepts, for the client's `version` option; data only, one export each |
691
+ | `@honeybbq/teamspeak/query` | The ServerQuery client, running the same typed commands over raw TCP, SSH or WebQuery; `@experimental` |
692
+
693
+ Each entry exports only its own symbols. The client entry does not re-export
694
+ the core, so a program imports the `Client` from `@honeybbq/teamspeak/client`
695
+ and the typed commands, ids and errors from `@honeybbq/teamspeak`.
696
+
697
+ The protocol internals (crypto, handshake, transport) are not exported. They
698
+ change with the protocol, and exporting them would have made every change a
699
+ breaking one.
700
+
701
+ `@honeybbq/teamspeak-client` and `@honeybbq/teamspeak-core` are deprecated and
702
+ get no further releases. Coming from 0.x? The
703
+ [migration guide](https://github.com/HoneyBBQ/teamspeak-js/blob/main/docs/migrating-to-1.0.md) lists every change.
704
+
705
+ ## Architecture
706
+
707
+ ```
708
+ src/
709
+ ├── core/ # Shared: command language, ids, errors, typed commands
710
+ ├── client/ # The voice client (@honeybbq/teamspeak/client)
711
+ │ ├── client.ts # Client lifecycle, connection management
712
+ │ ├── commands.ts # Command sending and response tracking
713
+ │ ├── api/voice.ts # Commands only the voice protocol has
714
+ │ ├── capabilities.ts # Server version and uid hash detection
715
+ │ ├── reconnect.ts # Backoff policy and permanent-failure detection
716
+ │ ├── events.ts # Event handler registration and middleware
717
+ │ ├── notifications.ts # Server notification parsing and dispatch
718
+ │ ├── handshake.ts # Protocol handshake orchestration
719
+ │ ├── transfer.ts # File transfer data connections
720
+ │ ├── throttle.ts # Token-bucket rate limiter
721
+ │ ├── crypto/ # ECDH, EAX encryption, identity management
722
+ │ ├── handshake/ # Crypto handshake and license verification
723
+ │ ├── transport/ # UDP packet framing, ACK, compression
724
+ │ └── discovery/ # SRV / TSDNS / direct address resolution
725
+ └── query/ # ServerQuery client (not exported yet)
726
+ examples/
727
+ └── connect.ts # Minimal connection example
728
+ ```
729
+
730
+ ## Related
731
+
732
+ - **[teamspeak-go](https://github.com/honeybbq/teamspeak-go)** — The original Go implementation this library is ported from
733
+
734
+ ## Acknowledgments
735
+
736
+ Protocol knowledge was primarily informed by the [TSLib](https://github.com/Splamy/TS3AudioBot) implementation in [TS3AudioBot](https://github.com/Splamy/TS3AudioBot) by Splamy. Huge thanks to the TS3AudioBot project and its contributors.
737
+
738
+ ## Disclaimer
739
+
740
+ TeamSpeak is a registered trademark of [TeamSpeak Systems GmbH](https://teamspeak.com/). This project is not affiliated with, endorsed by, or associated with TeamSpeak Systems GmbH in any way.
741
+
742
+ This library is a **clean-room implementation** developed from publicly available documentation, protocol analysis of network traffic, and independent research. No proprietary TeamSpeak SDK code, headers, or libraries were used in its creation.
743
+
744
+ ## Contributing
745
+
746
+ See [CONTRIBUTING.md](https://github.com/HoneyBBQ/teamspeak-js/blob/main/.github/CONTRIBUTING.md) for setup, checks and the integration suite.
747
+
748
+ ## License
749
+
750
+ [MIT](https://github.com/HoneyBBQ/teamspeak-js/blob/main/LICENSE)