@honeybbq/teamspeak 1.0.0-beta.11 → 1.0.0-beta.13
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.
- package/README.md +52 -7
- package/dist/client/api/voice.d.ts +13 -0
- package/dist/client/api/voice.d.ts.map +1 -1
- package/dist/client/api/voice.js +20 -1
- package/dist/client/api/voice.js.map +1 -1
- package/dist/client/capabilities.d.ts +4 -4
- package/dist/client/capabilities.d.ts.map +1 -1
- package/dist/client/capabilities.js +3 -8
- package/dist/client/capabilities.js.map +1 -1
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +120 -18
- package/dist/client/client.js.map +1 -1
- package/dist/client/crypto/crypt.d.ts +25 -4
- package/dist/client/crypto/crypt.d.ts.map +1 -1
- package/dist/client/crypto/crypt.js +41 -9
- package/dist/client/crypto/crypt.js.map +1 -1
- package/dist/client/crypto/identity.d.ts +2 -0
- package/dist/client/crypto/identity.d.ts.map +1 -1
- package/dist/client/crypto/identity.js +2 -2
- package/dist/client/crypto/identity.js.map +1 -1
- package/dist/client/crypto/index.d.ts +1 -1
- package/dist/client/crypto/index.d.ts.map +1 -1
- package/dist/client/crypto/index.js +1 -1
- package/dist/client/crypto/index.js.map +1 -1
- package/dist/client/errors.d.ts +14 -0
- package/dist/client/errors.d.ts.map +1 -1
- package/dist/client/errors.js +28 -0
- package/dist/client/errors.js.map +1 -1
- package/dist/client/handshake/crypt-handshake.d.ts +8 -2
- package/dist/client/handshake/crypt-handshake.d.ts.map +1 -1
- package/dist/client/handshake/crypt-handshake.js +26 -20
- package/dist/client/handshake/crypt-handshake.js.map +1 -1
- package/dist/client/index.d.ts +3 -3
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +2 -2
- package/dist/client/index.js.map +1 -1
- package/dist/client/trace.d.ts +7 -0
- package/dist/client/trace.d.ts.map +1 -1
- package/dist/client/transport/handler.d.ts +2 -0
- package/dist/client/transport/handler.d.ts.map +1 -1
- package/dist/client/transport/handler.js +4 -0
- package/dist/client/transport/handler.js.map +1 -1
- package/dist/client/types.d.ts +25 -3
- package/dist/client/types.d.ts.map +1 -1
- package/dist/client/types.js +4 -0
- package/dist/client/types.js.map +1 -1
- package/dist/client/view.d.ts +71 -4
- package/dist/client/view.d.ts.map +1 -1
- package/dist/client/view.js +165 -5
- package/dist/client/view.js.map +1 -1
- package/dist/core/api/channels.d.ts +7 -3
- package/dist/core/api/channels.d.ts.map +1 -1
- package/dist/core/api/channels.js +5 -3
- package/dist/core/api/channels.js.map +1 -1
- package/dist/core/api/clients.d.ts +38 -1
- package/dist/core/api/clients.d.ts.map +1 -1
- package/dist/core/api/clients.js +33 -2
- package/dist/core/api/clients.js.map +1 -1
- package/dist/core/api/command.d.ts +18 -1
- package/dist/core/api/command.d.ts.map +1 -1
- package/dist/core/api/command.js +7 -1
- package/dist/core/api/command.js.map +1 -1
- package/dist/core/api/group-rows.d.ts +12 -0
- package/dist/core/api/group-rows.d.ts.map +1 -0
- package/dist/core/api/group-rows.js +34 -0
- package/dist/core/api/group-rows.js.map +1 -0
- package/dist/core/api/groups.d.ts.map +1 -1
- package/dist/core/api/groups.js +2 -13
- package/dist/core/api/groups.js.map +1 -1
- package/dist/core/api/instance.d.ts +10 -2
- package/dist/core/api/instance.d.ts.map +1 -1
- package/dist/core/api/instance.js +6 -2
- package/dist/core/api/instance.js.map +1 -1
- package/dist/core/api/moderation.d.ts +7 -0
- package/dist/core/api/moderation.d.ts.map +1 -1
- package/dist/core/api/moderation.js +7 -0
- package/dist/core/api/moderation.js.map +1 -1
- package/dist/core/api/parse.d.ts.map +1 -1
- package/dist/core/api/parse.js +1 -0
- package/dist/core/api/parse.js.map +1 -1
- package/dist/core/api/server.d.ts +9 -0
- package/dist/core/api/server.d.ts.map +1 -1
- package/dist/core/api/server.js +5 -13
- package/dist/core/api/server.js.map +1 -1
- package/dist/core/command/responses.d.ts.map +1 -1
- package/dist/core/command/responses.js +1 -0
- package/dist/core/command/responses.js.map +1 -1
- package/dist/core/errorcode.d.ts +16 -0
- package/dist/core/errorcode.d.ts.map +1 -1
- package/dist/core/errorcode.js +16 -0
- package/dist/core/errorcode.js.map +1 -1
- package/dist/core/events.d.ts +67 -6
- package/dist/core/events.d.ts.map +1 -1
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/internal.d.ts +1 -0
- package/dist/core/internal.d.ts.map +1 -1
- package/dist/core/internal.js +1 -0
- package/dist/core/internal.js.map +1 -1
- package/dist/core/notification-name.d.ts +4 -0
- package/dist/core/notification-name.d.ts.map +1 -1
- package/dist/core/notification-name.js +4 -0
- package/dist/core/notification-name.js.map +1 -1
- package/dist/core/notifications.d.ts +6 -2
- package/dist/core/notifications.d.ts.map +1 -1
- package/dist/core/notifications.js +32 -1
- package/dist/core/notifications.js.map +1 -1
- package/dist/core/types.d.ts +7 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +16 -0
- package/dist/core/types.js.map +1 -1
- package/dist/query/client.d.ts +16 -7
- package/dist/query/client.d.ts.map +1 -1
- package/dist/query/client.js +55 -20
- package/dist/query/client.js.map +1 -1
- package/dist/query/errors.d.ts +21 -0
- package/dist/query/errors.d.ts.map +1 -1
- package/dist/query/errors.js +34 -0
- package/dist/query/errors.js.map +1 -1
- package/dist/query/index.d.ts +4 -3
- package/dist/query/index.d.ts.map +1 -1
- package/dist/query/index.js +3 -2
- package/dist/query/index.js.map +1 -1
- package/dist/query/options.d.ts +32 -19
- package/dist/query/options.d.ts.map +1 -1
- package/dist/query/options.js +21 -16
- package/dist/query/options.js.map +1 -1
- package/dist/query/ssh.d.ts +3 -1
- package/dist/query/ssh.d.ts.map +1 -1
- package/dist/query/ssh.js +4 -1
- package/dist/query/ssh.js.map +1 -1
- package/dist/query/stream.d.ts +16 -3
- package/dist/query/stream.d.ts.map +1 -1
- package/dist/query/stream.js +57 -6
- package/dist/query/stream.js.map +1 -1
- package/dist/query/tcp.js +1 -1
- package/dist/query/tcp.js.map +1 -1
- package/dist/query/transport.d.ts +39 -3
- package/dist/query/transport.d.ts.map +1 -1
- package/dist/query/web.d.ts +25 -7
- package/dist/query/web.d.ts.map +1 -1
- package/dist/query/web.js +40 -10
- package/dist/query/web.js.map +1 -1
- package/package.json +6 -5
- package/src/client/api/voice.ts +25 -1
- package/src/client/capabilities.ts +14 -11
- package/src/client/client.ts +128 -14
- package/src/client/crypto/crypt.ts +46 -9
- package/src/client/crypto/identity.ts +2 -2
- package/src/client/crypto/index.ts +1 -0
- package/src/client/errors.ts +31 -0
- package/src/client/handshake/crypt-handshake.ts +51 -16
- package/src/client/index.ts +4 -1
- package/src/client/trace.ts +7 -0
- package/src/client/transport/handler.ts +5 -0
- package/src/client/types.ts +25 -1
- package/src/client/view.ts +227 -8
- package/src/core/api/channels.ts +9 -3
- package/src/core/api/clients.ts +73 -2
- package/src/core/api/command.ts +22 -1
- package/src/core/api/group-rows.ts +38 -0
- package/src/core/api/groups.ts +1 -14
- package/src/core/api/instance.ts +20 -2
- package/src/core/api/moderation.ts +7 -0
- package/src/core/api/parse.ts +1 -0
- package/src/core/api/server.ts +13 -15
- package/src/core/command/responses.ts +1 -0
- package/src/core/errorcode.ts +16 -0
- package/src/core/events.ts +68 -6
- package/src/core/index.ts +2 -1
- package/src/core/internal.ts +1 -0
- package/src/core/notification-name.ts +4 -0
- package/src/core/notifications.ts +48 -17
- package/src/core/types.ts +14 -0
- package/src/query/client.ts +63 -20
- package/src/query/errors.ts +37 -0
- package/src/query/index.ts +9 -3
- package/src/query/options.ts +53 -33
- package/src/query/ssh.ts +9 -2
- package/src/query/stream.ts +65 -7
- package/src/query/tcp.ts +1 -1
- package/src/query/testing/live.ts +311 -0
- package/src/query/testing/ssh-keys.ts +67 -0
- package/src/query/transport.ts +40 -3
- package/src/query/web.ts +65 -16
package/README.md
CHANGED
|
@@ -537,11 +537,53 @@ the way the voice protocol cannot: the same typed commands the core exports,
|
|
|
537
537
|
plus the ones only an administrator may run, over the three transports a
|
|
538
538
|
ServerQuery speaks.
|
|
539
539
|
|
|
540
|
-
| Transport | Where
|
|
541
|
-
| --------- |
|
|
542
|
-
| `tcp` | 10011
|
|
543
|
-
| `ssh` | 10022
|
|
544
|
-
| `web` | 10080 (HTTP)
|
|
540
|
+
| Transport | Where | Server | Login | Notifications |
|
|
541
|
+
| --------- | --------------------------- | ---------------- | ----------------- | ------------- |
|
|
542
|
+
| `tcp` | 10011 | TeamSpeak 3 only | `transport.login` | yes |
|
|
543
|
+
| `ssh` | 10022 | both | the SSH login | yes |
|
|
544
|
+
| `web` | 10080 (HTTP), 10443 (HTTPS) | both | the api key | **no** |
|
|
545
|
+
|
|
546
|
+
TeamSpeak 3 (3.12 and later for WebQuery, 3.3 and later for SSH) serves SSH and
|
|
547
|
+
WebQuery as well as raw TCP, but only the raw port is on until
|
|
548
|
+
`query_protocols` lists the others; the official Docker image takes it as
|
|
549
|
+
`TS3SERVER_QUERY_PROTOCOLS=raw,ssh,http`. TeamSpeak 6 has no raw port. Its
|
|
550
|
+
WebQuery also answers a request with no api key as a guest; TeamSpeak 3 refuses
|
|
551
|
+
one.
|
|
552
|
+
|
|
553
|
+
WebQuery is reached over `http:` or `https:`, by the scheme of `url`. TeamSpeak 3
|
|
554
|
+
serves HTTPS on 10443 once `query_protocols` lists `https` and
|
|
555
|
+
`query_https_certificate_file` and `query_https_private_key_file` are set. The
|
|
556
|
+
built-in `fetch` verifies the certificate against the trust store Node uses and
|
|
557
|
+
never skips that. A certificate from a private CA, or a self-signed one, is
|
|
558
|
+
trusted by starting Node with `NODE_EXTRA_CA_CERTS=ca.pem`, or by a `fetch`
|
|
559
|
+
that trusts the CA:
|
|
560
|
+
|
|
561
|
+
```typescript
|
|
562
|
+
import { readFileSync } from "node:fs";
|
|
563
|
+
import { Agent, request } from "node:https";
|
|
564
|
+
|
|
565
|
+
const agent = new Agent({ ca: readFileSync("ca.pem") });
|
|
566
|
+
const trusting = ((url: string, init: RequestInit) =>
|
|
567
|
+
new Promise<Response>((resolve, reject) => {
|
|
568
|
+
const req = request(
|
|
569
|
+
url,
|
|
570
|
+
{ method: init.method, headers: init.headers as never, agent },
|
|
571
|
+
(res) => {
|
|
572
|
+
const chunks: Buffer[] = [];
|
|
573
|
+
res.on("data", (chunk: Buffer) => chunks.push(chunk));
|
|
574
|
+
res.on("end", () =>
|
|
575
|
+
resolve(new Response(Buffer.concat(chunks), { status: res.statusCode })),
|
|
576
|
+
);
|
|
577
|
+
},
|
|
578
|
+
);
|
|
579
|
+
req.on("error", reject);
|
|
580
|
+
req.end(init.body as string);
|
|
581
|
+
})) as typeof fetch;
|
|
582
|
+
|
|
583
|
+
new QueryClient({
|
|
584
|
+
transport: { kind: "web", url: "https://ts.example.com:10443", apiKey, fetch: trusting },
|
|
585
|
+
});
|
|
586
|
+
```
|
|
545
587
|
|
|
546
588
|
Only raw TCP and SSH carry notifications: the server pushes them down the same
|
|
547
589
|
connection. WebQuery has no session to push to and refuses to register, so the
|
|
@@ -554,8 +596,11 @@ import { QueryClient } from "@honeybbq/teamspeak/query";
|
|
|
554
596
|
import { listChannels } from "@honeybbq/teamspeak";
|
|
555
597
|
|
|
556
598
|
const client = new QueryClient({
|
|
557
|
-
transport: {
|
|
558
|
-
|
|
599
|
+
transport: {
|
|
600
|
+
kind: "tcp", // 10011
|
|
601
|
+
host: "ts.example.com",
|
|
602
|
+
login: { name: "serveradmin", password: process.env.QUERY_PASSWORD! },
|
|
603
|
+
},
|
|
559
604
|
server: { id: 1 },
|
|
560
605
|
nickname: "bot",
|
|
561
606
|
events: { categories: ["textserver", "textprivate"] },
|
|
@@ -14,6 +14,19 @@ import type { ChannelID, ClientID, CommandOptions } from "@honeybbq/teamspeak";
|
|
|
14
14
|
* a `channelEdited` event, since it is no edit.
|
|
15
15
|
*/
|
|
16
16
|
export declare function getChannelDescription(client: Client, cid: ChannelID, options?: CommandOptions): Promise<string>;
|
|
17
|
+
/**
|
|
18
|
+
* The virtual server's properties as the server sends them on request, which
|
|
19
|
+
* is a different set from `getServerInfo`'s: it has the settings, limits and
|
|
20
|
+
* counters (clients online, uptime, traffic) and lacks the identity ones such as
|
|
21
|
+
* the unique identifier. It is the whole row, counters included.
|
|
22
|
+
*
|
|
23
|
+
* The client's `view.server` takes every answer in, whoever asked, less the
|
|
24
|
+
* counters, so this is also how to bring it up to date after an edit the
|
|
25
|
+
* server did not spell out. The answer goes to the asker alone.
|
|
26
|
+
*
|
|
27
|
+
* @experimental New in 1.x and may change in a minor release.
|
|
28
|
+
*/
|
|
29
|
+
export declare function getServerVariables(client: Client, options?: CommandOptions): Promise<Readonly<Record<string, string>>>;
|
|
17
30
|
/**
|
|
18
31
|
* Subscribe to a channel: receive its clients' events and voice without
|
|
19
32
|
* joining it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"voice.d.ts","sourceRoot":"","sources":["../../../src/client/api/voice.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE/E;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,SAAS,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,MAAM,CAAC,CAUjB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,SAAS,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,8DAA8D;AAC9D,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,SAAS,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,gDAAgD;AAChD,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,oDAAoD;AACpD,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC,CAEf;AAaD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,OAAO,CAAC,CAalB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,SAAS,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,OAAO,CAAC,CAgBlB;AAaD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,QAAQ,EAAE,EAC9B,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,QAAQ,EAAE,EAC9B,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC,CAEf"}
|
|
1
|
+
{"version":3,"file":"voice.d.ts","sourceRoot":"","sources":["../../../src/client/api/voice.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE/E;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,SAAS,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,MAAM,CAAC,CAUjB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAO3C;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,SAAS,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,8DAA8D;AAC9D,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,SAAS,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,gDAAgD;AAChD,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,oDAAoD;AACpD,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC,CAEf;AAaD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,OAAO,CAAC,CAalB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,SAAS,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,OAAO,CAAC,CAgBlB;AAaD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,QAAQ,EAAE,EAC9B,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,QAAQ,EAAE,EAC9B,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,IAAI,CAAC,CAEf"}
|
package/dist/client/api/voice.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* `channelinfo` already carries the description. These run on the voice
|
|
7
7
|
* client alone, which is why they take one rather than any CommandExecutor.
|
|
8
8
|
*/
|
|
9
|
-
import { ErrorCode, ServerError } from "@honeybbq/teamspeak";
|
|
9
|
+
import { ErrorCode, NoDataError, ServerError } from "@honeybbq/teamspeak";
|
|
10
10
|
/**
|
|
11
11
|
* The channel's description, which `listChannels` omits for bandwidth. The
|
|
12
12
|
* server answers with a `notifychanneledited` that the client does not report as
|
|
@@ -20,6 +20,25 @@ export async function getChannelDescription(client, cid, options) {
|
|
|
20
20
|
const answer = rows.find((row) => row["cid"] === String(cid) && "channel_description" in row);
|
|
21
21
|
return answer?.["channel_description"] ?? "";
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* The virtual server's properties as the server sends them on request, which
|
|
25
|
+
* is a different set from `getServerInfo`'s: it has the settings, limits and
|
|
26
|
+
* counters (clients online, uptime, traffic) and lacks the identity ones such as
|
|
27
|
+
* the unique identifier. It is the whole row, counters included.
|
|
28
|
+
*
|
|
29
|
+
* The client's `view.server` takes every answer in, whoever asked, less the
|
|
30
|
+
* counters, so this is also how to bring it up to date after an edit the
|
|
31
|
+
* server did not spell out. The answer goes to the asker alone.
|
|
32
|
+
*
|
|
33
|
+
* @experimental New in 1.x and may change in a minor release.
|
|
34
|
+
*/
|
|
35
|
+
export async function getServerVariables(client, options) {
|
|
36
|
+
const rows = await client.send({ command: "servergetvariables" }, options);
|
|
37
|
+
const answer = rows.find((row) => Object.keys(row).some((key) => key.startsWith("virtualserver_")));
|
|
38
|
+
if (answer === undefined)
|
|
39
|
+
throw new NoDataError("servergetvariables");
|
|
40
|
+
return answer;
|
|
41
|
+
}
|
|
23
42
|
/**
|
|
24
43
|
* Subscribe to a channel: receive its clients' events and voice without
|
|
25
44
|
* joining it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"voice.js","sourceRoot":"","sources":["../../../src/client/api/voice.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"voice.js","sourceRoot":"","sources":["../../../src/client/api/voice.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAG1E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAAc,EACd,GAAc,EACd,OAAwB;IAExB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAC5B,EAAE,OAAO,EAAE,uBAAuB,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,EAC5D,OAAO,CACR,CAAC;IACF,2EAA2E;IAC3E,yEAAyE;IACzE,4CAA4C;IAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,qBAAqB,IAAI,GAAG,CAAC,CAAC;IAC9F,OAAO,MAAM,EAAE,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC;AAC/C,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAAc,EACd,OAAwB;IAExB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,EAAE,OAAO,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAC/B,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,CACjE,CAAC;IACF,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,IAAI,WAAW,CAAC,oBAAoB,CAAC,CAAC;IACtE,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAc,EACd,GAAc,EACd,OAAwB;IAExB,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AACtF,CAAC;AAED,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAAc,EACd,GAAc,EACd,OAAwB;IAExB,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AACxF,CAAC;AAED,gDAAgD;AAChD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAc,EACd,OAAwB;IAExB,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,qBAAqB,EAAE,EAAE,OAAO,CAAC,CAAC;AACjE,CAAC;AAED,oDAAoD;AACpD,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,MAAc,EACd,OAAwB;IAExB,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,uBAAuB,EAAE,EAAE,OAAO,CAAC,CAAC;AACnE,CAAC;AAED,0GAA0G;AAC1G,KAAK,UAAU,eAAe,CAAC,GAA2B,EAAE,QAAgB;IAC1E,IAAI,CAAC;QACH,MAAM,GAAG,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QAC1E,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAc,EACd,QAAgB,EAChB,OAAwB;IAExB,OAAO,eAAe,CACpB,GAAG,EAAE,CACH,MAAM,CAAC,IAAI,CACT;QACE,OAAO,EAAE,sBAAsB;QAC/B,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAChC,SAAS,EAAE,CAAC,UAAU,CAAC;KACxB,EACD,OAAO,CACR,EACH,SAAS,CAAC,qBAAqB,CAChC,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAc,EACd,GAAc,EACd,QAAgB,EAChB,OAAwB;IAExB,OAAO,eAAe,CACpB,GAAG,EAAE,CACH,MAAM,CAAC,IAAI,CACT;QACE,OAAO,EAAE,uBAAuB;QAChC,MAAM,EAAE;YACN,CAAC,KAAK,EAAE,GAAG,CAAC;YACZ,CAAC,UAAU,EAAE,QAAQ,CAAC;SACvB;QACD,SAAS,EAAE,CAAC,UAAU,CAAC;KACxB,EACD,OAAO,CACR,EACH,SAAS,CAAC,sBAAsB,CACjC,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,KAAK,UAAU,QAAQ,CACrB,MAAc,EACd,OAAsC,EACtC,SAA8B,EAC9B,OAAwB;IAExB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IACnC,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;AAC3F,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CACzB,MAAc,EACd,SAA8B,EAC9B,OAAwB;IAExB,OAAO,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAC5D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAc,EACd,SAA8B,EAC9B,OAAwB;IAExB,OAAO,QAAQ,CAAC,MAAM,EAAE,cAAc,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAC9D,CAAC"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* its name, icon, banner and welcome message — so reading it costs no extra
|
|
12
12
|
* round trip.
|
|
13
13
|
*/
|
|
14
|
-
import { type IconID, type ServerFamily, type ServerID } from "@honeybbq/teamspeak";
|
|
14
|
+
import { HostMessageMode, type IconID, type ServerFamily, type ServerID } from "@honeybbq/teamspeak";
|
|
15
15
|
import { type UIDAlgorithm } from "./crypto/identity.js";
|
|
16
16
|
/** What a server said about itself in the handshake. */
|
|
17
17
|
export interface ServerCapabilities {
|
|
@@ -48,10 +48,10 @@ export interface ServerCapabilities {
|
|
|
48
48
|
readonly hostMessage: string;
|
|
49
49
|
/**
|
|
50
50
|
* How the host message is to be shown (`virtualserver_hostmessage_mode`).
|
|
51
|
-
*
|
|
52
|
-
*
|
|
51
|
+
* A value the `HostMessageMode` table does not name is passed through as the
|
|
52
|
+
* server sent it.
|
|
53
53
|
*/
|
|
54
|
-
readonly hostMessageMode:
|
|
54
|
+
readonly hostMessageMode: HostMessageMode;
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
57
57
|
* Read what a server says about itself in `initserver`, or a version string
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../src/client/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../src/client/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAEL,eAAe,EAEf,KAAK,MAAM,EACX,KAAK,YAAY,EACjB,KAAK,QAAQ,EACd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEjF,wDAAwD;AACxD,MAAM,WAAW,kBAAkB;IACjC,yEAAyE;IACzE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC;IACpC,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,uFAAuF;IACvF,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC;IAChD,gFAAgF;IAChF,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,uFAAuF;IACvF,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,uGAAuG;IACvG,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,2FAA2F;IAC3F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;CAC3C;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GACpD,kBAAkB,CAqBpB;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,IAAI,kBAAkB,CAE9D"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* its name, icon, banner and welcome message — so reading it costs no extra
|
|
12
12
|
* round trip.
|
|
13
13
|
*/
|
|
14
|
-
import { asServerID } from "@honeybbq/teamspeak";
|
|
14
|
+
import { asServerID, HostMessageMode, serverFamilyForVersion, } from "@honeybbq/teamspeak";
|
|
15
15
|
import { parseIconID, parseUint64 } from "../core/internal.js";
|
|
16
16
|
import { uidAlgorithmForVersion } from "./crypto/identity.js";
|
|
17
17
|
/**
|
|
@@ -23,15 +23,10 @@ export function parseServerCapabilities(initserver) {
|
|
|
23
23
|
const version = params["virtualserver_version"] ?? "";
|
|
24
24
|
const parsed = Number.parseInt(version, 10);
|
|
25
25
|
const major = Number.isNaN(parsed) ? 0 : parsed;
|
|
26
|
-
let family = "unknown";
|
|
27
|
-
if (major === 3)
|
|
28
|
-
family = "ts3";
|
|
29
|
-
else if (major >= 6)
|
|
30
|
-
family = "ts6";
|
|
31
26
|
return {
|
|
32
27
|
version,
|
|
33
28
|
major,
|
|
34
|
-
family,
|
|
29
|
+
family: serverFamilyForVersion(version),
|
|
35
30
|
uidAlgorithm: uidAlgorithmForVersion(version),
|
|
36
31
|
name: params["virtualserver_name"] ?? "",
|
|
37
32
|
iconID: parseIconID(params["virtualserver_icon_id"]),
|
|
@@ -54,6 +49,6 @@ export function unknownServerCapabilities() {
|
|
|
54
49
|
}
|
|
55
50
|
function hostMessageMode(value) {
|
|
56
51
|
const parsed = Number.parseInt(value ?? "", 10);
|
|
57
|
-
return Number.isNaN(parsed) ?
|
|
52
|
+
return (Number.isNaN(parsed) ? HostMessageMode.None : parsed);
|
|
58
53
|
}
|
|
59
54
|
//# sourceMappingURL=capabilities.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/client/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/client/capabilities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EACL,UAAU,EACV,eAAe,EACf,sBAAsB,GAIvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAqB,MAAM,sBAAsB,CAAC;AA2CjF;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACrC,UAAqD;IAErD,MAAM,MAAM,GACV,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,qBAAqB,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC;IACtF,MAAM,OAAO,GAAG,MAAM,CAAC,uBAAuB,CAAC,IAAI,EAAE,CAAC;IACtD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAEhD,OAAO;QACL,OAAO;QACP,KAAK;QACL,MAAM,EAAE,sBAAsB,CAAC,OAAO,CAAC;QACvC,YAAY,EAAE,sBAAsB,CAAC,OAAO,CAAC;QAC7C,IAAI,EAAE,MAAM,CAAC,oBAAoB,CAAC,IAAI,EAAE;QACxC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC;QACpD,kBAAkB,EAAE,MAAM,CAAC,kCAAkC,CAAC,EAAE,IAAI,EAAE,IAAI,SAAS;QACnF,cAAc,EAAE,MAAM,CAAC,8BAA8B,CAAC,IAAI,EAAE;QAC5D,QAAQ,EAAE,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC;QACnE,SAAS,EAAE,MAAM,CAAC,iCAAiC,CAAC,IAAI,EAAE;QAC1D,WAAW,EAAE,MAAM,CAAC,2BAA2B,CAAC,IAAI,EAAE;QACtD,eAAe,EAAE,eAAe,CAAC,MAAM,CAAC,gCAAgC,CAAC,CAAC;KAC3E,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB;IACvC,OAAO,uBAAuB,CAAC,EAAE,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,eAAe,CAAC,KAAyB;IAChD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAChD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAoB,CAAC;AACnF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAOnB,MAAM,YAAY,CAAC;AAIpB,OAAO,EACL,KAAK,SAAS,EAEd,KAAK,QAAQ,EACb,KAAK,KAAK,EAGV,KAAK,cAAc,EACnB,KAAK,GAAG,EAGR,KAAK,QAAQ,EAGb,KAAK,WAAW,EAGhB,YAAY,EAKb,MAAM,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAclD,OAAO,EAAoC,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAW3F,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client/client.js
CHANGED
|
@@ -17,7 +17,7 @@ import { buildEventChain } from "./events.js";
|
|
|
17
17
|
import { processInit1 } from "./handshake/crypt-handshake.js";
|
|
18
18
|
import { handleHandshakeInitIV, handleHandshakeExpand2, defaultClientVersion, handleInitServer, prepareClientPassword, } from "./handshake.js";
|
|
19
19
|
import { handleNotification } from "../core/internal.js";
|
|
20
|
-
import { parseChannel, parseCommand } from "../core/internal.js";
|
|
20
|
+
import { parseChannel, parseChannelGroup, parseCommand, parseServerGroup, parseUint16, } from "../core/internal.js";
|
|
21
21
|
import { CommandThrottle } from "./throttle.js";
|
|
22
22
|
import { splitCommandRows, sleep } from "../core/internal.js";
|
|
23
23
|
import { isAutoNicknameMatch } from "./helpers.js";
|
|
@@ -83,6 +83,24 @@ const DEFAULT_COMMAND_TIMEOUT_MS = 10_000;
|
|
|
83
83
|
const DISCONNECT_TIMEOUT_MS = 1_000;
|
|
84
84
|
/** How long each reconnection attempt may take. */
|
|
85
85
|
const RECONNECT_ATTEMPT_TIMEOUT_MS = 30_000;
|
|
86
|
+
/** What an attempt is waiting for now, for the report of an attempt that ended. */
|
|
87
|
+
function describeWaiting(trace, clientEkPending) {
|
|
88
|
+
if (trace.phase === ConnectPhase.Open) {
|
|
89
|
+
return trace.target === "" ? "the server address to resolve" : "the connection to open";
|
|
90
|
+
}
|
|
91
|
+
if (trace.phase === ConnectPhase.Join) {
|
|
92
|
+
return clientEkPending
|
|
93
|
+
? "the server's answer to clientek"
|
|
94
|
+
: "the server's answer to clientinit";
|
|
95
|
+
}
|
|
96
|
+
if (trace.stage === "puzzleSolving")
|
|
97
|
+
return "the RSA puzzle to be solved";
|
|
98
|
+
if (trace.stage === "puzzleAnswered")
|
|
99
|
+
return "the server's answer to the RSA puzzle";
|
|
100
|
+
return trace.init1Step < 0
|
|
101
|
+
? "the server's first answer to init1"
|
|
102
|
+
: `the server's init1 step after step ${trace.init1Step}`;
|
|
103
|
+
}
|
|
86
104
|
/** The `initserver` parameters a trace never sees, because they could carry a secret. */
|
|
87
105
|
const SECRET_INITSERVER_PARAMS = new Set([
|
|
88
106
|
"client_server_password",
|
|
@@ -221,6 +239,8 @@ export class Client {
|
|
|
221
239
|
/** Deliveries waiting for their turn; see #emit. */
|
|
222
240
|
#queue = [];
|
|
223
241
|
#draining = false;
|
|
242
|
+
/** The group list rows of the command line being handled, by the name of the line. */
|
|
243
|
+
#groupLine;
|
|
224
244
|
#voiceDropped = 0;
|
|
225
245
|
#voiceDropWarnedAt = -Infinity;
|
|
226
246
|
#eventMiddlewares;
|
|
@@ -237,7 +257,7 @@ export class Client {
|
|
|
237
257
|
this.#fileTransferSocketFactory = options.fileTransferSocketFactory;
|
|
238
258
|
this.#reconnectOptions = options.reconnect;
|
|
239
259
|
this.#trace = options.trace === undefined ? undefined : { ...options.trace };
|
|
240
|
-
this.#viewStore = new ViewStore(this.#logger, () => this.#clid);
|
|
260
|
+
this.#viewStore = new ViewStore(this.#logger, () => this.#clid, () => this.#scheduleDrain());
|
|
241
261
|
this.#clients = this.#viewStore.roster;
|
|
242
262
|
this.#crypt = new Crypt(identity);
|
|
243
263
|
this.#handler = this.#newHandler();
|
|
@@ -362,16 +382,27 @@ export class Client {
|
|
|
362
382
|
sessionStarted: false,
|
|
363
383
|
welcomeDone: false,
|
|
364
384
|
channels: 0,
|
|
385
|
+
stage: "init1",
|
|
386
|
+
init1Step: -1,
|
|
365
387
|
};
|
|
366
388
|
attempt.trace = trace;
|
|
367
|
-
attempt.onFail = (error) =>
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
389
|
+
attempt.onFail = (error) => {
|
|
390
|
+
const waitingFor = describeWaiting(trace, this.#handler.clientEkPending);
|
|
391
|
+
this.#logger.info("connection attempt ended", {
|
|
392
|
+
phase: trace.phase,
|
|
393
|
+
waitingFor,
|
|
394
|
+
error: String(error),
|
|
395
|
+
});
|
|
396
|
+
this.#callHook(this.#trace?.attemptFailed, () => ({
|
|
397
|
+
attempt: trace.attempt,
|
|
398
|
+
reconnect: trace.reconnect,
|
|
399
|
+
phase: trace.phase,
|
|
400
|
+
error,
|
|
401
|
+
target: trace.target,
|
|
402
|
+
waitingFor,
|
|
403
|
+
durationMs: performance.now() - trace.startedAt,
|
|
404
|
+
}));
|
|
405
|
+
};
|
|
375
406
|
// The handshake may complete just as the signal fires, in which case
|
|
376
407
|
// #failConnection leaves the session alone and the caller gets the
|
|
377
408
|
// connection it made rather than one it would believe had failed.
|
|
@@ -1076,9 +1107,32 @@ export class Client {
|
|
|
1076
1107
|
if (pType === 8 /* Init1 */) {
|
|
1077
1108
|
if (this.#crypt.cryptoInitComplete)
|
|
1078
1109
|
return;
|
|
1079
|
-
const
|
|
1080
|
-
|
|
1081
|
-
|
|
1110
|
+
const signal = this.#attempt.signal;
|
|
1111
|
+
const handler = this.#handler;
|
|
1112
|
+
const trace = this.#attempt.trace;
|
|
1113
|
+
const step = p.data[0] ?? 0x7f;
|
|
1114
|
+
const response = processInit1(this.#crypt, p.data, signal);
|
|
1115
|
+
if (response instanceof Promise) {
|
|
1116
|
+
// The puzzle: solved in slices, so the loop keeps running meanwhile.
|
|
1117
|
+
if (trace !== undefined)
|
|
1118
|
+
trace.stage = "puzzleSolving";
|
|
1119
|
+
response.then((answer) => {
|
|
1120
|
+
if (answer && !signal.aborted) {
|
|
1121
|
+
handler.sendPacket(PacketType.Init1, answer, 0);
|
|
1122
|
+
if (trace !== undefined)
|
|
1123
|
+
trace.stage = "puzzleAnswered";
|
|
1124
|
+
}
|
|
1125
|
+
}, (error) => {
|
|
1126
|
+
// An attempt that ended did so for its own reason; the abandoned
|
|
1127
|
+
// solve has nothing more to report.
|
|
1128
|
+
if (!signal.aborted)
|
|
1129
|
+
this.#handleReceiveError(error);
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
else if (response) {
|
|
1133
|
+
handler.sendPacket(PacketType.Init1, response, 0);
|
|
1134
|
+
if (trace !== undefined)
|
|
1135
|
+
trace.init1Step = step === 0x7f ? -1 : step;
|
|
1082
1136
|
}
|
|
1083
1137
|
return;
|
|
1084
1138
|
}
|
|
@@ -1126,6 +1180,23 @@ export class Client {
|
|
|
1126
1180
|
for (const row of splitCommandRows(trimmed)) {
|
|
1127
1181
|
this.#handleCommandStr(row);
|
|
1128
1182
|
}
|
|
1183
|
+
this.#applyGroupLine();
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* A group list is a whole set, and the server sends it as one command line,
|
|
1188
|
+
* so it is applied once its last row has been handled.
|
|
1189
|
+
*/
|
|
1190
|
+
#applyGroupLine() {
|
|
1191
|
+
const line = this.#groupLine;
|
|
1192
|
+
if (line === undefined)
|
|
1193
|
+
return;
|
|
1194
|
+
this.#groupLine = undefined;
|
|
1195
|
+
if (line.name === "notifyservergrouplist") {
|
|
1196
|
+
this.#viewStore.setServerGroups(line.rows.map(parseServerGroup).filter((group) => group.id !== 0n));
|
|
1197
|
+
}
|
|
1198
|
+
else {
|
|
1199
|
+
this.#viewStore.setChannelGroups(line.rows.map(parseChannelGroup).filter((group) => group.id !== 0n));
|
|
1129
1200
|
}
|
|
1130
1201
|
}
|
|
1131
1202
|
#handleCommandStr(s) {
|
|
@@ -1194,8 +1265,21 @@ export class Client {
|
|
|
1194
1265
|
}
|
|
1195
1266
|
if (cmd.name === "notifyconnectioninforequest")
|
|
1196
1267
|
this.#answerConnectionInfoRequest();
|
|
1268
|
+
if (cmd.name === "notifyservergrouplist" || cmd.name === "notifychannelgrouplist") {
|
|
1269
|
+
if (this.#groupLine?.name !== cmd.name)
|
|
1270
|
+
this.#applyGroupLine();
|
|
1271
|
+
this.#groupLine ??= { name: cmd.name, rows: [] };
|
|
1272
|
+
this.#groupLine.rows.push(cmd.params);
|
|
1273
|
+
}
|
|
1274
|
+
else if (cmd.name === "notifyserverupdated") {
|
|
1275
|
+
this.#viewStore.mergeServer(cmd.params);
|
|
1276
|
+
}
|
|
1277
|
+
// The roster entry goes with the notification, so it is read first.
|
|
1278
|
+
const leaving = cmd.name === "notifyclientleftview"
|
|
1279
|
+
? this.#clients.get(parseUint16(cmd.params["clid"] ?? ""))
|
|
1280
|
+
: undefined;
|
|
1197
1281
|
const result = handleNotification(cmd, this.#clid, this.#clients);
|
|
1198
|
-
this.#processNotificationResult(result);
|
|
1282
|
+
this.#processNotificationResult(result, leaving);
|
|
1199
1283
|
if (this.#listeners.get("notification")?.length || this.#eventMiddlewares.length > 0) {
|
|
1200
1284
|
this.#emitServerEvent({
|
|
1201
1285
|
name: "notification",
|
|
@@ -1221,6 +1305,7 @@ export class Client {
|
|
|
1221
1305
|
// report a connection whose next command — clientinit with its password
|
|
1222
1306
|
// hashes among them — goes out under that dummy key.
|
|
1223
1307
|
if (this.#status === ClientStatus.Connecting && this.#crypt.cryptoInitComplete) {
|
|
1308
|
+
this.#viewStore.seedServer(cmd.params);
|
|
1224
1309
|
handleInitServer(this.#internals, cmd.params);
|
|
1225
1310
|
}
|
|
1226
1311
|
break;
|
|
@@ -1273,7 +1358,7 @@ export class Client {
|
|
|
1273
1358
|
});
|
|
1274
1359
|
}
|
|
1275
1360
|
}
|
|
1276
|
-
#processNotificationResult(result) {
|
|
1361
|
+
#processNotificationResult(result, leaving) {
|
|
1277
1362
|
switch (result.kind) {
|
|
1278
1363
|
case "clientEnter": {
|
|
1279
1364
|
const info = result.info;
|
|
@@ -1303,7 +1388,7 @@ export class Client {
|
|
|
1303
1388
|
break;
|
|
1304
1389
|
}
|
|
1305
1390
|
case "clientLeave": {
|
|
1306
|
-
const event = result.event;
|
|
1391
|
+
const event = leaving === undefined ? result.event : { ...result.event, previous: leaving };
|
|
1307
1392
|
this.#emitServerEvent({ name: "clientLeave", payload: event });
|
|
1308
1393
|
if (!result.isSelf)
|
|
1309
1394
|
break;
|
|
@@ -1353,10 +1438,15 @@ export class Client {
|
|
|
1353
1438
|
this.#viewStore.applyMoved(result.event);
|
|
1354
1439
|
this.#emitServerEvent({ name: "channelMoved", payload: result.event });
|
|
1355
1440
|
break;
|
|
1356
|
-
case "channelDeleted":
|
|
1441
|
+
case "channelDeleted": {
|
|
1442
|
+
const previous = this.#viewStore.channelBeforeDeletion(result.event.channelID);
|
|
1357
1443
|
this.#viewStore.applyDeleted(result.event);
|
|
1358
|
-
this.#emitServerEvent({
|
|
1444
|
+
this.#emitServerEvent({
|
|
1445
|
+
name: "channelDeleted",
|
|
1446
|
+
payload: previous === undefined ? result.event : { ...result.event, previous },
|
|
1447
|
+
});
|
|
1359
1448
|
break;
|
|
1449
|
+
}
|
|
1360
1450
|
case "channelDescriptionChanged":
|
|
1361
1451
|
this.#emitServerEvent({ name: "channelDescriptionChanged", payload: result.event });
|
|
1362
1452
|
break;
|
|
@@ -1364,6 +1454,7 @@ export class Client {
|
|
|
1364
1454
|
this.#emitServerEvent({ name: "channelPasswordChanged", payload: result.event });
|
|
1365
1455
|
break;
|
|
1366
1456
|
case "serverEdited":
|
|
1457
|
+
this.#viewStore.patchServer(result.event.changes);
|
|
1367
1458
|
this.#emitServerEvent({ name: "serverEdited", payload: result.event });
|
|
1368
1459
|
break;
|
|
1369
1460
|
case "channelSubscribed":
|
|
@@ -1380,6 +1471,9 @@ export class Client {
|
|
|
1380
1471
|
case "clientChatComposing":
|
|
1381
1472
|
this.#emitServerEvent({ name: "clientChatComposing", payload: result.event });
|
|
1382
1473
|
break;
|
|
1474
|
+
case "clientChatClosed":
|
|
1475
|
+
this.#emitServerEvent({ name: "clientChatClosed", payload: result.event });
|
|
1476
|
+
break;
|
|
1383
1477
|
case "poked":
|
|
1384
1478
|
this.#emitServerEvent({ name: "poked", payload: result.event });
|
|
1385
1479
|
break;
|
|
@@ -1468,6 +1562,9 @@ export class Client {
|
|
|
1468
1562
|
*/
|
|
1469
1563
|
#enqueue(delivery) {
|
|
1470
1564
|
this.#queue.push(delivery);
|
|
1565
|
+
this.#scheduleDrain();
|
|
1566
|
+
}
|
|
1567
|
+
#scheduleDrain() {
|
|
1471
1568
|
if (this.#draining)
|
|
1472
1569
|
return;
|
|
1473
1570
|
this.#draining = true;
|
|
@@ -1477,6 +1574,11 @@ export class Client {
|
|
|
1477
1574
|
try {
|
|
1478
1575
|
while (this.#queue.length > 0)
|
|
1479
1576
|
this.#queue.shift()();
|
|
1577
|
+
// Everything handled so far is delivered: say once that the view moved.
|
|
1578
|
+
// Listeners cannot change the view, so this is the last word of the run.
|
|
1579
|
+
const revision = this.#viewStore.announce();
|
|
1580
|
+
if (revision !== undefined)
|
|
1581
|
+
this.#deliver("viewChanged", { revision });
|
|
1480
1582
|
}
|
|
1481
1583
|
finally {
|
|
1482
1584
|
if (this.#queue.length > 0)
|