@honeybbq/teamspeak-client 1.0.0-beta.2 → 1.0.0-beta.4
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 +61 -8
- package/dist/capabilities.d.ts +13 -1
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/client.d.ts +17 -11
- package/dist/client.d.ts.map +1 -1
- package/dist/discovery/resolver.d.ts.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/handshake/crypt-handshake.d.ts +9 -1
- package/dist/handshake/crypt-handshake.d.ts.map +1 -1
- package/dist/handshake.d.ts.map +1 -1
- package/dist/hooks.d.ts +7 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +762 -185
- package/dist/index.js.map +1 -1
- package/dist/notifications.d.ts +1 -1
- package/dist/notifications.d.ts.map +1 -1
- package/dist/trace.d.ts +223 -0
- package/dist/trace.d.ts.map +1 -0
- package/dist/transfer.d.ts +80 -1
- package/dist/transfer.d.ts.map +1 -1
- package/dist/transport/handler.d.ts +2 -0
- package/dist/transport/handler.d.ts.map +1 -1
- package/dist/types.d.ts +17 -110
- package/dist/types.d.ts.map +1 -1
- package/package.json +11 -5
- package/src/capabilities.ts +23 -2
- package/src/client.ts +392 -54
- package/src/crypto/crypt.ts +5 -5
- package/src/discovery/resolver.ts +56 -3
- package/src/errors.ts +92 -11
- package/src/handshake/crypt-handshake.ts +26 -5
- package/src/handshake/crypt-init2.ts +5 -5
- package/src/handshake.ts +3 -1
- package/src/hooks.ts +30 -0
- package/src/index.ts +30 -10
- package/src/notifications.ts +1 -1
- package/src/throttle.ts +2 -2
- package/src/trace.ts +238 -0
- package/src/transfer.ts +334 -25
- package/src/transport/handler.ts +13 -9
- package/src/transport/packet.ts +1 -1
- package/src/types.ts +21 -123
package/dist/notifications.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Command } from "@honeybbq/teamspeak-core/internal";
|
|
2
|
-
import type { ClientEnterEvent, ClientLeaveEvent, ClientMovedEvent, TextMessageEvent, PokeEvent } from "
|
|
2
|
+
import type { ClientEnterEvent, ClientLeaveEvent, ClientMovedEvent, TextMessageEvent, PokeEvent } from "@honeybbq/teamspeak-core";
|
|
3
3
|
export type NotificationResult = {
|
|
4
4
|
kind: "clientEnter";
|
|
5
5
|
info: ClientEnterEvent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,SAAS,EACV,MAAM,
|
|
1
|
+
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,SAAS,EACV,MAAM,0BAA0B,CAAC;AASlC,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GACjE;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,GACvE;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAExB,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACtC,SAAS,EAAE,MAAM,GAChB,kBAAkB,CAepB"}
|
package/dist/trace.d.ts
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import type { ChannelID, ClientID } from "@honeybbq/teamspeak-core";
|
|
2
|
+
import type { ServerCapabilities } from "./capabilities.js";
|
|
3
|
+
import type { ResolvedAddr } from "./types.js";
|
|
4
|
+
/** The values of the table below, before freezing. */
|
|
5
|
+
declare const connectPhaseValues: {
|
|
6
|
+
/** Opening the socket, or the address was not usable once resolved. */
|
|
7
|
+
readonly Open: "open";
|
|
8
|
+
/** The handshake, from the first packet until the shared secret exists. */
|
|
9
|
+
readonly Handshake: "handshake";
|
|
10
|
+
/** After the handshake, waiting for the server to accept the client: a wrong password, a ban or an invalid nickname end here. */
|
|
11
|
+
readonly Join: "join";
|
|
12
|
+
};
|
|
13
|
+
/** Where a connection attempt can fail; see {@link AttemptFailedInfo}. */
|
|
14
|
+
export declare const ConnectPhase: typeof connectPhaseValues;
|
|
15
|
+
/**
|
|
16
|
+
* One of {@link ConnectPhase}. May gain members in a minor release: a
|
|
17
|
+
* `switch` over it needs a default case.
|
|
18
|
+
*/
|
|
19
|
+
export type ConnectPhase = (typeof ConnectPhase)[keyof typeof ConnectPhase];
|
|
20
|
+
/** What every milestone of one connection attempt says about the attempt. */
|
|
21
|
+
interface AttemptInfo {
|
|
22
|
+
/**
|
|
23
|
+
* The attempt's number, from 1. The attempt `connect()` starts is 1; a
|
|
24
|
+
* reconnection attempt carries the retry number the reconnect policy uses,
|
|
25
|
+
* the one `shouldRetry` and the backoff see.
|
|
26
|
+
*/
|
|
27
|
+
readonly attempt: number;
|
|
28
|
+
/** Whether the reconnect loop started this attempt rather than a call to `connect()`. */
|
|
29
|
+
readonly reconnect: boolean;
|
|
30
|
+
}
|
|
31
|
+
/** The address is about to be resolved. */
|
|
32
|
+
export interface ResolveStartInfo extends AttemptInfo {
|
|
33
|
+
/** The address as the client was given it. */
|
|
34
|
+
readonly addr: string;
|
|
35
|
+
}
|
|
36
|
+
/** The address has been resolved, or the lookup failed and the address is used as given. */
|
|
37
|
+
export interface ResolveDoneInfo extends AttemptInfo {
|
|
38
|
+
/** The address as the client was given it. */
|
|
39
|
+
readonly addr: string;
|
|
40
|
+
/** The `host:port` that will be dialled. */
|
|
41
|
+
readonly target: string;
|
|
42
|
+
/** What the resolver reports as the source of the answer dialled; may be empty. */
|
|
43
|
+
readonly source: string;
|
|
44
|
+
/** Every answer the resolver gave, in order; empty when the address is used as given. */
|
|
45
|
+
readonly candidates: readonly ResolvedAddr[];
|
|
46
|
+
/** Why the lookup failed, when the address is used as given; `undefined` otherwise. */
|
|
47
|
+
readonly error: unknown;
|
|
48
|
+
/** How long the resolution took, in milliseconds. */
|
|
49
|
+
readonly durationMs: number;
|
|
50
|
+
}
|
|
51
|
+
/** The socket is about to be opened. */
|
|
52
|
+
export interface ConnectStartInfo extends AttemptInfo {
|
|
53
|
+
/** The `host:port` being dialled. */
|
|
54
|
+
readonly target: string;
|
|
55
|
+
}
|
|
56
|
+
/** The socket is open; the first handshake packet has not been sent yet. */
|
|
57
|
+
export interface ConnectDoneInfo extends AttemptInfo {
|
|
58
|
+
/** The `host:port` being dialled. */
|
|
59
|
+
readonly target: string;
|
|
60
|
+
/** The local socket's `host:port`; empty when the socket does not say. */
|
|
61
|
+
readonly localAddr: string;
|
|
62
|
+
/** Milliseconds since `connectStart`. */
|
|
63
|
+
readonly durationMs: number;
|
|
64
|
+
}
|
|
65
|
+
/** The encrypted session exists; `clientinit` has not been sent yet. */
|
|
66
|
+
export interface HandshakeDoneInfo extends AttemptInfo {
|
|
67
|
+
/** Milliseconds since `connectStart`. */
|
|
68
|
+
readonly durationMs: number;
|
|
69
|
+
/** The level of the RSA puzzle the server demanded; 0 if it sent none. */
|
|
70
|
+
readonly puzzleLevel: number;
|
|
71
|
+
/** Milliseconds spent solving the puzzle. */
|
|
72
|
+
readonly puzzleDurationMs: number;
|
|
73
|
+
/**
|
|
74
|
+
* The packets sent again from `connectStart` to now, for want of an
|
|
75
|
+
* acknowledgement: the Init1 steps and the handshake's command packets.
|
|
76
|
+
*/
|
|
77
|
+
readonly resends: number;
|
|
78
|
+
/**
|
|
79
|
+
* The server's public key exactly as it sent it, base64, so that a caller can
|
|
80
|
+
* pin a server's identity.
|
|
81
|
+
*/
|
|
82
|
+
readonly serverPublicKey: string;
|
|
83
|
+
}
|
|
84
|
+
/** The server accepted the client, which is now connected. */
|
|
85
|
+
export interface SessionStartInfo extends AttemptInfo {
|
|
86
|
+
/** The client's ID on the server, the same as `client.clientID`. */
|
|
87
|
+
readonly clientID: ClientID;
|
|
88
|
+
/**
|
|
89
|
+
* The nickname the server accepted (`acn`), which differs from the one asked
|
|
90
|
+
* for when that was taken. The one asked for when the server did not say.
|
|
91
|
+
*/
|
|
92
|
+
readonly nickname: string;
|
|
93
|
+
/** The client's talk power (`client_talk_power`); 0 when the server did not say. */
|
|
94
|
+
readonly talkPower: number;
|
|
95
|
+
/**
|
|
96
|
+
* Every parameter of `initserver`, unescaped, except those that could carry a
|
|
97
|
+
* secret: `client_server_password`, `client_default_channel_password`,
|
|
98
|
+
* `client_default_token` and `client_key_offset`. Frozen.
|
|
99
|
+
*/
|
|
100
|
+
readonly initServer: Readonly<Record<string, string>>;
|
|
101
|
+
/** What the server said about itself in this handshake. */
|
|
102
|
+
readonly capabilities: ServerCapabilities;
|
|
103
|
+
/** Milliseconds since `connectStart`. */
|
|
104
|
+
readonly durationMs: number;
|
|
105
|
+
}
|
|
106
|
+
/** The server's welcome sequence ended: the channel list and the clients already there have arrived. */
|
|
107
|
+
export interface WelcomeDoneInfo extends AttemptInfo {
|
|
108
|
+
/**
|
|
109
|
+
* The channel the client is in at the end of the welcome: where it landed,
|
|
110
|
+
* which differs from the default channel asked for when that was refused.
|
|
111
|
+
*/
|
|
112
|
+
readonly channelID: ChannelID;
|
|
113
|
+
/** How many channel rows the welcome delivered. */
|
|
114
|
+
readonly channels: number;
|
|
115
|
+
/** How many clients are in view at the end of the welcome, this client included. */
|
|
116
|
+
readonly clients: number;
|
|
117
|
+
/** Milliseconds since `connectStart`. */
|
|
118
|
+
readonly durationMs: number;
|
|
119
|
+
}
|
|
120
|
+
/** An attempt ended without a session. */
|
|
121
|
+
export interface AttemptFailedInfo extends AttemptInfo {
|
|
122
|
+
/** Where the attempt failed. */
|
|
123
|
+
readonly phase: ConnectPhase;
|
|
124
|
+
/** Why: the error `connect()` rejects with, or the one that ended the reconnection attempt. */
|
|
125
|
+
readonly error: unknown;
|
|
126
|
+
/** The `host:port` being dialled; empty when the attempt failed before `resolveDone`. */
|
|
127
|
+
readonly target: string;
|
|
128
|
+
/** Milliseconds since `resolveStart`. */
|
|
129
|
+
readonly durationMs: number;
|
|
130
|
+
}
|
|
131
|
+
/** The reconnect loop will retry, after a wait. */
|
|
132
|
+
export interface ReconnectScheduledInfo {
|
|
133
|
+
/** The attempt that will follow, numbered as in {@link ResolveStartInfo.attempt}. */
|
|
134
|
+
readonly attempt: number;
|
|
135
|
+
/** How long the loop waits first, in milliseconds. */
|
|
136
|
+
readonly delayMs: number;
|
|
137
|
+
/** The error that ended the previous connection or attempt. */
|
|
138
|
+
readonly cause: unknown;
|
|
139
|
+
}
|
|
140
|
+
/** A connected session is about to be left with `disconnect()`. It has no fields yet. */
|
|
141
|
+
export interface DisconnectStartInfo {
|
|
142
|
+
}
|
|
143
|
+
/** The goodbye of `disconnect()` is over. */
|
|
144
|
+
export interface DisconnectDoneInfo {
|
|
145
|
+
/** Whether the server acknowledged the goodbye before the goodbye timeout. */
|
|
146
|
+
readonly acknowledged: boolean;
|
|
147
|
+
/** Milliseconds since `disconnectStart`. */
|
|
148
|
+
readonly durationMs: number;
|
|
149
|
+
}
|
|
150
|
+
/** A session that had a `sessionStart` has ended, however it ended. */
|
|
151
|
+
export interface SessionEndInfo {
|
|
152
|
+
/** The client's ID on the server during the session. */
|
|
153
|
+
readonly clientID: ClientID;
|
|
154
|
+
/**
|
|
155
|
+
* `undefined` after `disconnect()`, and otherwise the cause the
|
|
156
|
+
* `disconnected` event gets.
|
|
157
|
+
*/
|
|
158
|
+
readonly error: unknown;
|
|
159
|
+
/** Milliseconds since `sessionStart`. */
|
|
160
|
+
readonly durationMs: number;
|
|
161
|
+
/** The number of the attempt that started the session. */
|
|
162
|
+
readonly attempt: number;
|
|
163
|
+
/** Whether the reconnect loop started the attempt that started the session. */
|
|
164
|
+
readonly reconnect: boolean;
|
|
165
|
+
}
|
|
166
|
+
/** The reconnect loop ended without a session. */
|
|
167
|
+
export interface ReconnectStoppedInfo {
|
|
168
|
+
/** How many reconnection attempts the loop made. */
|
|
169
|
+
readonly attempts: number;
|
|
170
|
+
/**
|
|
171
|
+
* The error `shouldRetry` declined, or the last attempt's when the attempts
|
|
172
|
+
* ran out; `undefined` when `disconnect()` stopped the loop.
|
|
173
|
+
*/
|
|
174
|
+
readonly cause: unknown;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Hooks that observe a client for timing, metrics, logs or a progress
|
|
178
|
+
* display: the milestones of every connection attempt, the end of a session,
|
|
179
|
+
* and the reconnect loop. Every hook is optional.
|
|
180
|
+
*
|
|
181
|
+
* A hook is called synchronously, at the moment of the milestone, and the
|
|
182
|
+
* client waits for it to return: keep it quick, and hand slow work to your own
|
|
183
|
+
* task. What it returns is ignored, and a returned promise is never awaited. A
|
|
184
|
+
* hook that throws, or whose promise rejects, is reported the way a throwing
|
|
185
|
+
* event listener is, and the client carries on. A hook may read the
|
|
186
|
+
* client's state. It must not call `connect()` or `disconnect()`: to give up
|
|
187
|
+
* on an attempt, abort the signal passed to `connect()`, and to leave once
|
|
188
|
+
* connected, call `disconnect()` from a `connected` listener.
|
|
189
|
+
*
|
|
190
|
+
* Every attempt ends with exactly one of `sessionStart` and `attemptFailed`,
|
|
191
|
+
* and every session that started with exactly one `sessionEnd`. The hooks are
|
|
192
|
+
* read when the client is made, from a copy of this object.
|
|
193
|
+
*/
|
|
194
|
+
export interface ClientTrace {
|
|
195
|
+
/** Before the address is resolved. */
|
|
196
|
+
readonly resolveStart?: (info: ResolveStartInfo) => void;
|
|
197
|
+
/** After the address is resolved, also when it fell back to the address as given. */
|
|
198
|
+
readonly resolveDone?: (info: ResolveDoneInfo) => void;
|
|
199
|
+
/** Right before the socket is opened. */
|
|
200
|
+
readonly connectStart?: (info: ConnectStartInfo) => void;
|
|
201
|
+
/** Once the socket is open, before the first handshake packet is sent. */
|
|
202
|
+
readonly connectDone?: (info: ConnectDoneInfo) => void;
|
|
203
|
+
/** When the shared secret is derived, before `clientinit` is sent. */
|
|
204
|
+
readonly handshakeDone?: (info: HandshakeDoneInfo) => void;
|
|
205
|
+
/** When the server accepts the client: before `connect()` resolves and before `connected` is delivered. */
|
|
206
|
+
readonly sessionStart?: (info: SessionStartInfo) => void;
|
|
207
|
+
/** When the server's welcome sequence ends; at most once per attempt, and only after `sessionStart`. */
|
|
208
|
+
readonly welcomeDone?: (info: WelcomeDoneInfo) => void;
|
|
209
|
+
/** When an attempt ends without `sessionStart`, for any reason, an abort or `disconnect()` included. */
|
|
210
|
+
readonly attemptFailed?: (info: AttemptFailedInfo) => void;
|
|
211
|
+
/** When `disconnect()` begins saying goodbye to a connected session. */
|
|
212
|
+
readonly disconnectStart?: (info: DisconnectStartInfo) => void;
|
|
213
|
+
/** When that goodbye is over. */
|
|
214
|
+
readonly disconnectDone?: (info: DisconnectDoneInfo) => void;
|
|
215
|
+
/** When a session ends, however it ends; before `disconnected` is queued. */
|
|
216
|
+
readonly sessionEnd?: (info: SessionEndInfo) => void;
|
|
217
|
+
/** When the reconnect loop has decided to retry and is about to wait. */
|
|
218
|
+
readonly reconnectScheduled?: (info: ReconnectScheduledInfo) => void;
|
|
219
|
+
/** When the reconnect loop ends without a session. */
|
|
220
|
+
readonly reconnectStopped?: (info: ReconnectStoppedInfo) => void;
|
|
221
|
+
}
|
|
222
|
+
export {};
|
|
223
|
+
//# sourceMappingURL=trace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../src/trace.ts"],"names":[],"mappings":"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"}
|
package/dist/transfer.d.ts
CHANGED
|
@@ -5,10 +5,76 @@
|
|
|
5
5
|
* the bytes then go over a separate TCP connection to the server's file
|
|
6
6
|
* transfer port, opened with the key the negotiation returned.
|
|
7
7
|
*/
|
|
8
|
-
import type
|
|
8
|
+
import { type Duplex, type Readable, type Writable } from "node:stream";
|
|
9
9
|
import type { FileUploadInfo, FileDownloadInfo } from "@honeybbq/teamspeak-core";
|
|
10
10
|
import type { FileTransferSocketFactory } from "./types.js";
|
|
11
11
|
import { FileTransferError } from "./errors.js";
|
|
12
|
+
/** Where a failed transfer failed. */
|
|
13
|
+
export type FileTransferStage = "dial" | "transfer";
|
|
14
|
+
/** The file transfer port is about to be dialled. */
|
|
15
|
+
export interface FileTransferDialStartInfo {
|
|
16
|
+
/** The `host:port` being dialled. */
|
|
17
|
+
readonly addr: string;
|
|
18
|
+
}
|
|
19
|
+
/** The connection is open and the transfer key has been sent. */
|
|
20
|
+
export interface FileTransferDialDoneInfo {
|
|
21
|
+
/** The `host:port` dialled. */
|
|
22
|
+
readonly addr: string;
|
|
23
|
+
/** The local socket's `host:port`; empty when the socket does not say. */
|
|
24
|
+
readonly localAddr: string;
|
|
25
|
+
/** Milliseconds since `dialStart`. */
|
|
26
|
+
readonly durationMs: number;
|
|
27
|
+
}
|
|
28
|
+
/** Data has moved. */
|
|
29
|
+
export interface FileTransferProgressInfo {
|
|
30
|
+
/** The bytes moved so far. */
|
|
31
|
+
readonly bytes: number;
|
|
32
|
+
/** The size the negotiation gave; 0 when it is not known, as for an upload. */
|
|
33
|
+
readonly total: number;
|
|
34
|
+
}
|
|
35
|
+
/** The transfer succeeded. */
|
|
36
|
+
export interface FileTransferDoneInfo {
|
|
37
|
+
/** The bytes moved. */
|
|
38
|
+
readonly bytes: number;
|
|
39
|
+
/** Milliseconds since `dialStart`. */
|
|
40
|
+
readonly durationMs: number;
|
|
41
|
+
}
|
|
42
|
+
/** The transfer failed. */
|
|
43
|
+
export interface FileTransferFailedInfo {
|
|
44
|
+
/** Why: the error the transfer function rejects with. */
|
|
45
|
+
readonly error: unknown;
|
|
46
|
+
/** The bytes moved before it failed. */
|
|
47
|
+
readonly bytes: number;
|
|
48
|
+
/** Milliseconds since `dialStart`. */
|
|
49
|
+
readonly durationMs: number;
|
|
50
|
+
/** Whether the failure came while dialling or while the data moved. */
|
|
51
|
+
readonly stage: FileTransferStage;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Hooks that observe one file transfer. Every hook is optional, and none ever
|
|
55
|
+
* sees the transfer key.
|
|
56
|
+
*
|
|
57
|
+
* A hook runs synchronously on the task doing the transfer, and its return
|
|
58
|
+
* value is ignored: a returned promise is not awaited. A hook that throws, or
|
|
59
|
+
* whose promise rejects, is reported the way a throwing event listener is, and
|
|
60
|
+
* the transfer goes on. Keep hooks quick.
|
|
61
|
+
*
|
|
62
|
+
* A call of `uploadFileData` or `downloadFileData` ends with exactly one of
|
|
63
|
+
* `done` and `failed`; `dialFileTransfer` on its own reports `dialStart`, then
|
|
64
|
+
* `dialDone` or `failed` with the stage `"dial"`.
|
|
65
|
+
*/
|
|
66
|
+
export interface FileTransferTrace {
|
|
67
|
+
/** Before the file transfer port is dialled. */
|
|
68
|
+
readonly dialStart?: (info: FileTransferDialStartInfo) => void;
|
|
69
|
+
/** When the connection is open and the transfer key is sent. */
|
|
70
|
+
readonly dialDone?: (info: FileTransferDialDoneInfo) => void;
|
|
71
|
+
/** While data moves, at most once per 64 KiB, and once more at the end with the final count. */
|
|
72
|
+
readonly progress?: (info: FileTransferProgressInfo) => void;
|
|
73
|
+
/** When the transfer function is about to resolve. */
|
|
74
|
+
readonly done?: (info: FileTransferDoneInfo) => void;
|
|
75
|
+
/** When the transfer function is about to reject, a failed dial included. */
|
|
76
|
+
readonly failed?: (info: FileTransferFailedInfo) => void;
|
|
77
|
+
}
|
|
12
78
|
/** Options for a file transfer. */
|
|
13
79
|
export interface FileTransferOptions {
|
|
14
80
|
/** Abandons the transfer; it then rejects with the signal's reason. */
|
|
@@ -18,6 +84,19 @@ export interface FileTransferOptions {
|
|
|
18
84
|
* through a proxy or tunnel.
|
|
19
85
|
*/
|
|
20
86
|
readonly socketFactory?: FileTransferSocketFactory | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* Hooks called at each milestone of this transfer. The object is copied when
|
|
89
|
+
* the call starts. See {@link FileTransferTrace}.
|
|
90
|
+
*/
|
|
91
|
+
readonly trace?: FileTransferTrace | undefined;
|
|
92
|
+
/**
|
|
93
|
+
* The longest, in milliseconds, the transfer may go without moving a byte,
|
|
94
|
+
* the write of the transfer key included. When it passes, the transfer
|
|
95
|
+
* rejects with a {@link FileTransferError} whose `cause` is a `TimeoutError`
|
|
96
|
+
* and the connection is destroyed. `undefined` means the default, 30 000;
|
|
97
|
+
* `0` turns the limit off.
|
|
98
|
+
*/
|
|
99
|
+
readonly idleTimeoutMs?: number | undefined;
|
|
21
100
|
}
|
|
22
101
|
/**
|
|
23
102
|
* Open a connection to the file transfer port and send the transfer key.
|
package/dist/transfer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transfer.d.ts","sourceRoot":"","sources":["../src/transfer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"transfer.d.ts","sourceRoot":"","sources":["../src/transfer.ts"],"names":[],"mappings":"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"}
|
|
@@ -25,6 +25,8 @@ export declare class PacketHandler {
|
|
|
25
25
|
* ends the connection. Without an owner the error is logged.
|
|
26
26
|
*/
|
|
27
27
|
onReceiveError: ((error: unknown) => void) | null;
|
|
28
|
+
/** Called with the socket once it is open, before the handshake's first packet is sent. */
|
|
29
|
+
onOpen: ((socket: DatagramSocket) => void) | null;
|
|
28
30
|
constructor(crypt: Crypt, logger?: Logger, socketFactory?: SocketFactory);
|
|
29
31
|
setClientID(id: number): void;
|
|
30
32
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/transport/handler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,EACL,KAAK,MAAM,EACX,UAAU,EAMX,MAAM,aAAa,CAAC;AA4BrB;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAa,CAAC;AAE9C;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAgB,CAAC;AA4BhD,qBAAa,aAAa;;IACxB,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAC9C,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IACtD;;;;OAIG;IACH,cAAc,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IA0CzD,YAAY,KAAK,EAAE,KAAK,EAAE,MAAM,GAAE,MAAmB,EAAE,aAAa,CAAC,EAAE,aAAa,EAInF;IAED,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE5B;IAED;;;;;;;OAOG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/transport/handler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,EACL,KAAK,MAAM,EACX,UAAU,EAMX,MAAM,aAAa,CAAC;AA4BrB;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAa,CAAC;AAE9C;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAgB,CAAC;AA4BhD,qBAAa,aAAa;;IACxB,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAC9C,QAAQ,EAAE,CAAC,CAAC,GAAG,EAAE,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IACtD;;;;OAIG;IACH,cAAc,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IACzD,2FAA2F;IAC3F,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IA0CzD,YAAY,KAAK,EAAE,KAAK,EAAE,MAAM,GAAE,MAAmB,EAAE,aAAa,CAAC,EAAE,aAAa,EAInF;IAED,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAE5B;IAED;;;;;;;OAOG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAyD/D;IAOD,sGAAsG;IACtG,KAAK,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CA2ChC;IAED;;;;;;OAMG;IACH,oBAAoB,IAAI,IAAI,CAE3B;IAED,UAAU,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAOnE;IAED,eAAe,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CA6BrD;IAED,8EAA8E;IAC9E,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAwClF;IAED,4EAA4E;IAC5E,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,iDAAiD;IACjD,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,KAAK,IAAI,IAAI,CAmBZ;CAwfF"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,115 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ClientEnterEvent, ClientLeaveEvent, ClientMovedEvent, CommandMiddleware, KickedEvent, Logger, NotificationEvent, PokeEvent, TextMessageEvent, VoiceDataEvent } from "@honeybbq/teamspeak-core";
|
|
2
2
|
import type { Duplex } from "node:stream";
|
|
3
3
|
import type { ReconnectOptions } from "./reconnect.js";
|
|
4
|
-
|
|
5
|
-
export interface TextMessageEvent {
|
|
6
|
-
/** The sender's nickname. */
|
|
7
|
-
readonly invokerName: string;
|
|
8
|
-
/** The sender's unique identifier. */
|
|
9
|
-
readonly invokerUID: UID;
|
|
10
|
-
/** The message, unescaped. */
|
|
11
|
-
readonly message: string;
|
|
12
|
-
/** The sender's server groups, as this client last saw them. */
|
|
13
|
-
readonly invokerGroups: readonly ServerGroupID[];
|
|
14
|
-
/**
|
|
15
|
-
* Private, channel or server; compare it with `TextMessageTarget`. A plain
|
|
16
|
-
* number, since a server may send a mode that table does not name.
|
|
17
|
-
*/
|
|
18
|
-
readonly targetMode: number;
|
|
19
|
-
/**
|
|
20
|
-
* The client a private message was sent to. Channel and server messages
|
|
21
|
-
* carry no target, so it is 0 for them.
|
|
22
|
-
*/
|
|
23
|
-
readonly targetID: ClientID;
|
|
24
|
-
/** The sender. */
|
|
25
|
-
readonly invokerID: ClientID;
|
|
26
|
-
}
|
|
27
|
-
/** A client changing channel, of its own accord or moved by someone. */
|
|
28
|
-
export interface ClientMovedEvent {
|
|
29
|
-
/** Who moved the client; the client itself for a move of its own. */
|
|
30
|
-
readonly invokerName: string;
|
|
31
|
-
/** The mover's unique identifier. */
|
|
32
|
-
readonly invokerUID: UID;
|
|
33
|
-
/** The channel the client is now in. */
|
|
34
|
-
readonly targetChannelID: ChannelID;
|
|
35
|
-
/** Why the client moved; compare it with `Reason`. */
|
|
36
|
-
readonly reason: number;
|
|
37
|
-
/** The client that moved. */
|
|
38
|
-
readonly clientID: ClientID;
|
|
39
|
-
/** The mover. */
|
|
40
|
-
readonly invokerID: ClientID;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* A client going out of view: leaving the server, kicked or banned from it, or
|
|
44
|
-
* in a channel that stopped being subscribed.
|
|
45
|
-
*/
|
|
46
|
-
export interface ClientLeaveEvent {
|
|
47
|
-
/** The reason given for a kick or a ban, or the client's own parting message. */
|
|
48
|
-
readonly reasonMessage: string;
|
|
49
|
-
/** Why the client left; compare it with `Reason`. */
|
|
50
|
-
readonly reason: number;
|
|
51
|
-
/** The client that left. */
|
|
52
|
-
readonly clientID: ClientID;
|
|
53
|
-
/** Who kicked or banned the client; empty otherwise. */
|
|
54
|
-
readonly invokerName: string;
|
|
55
|
-
/** The kicker's unique identifier; empty unless kicked or banned. */
|
|
56
|
-
readonly invokerUID: UID;
|
|
57
|
-
/** The kicker; 0 unless kicked or banned. */
|
|
58
|
-
readonly invokerID: ClientID;
|
|
59
|
-
}
|
|
60
|
-
/** This client being kicked from its channel or the server. */
|
|
61
|
-
export interface KickedEvent {
|
|
62
|
-
/** The reason the invoker gave. */
|
|
63
|
-
readonly reasonMessage: string;
|
|
64
|
-
/** `Reason.KickChannel`, `Reason.KickServer` or `Reason.KickServerBan`. */
|
|
65
|
-
readonly reason: number;
|
|
66
|
-
/** Who kicked this client. */
|
|
67
|
-
readonly invokerName: string;
|
|
68
|
-
/** The kicker's unique identifier. */
|
|
69
|
-
readonly invokerUID: UID;
|
|
70
|
-
/** The kicker. */
|
|
71
|
-
readonly invokerID: ClientID;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* A client coming into view: the same record `listClients` returns, so one
|
|
75
|
-
* type describes a client however it was learned of; its own id is `id`, as
|
|
76
|
-
* in every record. The fields only `clientlist -times` reports are undefined
|
|
77
|
-
* here.
|
|
78
|
-
*/
|
|
79
|
-
export type ClientEnterEvent = ClientEntry;
|
|
80
|
-
/** This client being poked. */
|
|
81
|
-
export interface PokeEvent {
|
|
82
|
-
/** Who poked. */
|
|
83
|
-
readonly invokerName: string;
|
|
84
|
-
/** The poker's unique identifier. */
|
|
85
|
-
readonly invokerUID: UID;
|
|
86
|
-
/** The poker. */
|
|
87
|
-
readonly invokerID: ClientID;
|
|
88
|
-
/** The poke's message, unescaped. */
|
|
89
|
-
readonly message: string;
|
|
90
|
-
}
|
|
91
|
-
/** Audio from another client, in the channel or whispered. */
|
|
92
|
-
export interface VoiceDataEvent {
|
|
93
|
-
/** Who is speaking. */
|
|
94
|
-
readonly clientID: ClientID;
|
|
95
|
-
/**
|
|
96
|
-
* How the audio is encoded; compare it with `Codec`. A plain number, since a
|
|
97
|
-
* server may relay a codec that table does not name.
|
|
98
|
-
*/
|
|
99
|
-
readonly codec: number;
|
|
100
|
-
/** One encoded frame, copied: it stays valid after the listener returns. */
|
|
101
|
-
readonly data: Uint8Array;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* A notification from the server, as it arrived: the escape hatch for one the
|
|
105
|
-
* SDK does not model. Match its `name` against `NotificationName`.
|
|
106
|
-
*/
|
|
107
|
-
export interface NotificationEvent {
|
|
108
|
-
/** The notification's name, such as `notifyserveredited`; `NotificationName` lists the known ones. */
|
|
109
|
-
readonly name: NotificationName | (string & {});
|
|
110
|
-
/** Its parameters, unescaped. */
|
|
111
|
-
readonly params: Readonly<Record<string, string>>;
|
|
112
|
-
}
|
|
4
|
+
import type { ClientTrace } from "./trace.js";
|
|
113
5
|
/**
|
|
114
6
|
* The events `Client.on()` takes, and what each delivers. May gain events in a
|
|
115
7
|
* minor release; code that handles every event generically should expect
|
|
@@ -190,6 +82,14 @@ export interface DatagramSocket {
|
|
|
190
82
|
once(event: "error", listener: (error: Error) => void): unknown;
|
|
191
83
|
/** Stop listening for failures. */
|
|
192
84
|
off(event: "error", listener: (error: Error) => void): unknown;
|
|
85
|
+
/**
|
|
86
|
+
* The local end of the socket, for a trace to report. Optional: a socket that
|
|
87
|
+
* cannot say is reported with an empty local address.
|
|
88
|
+
*/
|
|
89
|
+
address?(): {
|
|
90
|
+
readonly address: string;
|
|
91
|
+
readonly port: number;
|
|
92
|
+
};
|
|
193
93
|
}
|
|
194
94
|
/** Creates the UDP socket the client talks through, for the given address family. */
|
|
195
95
|
export type SocketFactory = (family: 4 | 6) => DatagramSocket;
|
|
@@ -266,6 +166,13 @@ export interface ClientOptions {
|
|
|
266
166
|
* session. An explicit `disconnect()` never reconnects regardless.
|
|
267
167
|
*/
|
|
268
168
|
readonly reconnect?: ReconnectOptions | undefined;
|
|
169
|
+
/**
|
|
170
|
+
* Hooks called at each milestone of every connection attempt, for timing,
|
|
171
|
+
* metrics and progress. The object is copied when the client is made, so
|
|
172
|
+
* changing it afterwards has no effect. See {@link ClientTrace} for the
|
|
173
|
+
* rules a hook follows.
|
|
174
|
+
*/
|
|
175
|
+
readonly trace?: ClientTrace | undefined;
|
|
269
176
|
/**
|
|
270
177
|
* Creates the TCP socket a file transfer runs over.
|
|
271
178
|
*
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@honeybbq/teamspeak-client",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.4",
|
|
4
4
|
"description": "A clean-room TeamSpeak client for Node.js, speaking the voice protocol the way the TeamSpeak application does",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"client",
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
"ts6",
|
|
11
11
|
"voip"
|
|
12
12
|
],
|
|
13
|
+
"homepage": "https://github.com/HoneyBBQ/teamspeak-js/tree/main/packages/client#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/HoneyBBQ/teamspeak-js/issues"
|
|
16
|
+
},
|
|
13
17
|
"license": "MIT",
|
|
14
18
|
"author": "honeybbq",
|
|
15
19
|
"repository": {
|
|
@@ -30,17 +34,19 @@
|
|
|
30
34
|
".": {
|
|
31
35
|
"types": "./dist/index.d.ts",
|
|
32
36
|
"default": "./dist/index.js"
|
|
33
|
-
}
|
|
37
|
+
},
|
|
38
|
+
"./package.json": "./package.json"
|
|
34
39
|
},
|
|
35
40
|
"publishConfig": {
|
|
36
|
-
"access": "public"
|
|
41
|
+
"access": "public",
|
|
42
|
+
"provenance": true
|
|
37
43
|
},
|
|
38
44
|
"dependencies": {
|
|
39
45
|
"@noble/curves": "^2.0.1",
|
|
40
|
-
"@honeybbq/teamspeak-core": "1.0.0-beta.
|
|
46
|
+
"@honeybbq/teamspeak-core": "1.0.0-beta.4"
|
|
41
47
|
},
|
|
42
48
|
"engines": {
|
|
43
|
-
"node": ">=
|
|
49
|
+
"node": ">=22.12"
|
|
44
50
|
},
|
|
45
51
|
"scripts": {
|
|
46
52
|
"build": "vite build && tsc -p tsconfig.build.json",
|
package/src/capabilities.ts
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
* round trip.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import type
|
|
16
|
-
import { parseIconID } from "@honeybbq/teamspeak-core/internal";
|
|
15
|
+
import { asServerID, type IconID, type ServerID } from "@honeybbq/teamspeak-core";
|
|
16
|
+
import { parseIconID, parseUint64 } from "@honeybbq/teamspeak-core/internal";
|
|
17
17
|
import { uidAlgorithmForVersion, type UIDAlgorithm } from "./crypto/identity.js";
|
|
18
18
|
|
|
19
19
|
/**
|
|
@@ -50,6 +50,18 @@ export interface ServerCapabilities {
|
|
|
50
50
|
readonly hostBannerImageURL: string | undefined;
|
|
51
51
|
/** The welcome message shown on connecting (`virtualserver_welcomemessage`). */
|
|
52
52
|
readonly welcomeMessage: string;
|
|
53
|
+
/** The virtual server's ID (`virtualserver_id`); 0 when the server did not send it. */
|
|
54
|
+
readonly serverID: ServerID;
|
|
55
|
+
/** The virtual server's unique identifier (`virtualserver_unique_identifier`); empty when not sent. */
|
|
56
|
+
readonly serverUID: string;
|
|
57
|
+
/** The host message (`virtualserver_hostmessage`) the server wants shown on connecting. */
|
|
58
|
+
readonly hostMessage: string;
|
|
59
|
+
/**
|
|
60
|
+
* How the host message is to be shown (`virtualserver_hostmessage_mode`):
|
|
61
|
+
* 0 not at all, 1 in the chat log, 2 as a modal dialog, 3 as a modal dialog
|
|
62
|
+
* after which the client is disconnected.
|
|
63
|
+
*/
|
|
64
|
+
readonly hostMessageMode: number;
|
|
53
65
|
}
|
|
54
66
|
|
|
55
67
|
/**
|
|
@@ -78,6 +90,10 @@ export function parseServerCapabilities(
|
|
|
78
90
|
iconID: parseIconID(params["virtualserver_icon_id"]),
|
|
79
91
|
hostBannerImageURL: params["virtualserver_hostbanner_gfx_url"]?.trim() || undefined,
|
|
80
92
|
welcomeMessage: params["virtualserver_welcomemessage"] ?? "",
|
|
93
|
+
serverID: asServerID(parseUint64(params["virtualserver_id"] ?? "")),
|
|
94
|
+
serverUID: params["virtualserver_unique_identifier"] ?? "",
|
|
95
|
+
hostMessage: params["virtualserver_hostmessage"] ?? "",
|
|
96
|
+
hostMessageMode: hostMessageMode(params["virtualserver_hostmessage_mode"]),
|
|
81
97
|
};
|
|
82
98
|
}
|
|
83
99
|
|
|
@@ -90,3 +106,8 @@ export function parseServerCapabilities(
|
|
|
90
106
|
export function unknownServerCapabilities(): ServerCapabilities {
|
|
91
107
|
return parseServerCapabilities("");
|
|
92
108
|
}
|
|
109
|
+
|
|
110
|
+
function hostMessageMode(value: string | undefined): number {
|
|
111
|
+
const parsed = Number.parseInt(value ?? "", 10);
|
|
112
|
+
return Number.isNaN(parsed) ? 0 : parsed;
|
|
113
|
+
}
|