@honeybbq/teamspeak 0.0.1 → 1.0.0-beta.7

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 (393) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +726 -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/voice.d.ts +24 -0
  12. package/dist/client/api/voice.d.ts.map +1 -0
  13. package/dist/client/api/voice.js +33 -0
  14. package/dist/client/api/voice.js.map +1 -0
  15. package/dist/client/capabilities.d.ts +68 -0
  16. package/dist/client/capabilities.d.ts.map +1 -0
  17. package/dist/client/capabilities.js +59 -0
  18. package/dist/client/capabilities.js.map +1 -0
  19. package/dist/client/client.d.ts +196 -0
  20. package/dist/client/client.d.ts.map +1 -0
  21. package/dist/client/client.js +1523 -0
  22. package/dist/client/client.js.map +1 -0
  23. package/dist/client/commands.d.ts +66 -0
  24. package/dist/client/commands.d.ts.map +1 -0
  25. package/dist/client/commands.js +162 -0
  26. package/dist/client/commands.js.map +1 -0
  27. package/dist/client/crypto/crypt-ops.d.ts +7 -0
  28. package/dist/client/crypto/crypt-ops.d.ts.map +1 -0
  29. package/dist/client/crypto/crypt-ops.js +2 -0
  30. package/dist/client/crypto/crypt-ops.js.map +1 -0
  31. package/dist/client/crypto/crypt.d.ts +37 -0
  32. package/dist/client/crypto/crypt.d.ts.map +1 -0
  33. package/dist/client/crypto/crypt.js +203 -0
  34. package/dist/client/crypto/crypt.js.map +1 -0
  35. package/dist/client/crypto/eax.d.ts +12 -0
  36. package/dist/client/crypto/eax.d.ts.map +1 -0
  37. package/dist/client/crypto/eax.js +118 -0
  38. package/dist/client/crypto/eax.js.map +1 -0
  39. package/dist/client/crypto/identity.d.ts +97 -0
  40. package/dist/client/crypto/identity.d.ts.map +1 -0
  41. package/dist/client/crypto/identity.js +412 -0
  42. package/dist/client/crypto/identity.js.map +1 -0
  43. package/dist/client/crypto/index.d.ts +7 -0
  44. package/dist/client/crypto/index.d.ts.map +1 -0
  45. package/dist/client/crypto/index.js +5 -0
  46. package/dist/client/crypto/index.js.map +1 -0
  47. package/dist/client/crypto/primitives.d.ts +43 -0
  48. package/dist/client/crypto/primitives.d.ts.map +1 -0
  49. package/dist/client/crypto/primitives.js +116 -0
  50. package/dist/client/crypto/primitives.js.map +1 -0
  51. package/dist/client/diagnostics.d.ts +45 -0
  52. package/dist/client/diagnostics.d.ts.map +1 -0
  53. package/dist/client/diagnostics.js +30 -0
  54. package/dist/client/diagnostics.js.map +1 -0
  55. package/dist/client/discovery/index.d.ts +2 -0
  56. package/dist/client/discovery/index.d.ts.map +1 -0
  57. package/dist/client/discovery/index.js +2 -0
  58. package/dist/client/discovery/index.js.map +1 -0
  59. package/dist/client/discovery/resolver.d.ts +26 -0
  60. package/dist/client/discovery/resolver.d.ts.map +1 -0
  61. package/dist/client/discovery/resolver.js +275 -0
  62. package/dist/client/discovery/resolver.js.map +1 -0
  63. package/dist/client/errors.d.ts +82 -0
  64. package/dist/client/errors.d.ts.map +1 -0
  65. package/dist/client/errors.js +201 -0
  66. package/dist/client/errors.js.map +1 -0
  67. package/dist/client/events.d.ts +3 -0
  68. package/dist/client/events.d.ts.map +1 -0
  69. package/dist/client/events.js +8 -0
  70. package/dist/client/events.js.map +1 -0
  71. package/dist/client/handshake/crypt-handshake.d.ts +17 -0
  72. package/dist/client/handshake/crypt-handshake.d.ts.map +1 -0
  73. package/dist/client/handshake/crypt-handshake.js +128 -0
  74. package/dist/client/handshake/crypt-handshake.js.map +1 -0
  75. package/dist/client/handshake/crypt-init2.d.ts +7 -0
  76. package/dist/client/handshake/crypt-init2.d.ts.map +1 -0
  77. package/dist/client/handshake/crypt-init2.js +37 -0
  78. package/dist/client/handshake/crypt-init2.js.map +1 -0
  79. package/dist/client/handshake/index.d.ts +4 -0
  80. package/dist/client/handshake/index.d.ts.map +1 -0
  81. package/dist/client/handshake/index.js +4 -0
  82. package/dist/client/handshake/index.js.map +1 -0
  83. package/dist/client/handshake/license.d.ts +35 -0
  84. package/dist/client/handshake/license.d.ts.map +1 -0
  85. package/dist/client/handshake/license.js +169 -0
  86. package/dist/client/handshake/license.js.map +1 -0
  87. package/dist/client/handshake.d.ts +27 -0
  88. package/dist/client/handshake.d.ts.map +1 -0
  89. package/dist/client/handshake.js +126 -0
  90. package/dist/client/handshake.js.map +1 -0
  91. package/dist/client/helpers.d.ts +6 -0
  92. package/dist/client/helpers.d.ts.map +1 -0
  93. package/dist/client/helpers.js +13 -0
  94. package/dist/client/helpers.js.map +1 -0
  95. package/dist/client/hooks.d.ts +7 -0
  96. package/dist/client/hooks.d.ts.map +1 -0
  97. package/dist/client/hooks.js +28 -0
  98. package/dist/client/hooks.js.map +1 -0
  99. package/dist/client/index.d.ts +26 -0
  100. package/dist/client/index.d.ts.map +1 -0
  101. package/dist/client/index.js +28 -0
  102. package/dist/client/index.js.map +1 -0
  103. package/dist/client/reconnect.d.ts +12 -0
  104. package/dist/client/reconnect.d.ts.map +1 -0
  105. package/dist/client/reconnect.js +44 -0
  106. package/dist/client/reconnect.js.map +1 -0
  107. package/dist/client/throttle.d.ts +20 -0
  108. package/dist/client/throttle.d.ts.map +1 -0
  109. package/dist/client/throttle.js +83 -0
  110. package/dist/client/throttle.js.map +1 -0
  111. package/dist/client/trace.d.ts +223 -0
  112. package/dist/client/trace.d.ts.map +1 -0
  113. package/dist/client/trace.js +13 -0
  114. package/dist/client/trace.js.map +1 -0
  115. package/dist/client/transfer.d.ts +111 -0
  116. package/dist/client/transfer.d.ts.map +1 -0
  117. package/dist/client/transfer.js +243 -0
  118. package/dist/client/transfer.js.map +1 -0
  119. package/dist/client/transport/generation-window.d.ts +30 -0
  120. package/dist/client/transport/generation-window.d.ts.map +1 -0
  121. package/dist/client/transport/generation-window.js +97 -0
  122. package/dist/client/transport/generation-window.js.map +1 -0
  123. package/dist/client/transport/handler.d.ts +61 -0
  124. package/dist/client/transport/handler.d.ts.map +1 -0
  125. package/dist/client/transport/handler.js +793 -0
  126. package/dist/client/transport/handler.js.map +1 -0
  127. package/dist/client/transport/index.d.ts +6 -0
  128. package/dist/client/transport/index.d.ts.map +1 -0
  129. package/dist/client/transport/index.js +5 -0
  130. package/dist/client/transport/index.js.map +1 -0
  131. package/dist/client/transport/packet.d.ts +36 -0
  132. package/dist/client/transport/packet.d.ts.map +1 -0
  133. package/dist/client/transport/packet.js +55 -0
  134. package/dist/client/transport/packet.js.map +1 -0
  135. package/dist/client/transport/quicklz.d.ts +24 -0
  136. package/dist/client/transport/quicklz.d.ts.map +1 -0
  137. package/dist/client/transport/quicklz.js +179 -0
  138. package/dist/client/transport/quicklz.js.map +1 -0
  139. package/dist/client/types.d.ts +226 -0
  140. package/dist/client/types.d.ts.map +1 -0
  141. package/dist/client/types.js +39 -0
  142. package/dist/client/types.js.map +1 -0
  143. package/dist/core/api/channels.d.ts +182 -0
  144. package/dist/core/api/channels.d.ts.map +1 -0
  145. package/dist/core/api/channels.js +155 -0
  146. package/dist/core/api/channels.js.map +1 -0
  147. package/dist/core/api/clients.d.ts +304 -0
  148. package/dist/core/api/clients.d.ts.map +1 -0
  149. package/dist/core/api/clients.js +260 -0
  150. package/dist/core/api/clients.js.map +1 -0
  151. package/dist/core/api/command.d.ts +305 -0
  152. package/dist/core/api/command.d.ts.map +1 -0
  153. package/dist/core/api/command.js +363 -0
  154. package/dist/core/api/command.js.map +1 -0
  155. package/dist/core/api/files.d.ts +153 -0
  156. package/dist/core/api/files.d.ts.map +1 -0
  157. package/dist/core/api/files.js +181 -0
  158. package/dist/core/api/files.js.map +1 -0
  159. package/dist/core/api/groups.d.ts +248 -0
  160. package/dist/core/api/groups.d.ts.map +1 -0
  161. package/dist/core/api/groups.js +271 -0
  162. package/dist/core/api/groups.js.map +1 -0
  163. package/dist/core/api/moderation.d.ts +205 -0
  164. package/dist/core/api/moderation.d.ts.map +1 -0
  165. package/dist/core/api/moderation.js +209 -0
  166. package/dist/core/api/moderation.js.map +1 -0
  167. package/dist/core/api/parse.d.ts +16 -0
  168. package/dist/core/api/parse.d.ts.map +1 -0
  169. package/dist/core/api/parse.js +40 -0
  170. package/dist/core/api/parse.js.map +1 -0
  171. package/dist/core/api/server.d.ts +310 -0
  172. package/dist/core/api/server.d.ts.map +1 -0
  173. package/dist/core/api/server.js +290 -0
  174. package/dist/core/api/server.js.map +1 -0
  175. package/dist/core/command/command.d.ts +20 -0
  176. package/dist/core/command/command.d.ts.map +1 -0
  177. package/dist/core/command/command.js +112 -0
  178. package/dist/core/command/command.js.map +1 -0
  179. package/dist/core/command/ids.d.ts +125 -0
  180. package/dist/core/command/ids.d.ts.map +1 -0
  181. package/dist/core/command/ids.js +85 -0
  182. package/dist/core/command/ids.js.map +1 -0
  183. package/dist/core/command/parser.d.ts +17 -0
  184. package/dist/core/command/parser.d.ts.map +1 -0
  185. package/dist/core/command/parser.js +65 -0
  186. package/dist/core/command/parser.js.map +1 -0
  187. package/dist/core/command/request.d.ts +61 -0
  188. package/dist/core/command/request.d.ts.map +1 -0
  189. package/dist/core/command/request.js +64 -0
  190. package/dist/core/command/request.js.map +1 -0
  191. package/dist/core/command/responses.d.ts +59 -0
  192. package/dist/core/command/responses.d.ts.map +1 -0
  193. package/dist/core/command/responses.js +74 -0
  194. package/dist/core/command/responses.js.map +1 -0
  195. package/dist/core/command-name.d.ts +333 -0
  196. package/dist/core/command-name.d.ts.map +1 -0
  197. package/dist/core/command-name.js +331 -0
  198. package/dist/core/command-name.js.map +1 -0
  199. package/dist/core/enums.d.ts +146 -0
  200. package/dist/core/enums.d.ts.map +1 -0
  201. package/dist/core/enums.js +132 -0
  202. package/dist/core/enums.js.map +1 -0
  203. package/dist/core/errorcode.d.ts +413 -0
  204. package/dist/core/errorcode.d.ts.map +1 -0
  205. package/dist/core/errorcode.js +410 -0
  206. package/dist/core/errorcode.js.map +1 -0
  207. package/dist/core/errors.d.ts +111 -0
  208. package/dist/core/errors.d.ts.map +1 -0
  209. package/dist/core/errors.js +233 -0
  210. package/dist/core/errors.js.map +1 -0
  211. package/dist/core/events.d.ts +207 -0
  212. package/dist/core/events.d.ts.map +1 -0
  213. package/dist/core/events.js +6 -0
  214. package/dist/core/events.js.map +1 -0
  215. package/dist/core/helpers.d.ts +42 -0
  216. package/dist/core/helpers.d.ts.map +1 -0
  217. package/dist/core/helpers.js +156 -0
  218. package/dist/core/helpers.js.map +1 -0
  219. package/dist/core/index.d.ts +35 -0
  220. package/dist/core/index.d.ts.map +1 -0
  221. package/dist/core/index.js +34 -0
  222. package/dist/core/index.js.map +1 -0
  223. package/dist/core/internal.d.ts +23 -0
  224. package/dist/core/internal.d.ts.map +1 -0
  225. package/dist/core/internal.js +20 -0
  226. package/dist/core/internal.js.map +1 -0
  227. package/dist/core/middleware.d.ts +14 -0
  228. package/dist/core/middleware.d.ts.map +1 -0
  229. package/dist/core/middleware.js +18 -0
  230. package/dist/core/middleware.js.map +1 -0
  231. package/dist/core/notification-name.d.ts +154 -0
  232. package/dist/core/notification-name.d.ts.map +1 -0
  233. package/dist/core/notification-name.js +152 -0
  234. package/dist/core/notification-name.js.map +1 -0
  235. package/dist/core/notifications.d.ts +43 -0
  236. package/dist/core/notifications.d.ts.map +1 -0
  237. package/dist/core/notifications.js +116 -0
  238. package/dist/core/notifications.js.map +1 -0
  239. package/dist/core/permission-name.d.ts +533 -0
  240. package/dist/core/permission-name.d.ts.map +1 -0
  241. package/dist/core/permission-name.js +531 -0
  242. package/dist/core/permission-name.js.map +1 -0
  243. package/dist/core/permission.d.ts +31 -0
  244. package/dist/core/permission.d.ts.map +1 -0
  245. package/dist/core/permission.js +20 -0
  246. package/dist/core/permission.js.map +1 -0
  247. package/dist/core/property-name.d.ts +403 -0
  248. package/dist/core/property-name.d.ts.map +1 -0
  249. package/dist/core/property-name.js +405 -0
  250. package/dist/core/property-name.js.map +1 -0
  251. package/dist/core/reason.d.ts +39 -0
  252. package/dist/core/reason.d.ts.map +1 -0
  253. package/dist/core/reason.js +36 -0
  254. package/dist/core/reason.js.map +1 -0
  255. package/dist/core/reconnect.d.ts +59 -0
  256. package/dist/core/reconnect.d.ts.map +1 -0
  257. package/dist/core/reconnect.js +55 -0
  258. package/dist/core/reconnect.js.map +1 -0
  259. package/dist/core/types.d.ts +110 -0
  260. package/dist/core/types.d.ts.map +1 -0
  261. package/dist/core/types.js +27 -0
  262. package/dist/core/types.js.map +1 -0
  263. package/dist/query/client.d.ts +194 -0
  264. package/dist/query/client.d.ts.map +1 -0
  265. package/dist/query/client.js +967 -0
  266. package/dist/query/client.js.map +1 -0
  267. package/dist/query/errors.d.ts +61 -0
  268. package/dist/query/errors.d.ts.map +1 -0
  269. package/dist/query/errors.js +100 -0
  270. package/dist/query/errors.js.map +1 -0
  271. package/dist/query/index.d.ts +36 -0
  272. package/dist/query/index.d.ts.map +1 -0
  273. package/dist/query/index.js +34 -0
  274. package/dist/query/index.js.map +1 -0
  275. package/dist/query/knownhosts.d.ts +61 -0
  276. package/dist/query/knownhosts.d.ts.map +1 -0
  277. package/dist/query/knownhosts.js +223 -0
  278. package/dist/query/knownhosts.js.map +1 -0
  279. package/dist/query/lines.d.ts +14 -0
  280. package/dist/query/lines.d.ts.map +1 -0
  281. package/dist/query/lines.js +29 -0
  282. package/dist/query/lines.js.map +1 -0
  283. package/dist/query/options.d.ts +187 -0
  284. package/dist/query/options.d.ts.map +1 -0
  285. package/dist/query/options.js +213 -0
  286. package/dist/query/options.js.map +1 -0
  287. package/dist/query/reconnect.d.ts +29 -0
  288. package/dist/query/reconnect.d.ts.map +1 -0
  289. package/dist/query/reconnect.js +87 -0
  290. package/dist/query/reconnect.js.map +1 -0
  291. package/dist/query/ssh.d.ts +345 -0
  292. package/dist/query/ssh.d.ts.map +1 -0
  293. package/dist/query/ssh.js +241 -0
  294. package/dist/query/ssh.js.map +1 -0
  295. package/dist/query/stream.d.ts +38 -0
  296. package/dist/query/stream.d.ts.map +1 -0
  297. package/dist/query/stream.js +70 -0
  298. package/dist/query/stream.js.map +1 -0
  299. package/dist/query/tcp.d.ts +38 -0
  300. package/dist/query/tcp.d.ts.map +1 -0
  301. package/dist/query/tcp.js +53 -0
  302. package/dist/query/tcp.js.map +1 -0
  303. package/dist/query/transport.d.ts +36 -0
  304. package/dist/query/transport.d.ts.map +1 -0
  305. package/dist/query/transport.js +2 -0
  306. package/dist/query/transport.js.map +1 -0
  307. package/dist/query/web.d.ts +54 -0
  308. package/dist/query/web.d.ts.map +1 -0
  309. package/dist/query/web.js +146 -0
  310. package/dist/query/web.js.map +1 -0
  311. package/dist/versions/index.d.ts +3094 -0
  312. package/dist/versions/index.d.ts.map +1 -0
  313. package/dist/versions/index.js +9237 -0
  314. package/dist/versions/index.js.map +1 -0
  315. package/package.json +118 -4
  316. package/src/client/abort.ts +24 -0
  317. package/src/client/address.ts +74 -0
  318. package/src/client/api/voice.ts +61 -0
  319. package/src/client/capabilities.ts +106 -0
  320. package/src/client/client.ts +1809 -0
  321. package/src/client/commands.ts +193 -0
  322. package/src/client/crypto/crypt-ops.ts +6 -0
  323. package/src/client/crypto/crypt.ts +275 -0
  324. package/src/client/crypto/eax.ts +152 -0
  325. package/src/client/crypto/identity.ts +484 -0
  326. package/src/client/crypto/index.ts +21 -0
  327. package/src/client/crypto/primitives.ts +141 -0
  328. package/src/client/diagnostics.ts +58 -0
  329. package/src/client/discovery/index.ts +1 -0
  330. package/src/client/discovery/resolver.ts +325 -0
  331. package/src/client/errors.ts +217 -0
  332. package/src/client/events.ts +12 -0
  333. package/src/client/handshake/crypt-handshake.ts +157 -0
  334. package/src/client/handshake/crypt-init2.ts +48 -0
  335. package/src/client/handshake/index.ts +3 -0
  336. package/src/client/handshake/license.ts +208 -0
  337. package/src/client/handshake.ts +150 -0
  338. package/src/client/helpers.ts +10 -0
  339. package/src/client/hooks.ts +30 -0
  340. package/src/client/index.ts +93 -0
  341. package/src/client/reconnect.ts +43 -0
  342. package/src/client/throttle.ts +92 -0
  343. package/src/client/trace.ts +237 -0
  344. package/src/client/transfer.ts +436 -0
  345. package/src/client/transport/generation-window.ts +108 -0
  346. package/src/client/transport/handler.ts +926 -0
  347. package/src/client/transport/index.ts +14 -0
  348. package/src/client/transport/packet.ts +69 -0
  349. package/src/client/transport/quicklz.ts +209 -0
  350. package/src/client/types.ts +268 -0
  351. package/src/core/api/channels.ts +396 -0
  352. package/src/core/api/clients.ts +654 -0
  353. package/src/core/api/command.ts +563 -0
  354. package/src/core/api/files.ts +405 -0
  355. package/src/core/api/groups.ts +622 -0
  356. package/src/core/api/moderation.ts +525 -0
  357. package/src/core/api/parse.ts +52 -0
  358. package/src/core/api/server.ts +709 -0
  359. package/src/core/command/command.ts +125 -0
  360. package/src/core/command/ids.ts +149 -0
  361. package/src/core/command/parser.ts +68 -0
  362. package/src/core/command/request.ts +119 -0
  363. package/src/core/command/responses.ts +114 -0
  364. package/src/core/command-name.ts +334 -0
  365. package/src/core/enums.ts +167 -0
  366. package/src/core/errorcode.ts +412 -0
  367. package/src/core/errors.ts +258 -0
  368. package/src/core/events.ts +219 -0
  369. package/src/core/helpers.ts +161 -0
  370. package/src/core/index.ts +126 -0
  371. package/src/core/internal.ts +23 -0
  372. package/src/core/middleware.ts +24 -0
  373. package/src/core/notification-name.ts +155 -0
  374. package/src/core/notifications.ts +157 -0
  375. package/src/core/permission-name.ts +538 -0
  376. package/src/core/permission.ts +34 -0
  377. package/src/core/property-name.ts +411 -0
  378. package/src/core/reason.ts +38 -0
  379. package/src/core/reconnect.ts +98 -0
  380. package/src/core/types.ts +138 -0
  381. package/src/query/client.ts +1132 -0
  382. package/src/query/errors.ts +108 -0
  383. package/src/query/index.ts +65 -0
  384. package/src/query/knownhosts.ts +257 -0
  385. package/src/query/lines.ts +28 -0
  386. package/src/query/options.ts +388 -0
  387. package/src/query/reconnect.ts +84 -0
  388. package/src/query/ssh.ts +614 -0
  389. package/src/query/stream.ts +91 -0
  390. package/src/query/tcp.ts +85 -0
  391. package/src/query/transport.ts +35 -0
  392. package/src/query/web.ts +195 -0
  393. package/src/versions/index.ts +10774 -0
@@ -0,0 +1,525 @@
1
+ /**
2
+ * Bans, complaints, offline messages, text messages and the server log.
3
+ *
4
+ * All administrative: expect a permission error, not an empty list, when the
5
+ * client lacks the rights.
6
+ */
7
+
8
+ import {
9
+ nonZero,
10
+ firstRow,
11
+ exec,
12
+ query,
13
+ list,
14
+ encodeFields,
15
+ nonEmpty,
16
+ toWireDuration,
17
+ str,
18
+ big,
19
+ num,
20
+ bool,
21
+ date,
22
+ durationMs,
23
+ SECOND,
24
+ } from "./command.js";
25
+ import type { Params, WireNames } from "./command.js";
26
+ import type { CommandExecutor, CommandOptions, ParamValue } from "../command/request.js";
27
+ import type { BanID, ClientDBID, ClientID, MessageID, UID } from "../command/ids.js";
28
+ import { asBanID, asClientDBID, asMessageID, asUID } from "../command/ids.js";
29
+ import { TextMessageTarget } from "../enums.js";
30
+ import type { LogLevel } from "../enums.js";
31
+
32
+ // ---- Bans -------------------------------------------------------------------
33
+
34
+ /** A ban, as `banlist` reports it. */
35
+ export interface BanEntry {
36
+ /** The ban's id. */
37
+ readonly id: BanID;
38
+ /** The address pattern the ban matches, or "". */
39
+ readonly ip: string;
40
+ /** The nickname pattern the ban matches, or "". */
41
+ readonly name: string;
42
+ /** The unique identifier the ban matches, or "". */
43
+ readonly uid: UID;
44
+ /** The nickname of the last client the ban caught. */
45
+ readonly lastNickname: string;
46
+ /** When the ban was made. */
47
+ readonly createdAt: Date | undefined;
48
+ /**
49
+ * How long the ban lasts from `createdAt`, in milliseconds; 0 is a
50
+ * permanent ban. The server reports it in seconds.
51
+ */
52
+ readonly durationMs: number;
53
+ /** Who made the ban. */
54
+ readonly invokerDatabaseID: ClientDBID;
55
+ /** Their nickname. */
56
+ readonly invokerName: string;
57
+ /** Their unique identifier. */
58
+ readonly invokerUID: UID;
59
+ /** The reason given. */
60
+ readonly reason: string;
61
+ /** How many times the ban has turned a client away. */
62
+ readonly enforcements: number;
63
+ }
64
+
65
+ const parseBan = (row: Record<string, string>): BanEntry => ({
66
+ id: asBanID(big(row, "banid")),
67
+ ip: str(row, "ip"),
68
+ name: str(row, "name"),
69
+ uid: asUID(str(row, "uid")),
70
+ lastNickname: str(row, "lastnickname"),
71
+ createdAt: date(row, "created"),
72
+ durationMs: durationMs(row, "duration", SECOND),
73
+ invokerDatabaseID: asClientDBID(big(row, "invokercldbid")),
74
+ invokerName: str(row, "invokername"),
75
+ invokerUID: asUID(str(row, "invokeruid")),
76
+ reason: str(row, "reason"),
77
+ enforcements: num(row, "enforcements"),
78
+ });
79
+
80
+ /** Every active ban. A server with none answers an empty list. */
81
+ export async function listBans(
82
+ client: CommandExecutor,
83
+ options?: CommandOptions,
84
+ ): Promise<BanEntry[]> {
85
+ return (await list(client, "banlist", [], options)).map(parseBan);
86
+ }
87
+
88
+ /**
89
+ * A ban's duration on the wire. A permanent ban (0) omits it: the server's
90
+ * default is permanent, which is also what `time=0` means. A positive duration
91
+ * never rounds down to 0, which would make it permanent.
92
+ */
93
+ const banTime = (ms: number): ParamValue => (ms === 0 ? undefined : toWireDuration(ms, SECOND));
94
+
95
+ /**
96
+ * What a ban matches, how long it lasts and why: the ban itself, never a
97
+ * command's options. `ip` and `name` are regular expressions matched against
98
+ * a client's address and nickname.
99
+ *
100
+ * Unset fields are omitted, and an empty string is treated as unset in every
101
+ * field here, never sent: an empty pattern would match every client.
102
+ */
103
+ export interface BanFields {
104
+ /** The address pattern to ban (`ip`). */
105
+ readonly ip?: string | undefined;
106
+ /** The nickname pattern to ban (`name`). */
107
+ readonly name?: string | undefined;
108
+ /** The unique identifier to ban (`uid`). */
109
+ readonly uid?: UID | undefined;
110
+ /** The reason, shown to the banned client (`banreason`). */
111
+ readonly reason?: string | undefined;
112
+ /**
113
+ * How long the ban lasts, in milliseconds (`time`); unset or 0 is permanent.
114
+ * Sent in whole seconds, and a positive duration under a second is sent as
115
+ * one rather than rounded down to forever.
116
+ */
117
+ readonly durationMs?: number | undefined;
118
+ }
119
+
120
+ /**
121
+ * A ban to add: {@link BanFields}, at least one of `ip`, `name` or `uid` set; a
122
+ * ban matching nothing is refused before anything is sent. It carries no
123
+ * signal or timeoutMs: those are addBan's separate last argument.
124
+ */
125
+ export type BanOptions = BanFields;
126
+
127
+ const banNames: WireNames<BanFields> = {
128
+ ip: ["ip", nonEmpty],
129
+ name: ["name", nonEmpty],
130
+ uid: ["uid", nonEmpty],
131
+ reason: ["banreason", nonEmpty],
132
+ durationMs: ["time", banTime],
133
+ };
134
+
135
+ /**
136
+ * How long {@link banClient}'s bans last and why — {@link BanFields}' duration
137
+ * and reason — with the command's signal and timeoutMs, as the last argument.
138
+ */
139
+ export interface BanClientOptions
140
+ extends Pick<BanFields, "durationMs" | "reason">, CommandOptions {}
141
+
142
+ const banClientNames: WireNames<BanClientOptions> = {
143
+ durationMs: ["time", banTime],
144
+ reason: ["banreason", nonEmpty],
145
+ };
146
+
147
+ /**
148
+ * Add a ban and return its id — over ServerQuery. The voice protocol reports
149
+ * no id, so there this resolves to undefined.
150
+ *
151
+ * `ban` is what to ban; the command's `signal` and `timeoutMs` go in `options`,
152
+ * a separate last argument — set among the fields, they are not read.
153
+ */
154
+ export async function addBan(
155
+ client: CommandExecutor,
156
+ ban: BanOptions,
157
+ options?: CommandOptions,
158
+ ): Promise<BanID | undefined> {
159
+ if (!ban.ip && !ban.name && !ban.uid) {
160
+ throw new TypeError("a ban needs an ip, a name or a uid to match");
161
+ }
162
+ const rows = await query(client, "banadd", encodeFields(ban, banNames), options);
163
+ return rows[0]?.["banid"] === undefined ? undefined : asBanID(big(rows[0], "banid"));
164
+ }
165
+
166
+ /**
167
+ * Ban a connected client by clid, and return the id of every ban that made.
168
+ *
169
+ * The server bans the client on several counts at once — its address, its
170
+ * uid, and on TS6 its myTeamSpeak id — and over ServerQuery answers one
171
+ * `banid` row for each; returning the first left the others to be found by
172
+ * hand. The voice protocol reports no ids, so there this resolves to `[]`.
173
+ */
174
+ export async function banClient(
175
+ client: CommandExecutor,
176
+ clid: ClientID,
177
+ options: BanClientOptions = {},
178
+ ): Promise<BanID[]> {
179
+ const rows = await query(
180
+ client,
181
+ "banclient",
182
+ [["clid", clid], ...encodeFields(options, banClientNames)],
183
+ options,
184
+ );
185
+ return rows.flatMap((row) => (str(row, "banid") === "" ? [] : [asBanID(big(row, "banid"))]));
186
+ }
187
+
188
+ /** Remove a ban. */
189
+ export async function deleteBan(
190
+ client: CommandExecutor,
191
+ banID: BanID,
192
+ options?: CommandOptions,
193
+ ): Promise<void> {
194
+ await exec(client, "bandel", [["banid", banID]], options);
195
+ }
196
+
197
+ /** Remove every ban. */
198
+ export async function deleteAllBans(
199
+ client: CommandExecutor,
200
+ options?: CommandOptions,
201
+ ): Promise<void> {
202
+ await exec(client, "bandelall", [], options);
203
+ }
204
+
205
+ // ---- Complaints -------------------------------------------------------------
206
+
207
+ /** A complaint one client filed against another. */
208
+ export interface Complaint {
209
+ /** Who the complaint is about. */
210
+ readonly targetDatabaseID: ClientDBID;
211
+ /** Their nickname. */
212
+ readonly targetName: string;
213
+ /** Who filed it. */
214
+ readonly fromDatabaseID: ClientDBID;
215
+ /** Their nickname. */
216
+ readonly fromName: string;
217
+ /** The complaint. */
218
+ readonly message: string;
219
+ /** When it was filed. */
220
+ readonly createdAt: Date | undefined;
221
+ }
222
+
223
+ const parseComplaint = (row: Record<string, string>): Complaint => ({
224
+ targetDatabaseID: asClientDBID(big(row, "tcldbid")),
225
+ targetName: str(row, "tname"),
226
+ fromDatabaseID: asClientDBID(big(row, "fcldbid")),
227
+ fromName: str(row, "fname"),
228
+ message: str(row, "message"),
229
+ createdAt: date(row, "timestamp"),
230
+ });
231
+
232
+ /** Which complaints {@link listComplaints} reports. */
233
+ export interface ComplaintListOptions extends CommandOptions {
234
+ /** Only those against this client; unset for all (`tcldbid`). */
235
+ readonly targetDatabaseID?: ClientDBID | undefined;
236
+ }
237
+
238
+ /** Complaints, optionally only those against one client. */
239
+ export async function listComplaints(
240
+ client: CommandExecutor,
241
+ options: ComplaintListOptions = {},
242
+ ): Promise<Complaint[]> {
243
+ // 0 names no client, so it lists every complaint, as unset does.
244
+ const target = options.targetDatabaseID;
245
+ const params: Params = [["tcldbid", target === undefined ? undefined : nonZero(target)]];
246
+ return (await list(client, "complainlist", params, options)).map(parseComplaint);
247
+ }
248
+
249
+ /** File a complaint against a client. */
250
+ export async function addComplaint(
251
+ client: CommandExecutor,
252
+ targetDatabaseID: ClientDBID,
253
+ message: string,
254
+ options?: CommandOptions,
255
+ ): Promise<void> {
256
+ await exec(
257
+ client,
258
+ "complainadd",
259
+ [
260
+ ["tcldbid", targetDatabaseID],
261
+ ["message", message],
262
+ ],
263
+ options,
264
+ );
265
+ }
266
+
267
+ /** Withdraw one complaint. */
268
+ export async function deleteComplaint(
269
+ client: CommandExecutor,
270
+ targetDatabaseID: ClientDBID,
271
+ fromDatabaseID: ClientDBID,
272
+ options?: CommandOptions,
273
+ ): Promise<void> {
274
+ await exec(
275
+ client,
276
+ "complaindel",
277
+ [
278
+ ["tcldbid", targetDatabaseID],
279
+ ["fcldbid", fromDatabaseID],
280
+ ],
281
+ options,
282
+ );
283
+ }
284
+
285
+ /** Withdraw every complaint against a client. */
286
+ export async function deleteAllComplaints(
287
+ client: CommandExecutor,
288
+ targetDatabaseID: ClientDBID,
289
+ options?: CommandOptions,
290
+ ): Promise<void> {
291
+ await exec(client, "complaindelall", [["tcldbid", targetDatabaseID]], options);
292
+ }
293
+
294
+ // ---- Offline messages -------------------------------------------------------
295
+
296
+ /** A message left for a client while they were away. */
297
+ export interface OfflineMessage {
298
+ /** The message's id. */
299
+ readonly id: MessageID;
300
+ /** The sender's unique identifier. */
301
+ readonly uid: UID;
302
+ /** The subject. */
303
+ readonly subject: string;
304
+ /** The message; `messagelist` leaves it out, `getMessage` has it. */
305
+ readonly message: string;
306
+ /** When it was sent. */
307
+ readonly sentAt: Date | undefined;
308
+ /** Whether it has been read. */
309
+ readonly isRead: boolean;
310
+ }
311
+
312
+ const parseMessage = (row: Record<string, string>): OfflineMessage => ({
313
+ id: asMessageID(big(row, "msgid")),
314
+ uid: asUID(str(row, "cluid")),
315
+ subject: str(row, "subject"),
316
+ message: str(row, "message"),
317
+ sentAt: date(row, "timestamp"),
318
+ isRead: bool(row, "flag_read"),
319
+ });
320
+
321
+ /** Offline messages for this client. None is an empty list. */
322
+ export async function listMessages(
323
+ client: CommandExecutor,
324
+ options?: CommandOptions,
325
+ ): Promise<OfflineMessage[]> {
326
+ return (await list(client, "messagelist", [], options)).map(parseMessage);
327
+ }
328
+
329
+ /** One offline message, with its text. */
330
+ export async function getMessage(
331
+ client: CommandExecutor,
332
+ messageID: MessageID,
333
+ options?: CommandOptions,
334
+ ): Promise<OfflineMessage> {
335
+ const rows = await query(client, "messageget", [["msgid", messageID]], options);
336
+ return { ...parseMessage(firstRow(rows, "messageget")), id: messageID };
337
+ }
338
+
339
+ /** Delete an offline message. */
340
+ export async function deleteMessage(
341
+ client: CommandExecutor,
342
+ messageID: MessageID,
343
+ options?: CommandOptions,
344
+ ): Promise<void> {
345
+ await exec(client, "messagedel", [["msgid", messageID]], options);
346
+ }
347
+
348
+ /** The flags of an offline message that can be changed. */
349
+ export interface MessageFlags {
350
+ /** Whether the message is marked read (`flag`). */
351
+ readonly read: boolean;
352
+ }
353
+
354
+ /** Mark a message read or unread. */
355
+ export async function updateMessageFlag(
356
+ client: CommandExecutor,
357
+ messageID: MessageID,
358
+ flags: MessageFlags,
359
+ options?: CommandOptions,
360
+ ): Promise<void> {
361
+ await exec(
362
+ client,
363
+ "messageupdateflag",
364
+ [
365
+ ["msgid", messageID],
366
+ ["flag", flags.read],
367
+ ],
368
+ options,
369
+ );
370
+ }
371
+
372
+ // ---- Text messages ----------------------------------------------------------
373
+ //
374
+ // Three functions rather than one taking a mode and an id, because the id meant
375
+ // a different thing in each mode — a clid, a cid, or nothing — and an untyped
376
+ // one let a channel id reach an unrelated client.
377
+ //
378
+ // Each waits for the server's answer, so a refusal — no permission to message
379
+ // that target — is thrown rather than lost.
380
+
381
+ /** Send a text message to one client. */
382
+ export async function sendPrivateMessage(
383
+ client: CommandExecutor,
384
+ clid: ClientID,
385
+ message: string,
386
+ options?: CommandOptions,
387
+ ): Promise<void> {
388
+ await exec(
389
+ client,
390
+ "sendtextmessage",
391
+ [
392
+ ["targetmode", TextMessageTarget.Client],
393
+ ["target", clid],
394
+ ["msg", message],
395
+ ],
396
+ options,
397
+ );
398
+ }
399
+
400
+ /**
401
+ * Send a text message to the channel this connection is in.
402
+ *
403
+ * It takes no channel because the server takes none: measured on TS3 and TS6,
404
+ * a channel message naming another channel still arrives in the sender's own.
405
+ * To write to another channel, move there first.
406
+ */
407
+ export async function sendChannelMessage(
408
+ client: CommandExecutor,
409
+ message: string,
410
+ options?: CommandOptions,
411
+ ): Promise<void> {
412
+ await exec(
413
+ client,
414
+ "sendtextmessage",
415
+ [
416
+ ["targetmode", TextMessageTarget.Channel],
417
+ ["msg", message],
418
+ ],
419
+ options,
420
+ );
421
+ }
422
+
423
+ /** Send a text message to everyone on the virtual server. */
424
+ export async function sendServerMessage(
425
+ client: CommandExecutor,
426
+ message: string,
427
+ options?: CommandOptions,
428
+ ): Promise<void> {
429
+ await exec(
430
+ client,
431
+ "sendtextmessage",
432
+ [
433
+ ["targetmode", TextMessageTarget.Server],
434
+ ["msg", message],
435
+ ],
436
+ options,
437
+ );
438
+ }
439
+
440
+ // ---- Log --------------------------------------------------------------------
441
+
442
+ /** One read of the server log. */
443
+ export interface LogPage {
444
+ /** The lines read, in the order the server sent them. */
445
+ readonly lines: readonly string[];
446
+ /**
447
+ * The byte offset the read stopped at. Pass it as the next read's
448
+ * `beginPosition` to continue from there.
449
+ */
450
+ readonly lastPosition: number;
451
+ /** The log file's size in bytes. */
452
+ readonly fileSize: number;
453
+ }
454
+
455
+ /**
456
+ * Which part of the log {@link viewLog} reads. Unset fields are omitted, and
457
+ * left to the server.
458
+ *
459
+ * The log is paged by byte offset rather than by row, and nothing says when
460
+ * the walk is done, so there is no iterator as there is for the client
461
+ * database: read a page, then pass its `lastPosition` as the next read's
462
+ * `beginPosition`.
463
+ */
464
+ export interface LogViewOptions extends CommandOptions {
465
+ /** How many lines to read, at most 100; unset or 0 leaves it to the server (`lines`). */
466
+ readonly lines?: number | undefined;
467
+ /** Read backwards from `beginPosition`, newest line first; false by default (`reverse`, always sent). */
468
+ readonly reverse?: boolean | undefined;
469
+ /** Read the instance log rather than the virtual server's; false by default (`instance`, always sent). */
470
+ readonly instance?: boolean | undefined;
471
+ /**
472
+ * The byte offset to read from; 0 is the start of the log, and unset leaves
473
+ * where to start to the server (`begin_pos`).
474
+ */
475
+ readonly beginPosition?: number | undefined;
476
+ }
477
+
478
+ const logViewNames: WireNames<LogViewOptions> = {
479
+ lines: ["lines", (lines) => (lines === 0 ? undefined : lines)],
480
+ reverse: "reverse",
481
+ instance: "instance",
482
+ beginPosition: "begin_pos",
483
+ };
484
+
485
+ /** Read a page of the server log. */
486
+ export async function viewLog(
487
+ client: CommandExecutor,
488
+ options: LogViewOptions = {},
489
+ ): Promise<LogPage> {
490
+ const fields: LogViewOptions = {
491
+ ...options,
492
+ reverse: options.reverse ?? false,
493
+ instance: options.instance ?? false,
494
+ };
495
+ const rows = await query(client, "logview", encodeFields(fields, logViewNames), options);
496
+ const first = firstRow(rows, "logview");
497
+ // One line per row, under the key `l`. This used to read only a `log` field
498
+ // from the first row, which the server does not send; it is still read,
499
+ // should a server send the lines that way.
500
+ const lines = rows.flatMap((row) => (row["l"] === undefined ? [] : [row["l"]]));
501
+ const joined = str(first, "log");
502
+ return {
503
+ lines: lines.length === 0 && joined !== "" ? joined.split("\n") : lines,
504
+ lastPosition: num(first, "last_pos"),
505
+ fileSize: num(first, "file_size"),
506
+ };
507
+ }
508
+
509
+ /** Write an entry to the server log. */
510
+ export async function addLog(
511
+ client: CommandExecutor,
512
+ level: LogLevel,
513
+ message: string,
514
+ options?: CommandOptions,
515
+ ): Promise<void> {
516
+ await exec(
517
+ client,
518
+ "logadd",
519
+ [
520
+ ["loglevel", level],
521
+ ["logmsg", message],
522
+ ],
523
+ options,
524
+ );
525
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Row parsers shared with the client and query modules, kept out of the public index:
3
+ * they read wire rows, which is plumbing, not API. They reach them through
4
+ * `./internal`.
5
+ */
6
+
7
+ import { str, big, num, uint, U16, bool, date, durationMs, MILLISECOND } from "./command.js";
8
+ import type { ServerGroupID } from "../command/ids.js";
9
+ import {
10
+ asChannelID,
11
+ asChannelGroupID,
12
+ asClientID,
13
+ asServerGroupID,
14
+ asUID,
15
+ } from "../command/ids.js";
16
+ import type { ClientEntry } from "./clients.js";
17
+
18
+ /** A comma-separated list of server group ids; anything that is not one is skipped. */
19
+ export function parseServerGroups(raw: string): ServerGroupID[] {
20
+ if (raw === "") return [];
21
+ return raw
22
+ .split(",")
23
+ .flatMap((id) =>
24
+ /^\d{1,20}$/.test(id) && BigInt(id) < 1n << 64n ? [asServerGroupID(BigInt(id))] : [],
25
+ );
26
+ }
27
+
28
+ /**
29
+ * Read a client from a `clientlist` row, or from a `notifycliententerview`,
30
+ * which names its channel `ctid` where the list says `cid`. Reached by the
31
+ * client module through `./internal`.
32
+ */
33
+ export function parseClient(row: Record<string, string>): ClientEntry {
34
+ return {
35
+ id: asClientID(uint(row, "clid", U16)),
36
+ nickname: str(row, "client_nickname"),
37
+ uid: asUID(str(row, "client_unique_identifier")),
38
+ channelID: asChannelID(big(row, row["cid"] === undefined ? "ctid" : "cid")),
39
+ type: num(row, "client_type"),
40
+ serverGroups: parseServerGroups(row["client_servergroups"] ?? ""),
41
+ isAway: bool(row, "client_away"),
42
+ isRecording: bool(row, "client_is_recording"),
43
+ isTalker: bool(row, "client_is_talker"),
44
+ channelGroupID: asChannelGroupID(big(row, "client_channel_group_id")),
45
+ createdAt: date(row, "client_created"),
46
+ lastConnectedAt: date(row, "client_lastconnected"),
47
+ idleTimeMs:
48
+ row["client_idle_time"] === undefined
49
+ ? undefined
50
+ : durationMs(row, "client_idle_time", MILLISECOND),
51
+ };
52
+ }