@honeybbq/teamspeak 1.0.0-beta.27 → 1.0.0-beta.29
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 +9 -8
- package/dist/client/api/files.d.ts +4 -0
- package/dist/client/api/files.d.ts.map +1 -1
- package/dist/client/api/files.js +4 -0
- package/dist/client/api/files.js.map +1 -1
- package/dist/client/api/s3-list.d.ts +12 -0
- package/dist/client/api/s3-list.d.ts.map +1 -0
- package/dist/client/api/s3-list.js +43 -0
- package/dist/client/api/s3-list.js.map +1 -0
- package/dist/client/api/s3.d.ts +239 -0
- package/dist/client/api/s3.d.ts.map +1 -0
- package/dist/client/api/s3.js +461 -0
- package/dist/client/api/s3.js.map +1 -0
- package/dist/client/capabilities.d.ts +3 -2
- package/dist/client/capabilities.d.ts.map +1 -1
- package/dist/client/capabilities.js.map +1 -1
- package/dist/client/commands.d.ts.map +1 -1
- package/dist/client/commands.js +3 -2
- package/dist/client/commands.js.map +1 -1
- package/dist/client/errors.d.ts +46 -0
- package/dist/client/errors.d.ts.map +1 -1
- package/dist/client/errors.js +73 -0
- package/dist/client/errors.js.map +1 -1
- package/dist/client/index.d.ts +4 -3
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +4 -3
- package/dist/client/index.js.map +1 -1
- package/dist/client/transfer.d.ts +13 -1
- package/dist/client/transfer.d.ts.map +1 -1
- package/dist/client/transfer.js +2 -2
- package/dist/client/transfer.js.map +1 -1
- package/dist/core/command/parser.d.ts +6 -4
- package/dist/core/command/parser.d.ts.map +1 -1
- package/dist/core/command/parser.js +10 -8
- package/dist/core/command/parser.js.map +1 -1
- package/dist/core/command/responses.d.ts +6 -0
- package/dist/core/command/responses.d.ts.map +1 -1
- package/dist/core/command/responses.js +17 -0
- package/dist/core/command/responses.js.map +1 -1
- package/dist/core/command-name.d.ts +8 -0
- package/dist/core/command-name.d.ts.map +1 -1
- package/dist/core/command-name.js +8 -0
- package/dist/core/command-name.js.map +1 -1
- package/dist/core/notification-name.d.ts +8 -0
- package/dist/core/notification-name.d.ts.map +1 -1
- package/dist/core/notification-name.js +8 -0
- package/dist/core/notification-name.js.map +1 -1
- package/dist/query/index.d.ts +1 -1
- package/dist/query/index.js +1 -1
- package/dist/stream/index.d.ts +3 -3
- package/dist/stream/index.js +3 -3
- package/package.json +13 -5
- package/src/client/api/files.ts +4 -0
- package/src/client/api/s3-list.ts +49 -0
- package/src/client/api/s3.ts +701 -0
- package/src/client/capabilities.ts +3 -2
- package/src/client/commands.ts +3 -1
- package/src/client/errors.ts +90 -0
- package/src/client/index.ts +5 -2
- package/src/client/transfer.ts +2 -2
- package/src/core/command/parser.ts +10 -8
- package/src/core/command/responses.ts +24 -0
- package/src/core/command-name.ts +8 -0
- package/src/core/notification-name.ts +8 -0
- package/src/query/index.ts +1 -1
- package/src/stream/index.ts +3 -3
package/README.md
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
</p>
|
|
9
9
|
|
|
10
10
|
<p align="center">
|
|
11
|
-
<strong>
|
|
12
|
-
|
|
11
|
+
<strong>A complete TeamSpeak client in pure TypeScript: voice, ServerQuery and screen share.</strong><br>
|
|
12
|
+
For TeamSpeak 3 and 6 servers. No native addons, no proprietary SDK.
|
|
13
13
|
</p>
|
|
14
14
|
|
|
15
15
|
<p align="center">
|
|
@@ -30,11 +30,11 @@
|
|
|
30
30
|
|
|
31
31
|
## Why this library
|
|
32
32
|
|
|
33
|
-
- **
|
|
34
|
-
- **ServerQuery
|
|
33
|
+
- **Voice, both ways.** Send and receive Opus voice (codecs 4 and 5), whisper to clients, channels or groups, and get each frame with its speaker and sequence number for your own jitter buffer. The whole voice protocol is here: ECDH key exchange, the RSA puzzle and EAX-encrypted transport, in TypeScript with no native addons.
|
|
34
|
+
- **ServerQuery.** The same typed commands run over raw TCP, SSH (with host-key verification) or WebQuery, so an administration script and a voice bot share one vocabulary.
|
|
35
|
+
- **TeamSpeak 6 screen share.** Find, publish and watch the streams of a TeamSpeak 6 server, interoperable with the TeamSpeak 6 client. SDP and ICE are plain strings for any WebRTC stack: a browser, Electron, or werift in Node.
|
|
35
36
|
- **Typed commands and events.** Every command the voice protocol answers is a typed function, and the server's notifications arrive as typed events with pluggable middleware.
|
|
36
|
-
- **File transfers.** Upload, download and delete files on the server, with avatars and icons covered.
|
|
37
|
-
- **TeamSpeak 6 screen-share signalling.** Find, publish and watch streams, with SDP and ICE as plain strings for any WebRTC stack.
|
|
37
|
+
- **File transfers.** Upload, download and delete files on the server, with avatars and icons covered, and the S3 file transfer of a TeamSpeak 6 server that keeps its files in an S3 bucket.
|
|
38
38
|
- **Built for long-running bots.** Opt-in reconnection tuned for TeamSpeak's antiflood ban, and a line middleware seam for pacing commands, with recipes for a token bucket, resending a refused command and keeping a query session open.
|
|
39
39
|
- **Identities and server facts.** Generate, import, export and upgrade identities; read the server version, its uid hash (SHA-1 on TS3, SHA-256 on TS6) and its name, icon and banner.
|
|
40
40
|
- **TeamSpeak 3 and 6, ESM with types.** Pure TypeScript, zero native dependencies, full declarations, and a custom-transport hook for proxies and tests.
|
|
@@ -84,14 +84,15 @@ process.on("SIGINT", () => void client.disconnect());
|
|
|
84
84
|
|
|
85
85
|
The full API reference is at [honeybbq.github.io/teamspeak-js](https://honeybbq.github.io/teamspeak-js/). The pages below are the long-form guides.
|
|
86
86
|
|
|
87
|
-
- [Guide](https://honeybbq.github.io/teamspeak-js/documents/guide.html): connecting, events, commands, file transfers and identities.
|
|
87
|
+
- [Guide](https://honeybbq.github.io/teamspeak-js/documents/guide.html): connecting, events, sending and receiving voice, commands, file transfers and identities.
|
|
88
88
|
- [Configuration](https://honeybbq.github.io/teamspeak-js/documents/configuration.html): options, client version, tracing, diagnostics, reconnection, custom transports and server capabilities.
|
|
89
|
-
- [Streams](https://honeybbq.github.io/teamspeak-js/documents/streams.html): TeamSpeak 6 screen
|
|
89
|
+
- [Streams](https://honeybbq.github.io/teamspeak-js/documents/streams.html): watching and publishing TeamSpeak 6 screen shares, running WebRTC in Node and Electron, and interop with the TeamSpeak 6 client.
|
|
90
90
|
- [ServerQuery](https://honeybbq.github.io/teamspeak-js/documents/serverquery.html): the query client and its SSH host-key policy.
|
|
91
91
|
- [Flood control](https://honeybbq.github.io/teamspeak-js/documents/flood-control.html): what the server counts, what each command costs, and line middleware recipes for pacing, resending and keeping a query session open.
|
|
92
92
|
- [Design](https://honeybbq.github.io/teamspeak-js/documents/design.html): errors, ids, absent values, events, stability, and the server behaviour the SDK works around.
|
|
93
93
|
- [Compatibility](https://honeybbq.github.io/teamspeak-js/documents/compatibility.html): supported environments and the differences from the Go SDK.
|
|
94
94
|
- [Architecture](https://honeybbq.github.io/teamspeak-js/documents/architecture.html): source layout and entry points.
|
|
95
|
+
- [Examples](https://github.com/HoneyBBQ/teamspeak-js/tree/main/examples): connecting, a voice echo bot, watching a screen share from Node, pacing commands, and ServerQuery events and keepalive.
|
|
95
96
|
- [Migrating to 1.0](https://honeybbq.github.io/teamspeak-js/documents/migrating-to-1.0.html), [voice protocol responses](https://honeybbq.github.io/teamspeak-js/documents/voice-protocol-responses.html) and [ServerQuery responses](https://honeybbq.github.io/teamspeak-js/documents/serverquery-responses.html): reference material.
|
|
96
97
|
|
|
97
98
|
## Compatibility
|
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
* beta13.1 (SSH, voice), the key a query connection negotiates opens the same
|
|
9
9
|
* file transfer port a voice client's does. WebQuery refuses every file command
|
|
10
10
|
* (error 5120), on both servers.
|
|
11
|
+
*
|
|
12
|
+
* A TeamSpeak 6 server whose extensions name `s3` keeps a separate store in an
|
|
13
|
+
* S3 bucket, which these do not reach: see `uploadS3File` and the rest of the
|
|
14
|
+
* S3 functions.
|
|
11
15
|
*/
|
|
12
16
|
import { Readable, Writable } from "node:stream";
|
|
13
17
|
import type { ChannelID, CommandExecutor, FileDownloadOptions, FileUploadOptions } from "@honeybbq/teamspeak";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../../src/client/api/files.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../../src/client/api/files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAa,QAAQ,EAAY,MAAM,aAAa,CAAC;AAEtE,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EAEf,mBAAmB,EAEnB,iBAAiB,EAClB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE1D;;;;GAIG;AACH,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB,EAAE,mBAAmB;IAC/E;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;CAC7C;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB,EAAE,mBAAmB;IACnF,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAqHD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,eAAe,EACvB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,GAAG,QAAQ,EAC3B,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAqBf;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,eAAe,EACvB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,mBAAmB,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GACzD,OAAO,CAAC,IAAI,CAAC,CAAC;AACjB,wBAAgB,YAAY,CAC1B,MAAM,EAAE,eAAe,EACvB,SAAS,EAAE,SAAS,EACpB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,UAAU,CAAC,CAAC"}
|
package/dist/client/api/files.js
CHANGED
|
@@ -8,6 +8,10 @@
|
|
|
8
8
|
* beta13.1 (SSH, voice), the key a query connection negotiates opens the same
|
|
9
9
|
* file transfer port a voice client's does. WebQuery refuses every file command
|
|
10
10
|
* (error 5120), on both servers.
|
|
11
|
+
*
|
|
12
|
+
* A TeamSpeak 6 server whose extensions name `s3` keeps a separate store in an
|
|
13
|
+
* S3 bucket, which these do not reach: see `uploadS3File` and the rest of the
|
|
14
|
+
* S3 functions.
|
|
11
15
|
*/
|
|
12
16
|
import { Readable, Transform, Writable, pipeline } from "node:stream";
|
|
13
17
|
import { initFileDownload, initFileUpload, stopFileTransfer } from "@honeybbq/teamspeak";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../../src/client/api/files.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../../src/client/api/files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AASzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AA+DnE,SAAS,iBAAiB,CAAC,MAAuB;IAChD,MAAM,SAAS,GAAG,MAAkC,CAAC;IACrD,OAAO,CACL,OAAO,SAAS,CAAC,IAAI,KAAK,QAAQ;QAClC,OAAO,SAAS,CAAC,cAAc,KAAK,UAAU;QAC9C,OAAO,SAAS,CAAC,gBAAgB,KAAK,UAAU,CACjD,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,QAAQ,CACf,MAAuB,EACvB,OAA4F;IAK5F,IAAI,iBAAiB,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QACtF,OAAO;YACL,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC5E,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;SACjF,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACnF,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,SAAS,CACjB,4FAA4F,CAC7F,CAAC;IACJ,CAAC;IACD,OAAO;QACL,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9D,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;KACnE,CAAC;AACJ,CAAC;AAED,6DAA6D;AAC7D,SAAS,eAAe,CAAC,OAA4B;IACnD,OAAO;QACL,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,aAAa,EAAE,OAAO,CAAC,aAAa;KACrC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,kBAAkB,GAAG,EAAE,GAAG,IAAI,CAAC;AAErC,mFAAmF;AACnF,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAgB;IACjC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,CAAC;IAClC,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,kBAAkB,EAAE,CAAC;QAC5D,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,GAAG,kBAAkB,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED,SAAS,MAAM,CAAC,IAA2B,EAAE,QAAqC;IAChF,MAAM,IAAI,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACnE,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7E,MAAM,IAAI,UAAU,CAAC,qDAAqD,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAChG,CAAC;IACD,IAAI,IAAI,YAAY,UAAU,EAAE,CAAC;QAC/B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,MAAM,IAAI,SAAS,CAAC,aAAa,IAAI,0BAA0B,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAChF,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7B,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,MAAM,IAAI,SAAS,CAAC,2DAA2D,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,iDAAiD;AACjD,SAAS,SAAS,CAAC,KAAa;IAC9B,IAAI,IAAI,GAAG,KAAK,CAAC;IACjB,OAAO,IAAI,SAAS,CAAC;QACnB,SAAS,CAAC,KAAa,EAAE,SAAS,EAAE,QAAQ;YAC1C,IAAI,IAAI,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACzB,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;gBACrB,QAAQ,EAAE,CAAC;gBACX,OAAO;YACT,CAAC;YACD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,GAAG,CAAC,CAAC;YACT,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACvB,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAAuB,EACvB,SAAoB,EACpB,IAAY,EACZ,IAA2B,EAC3B,OAAO,GAAsB,EAAE;IAE/B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE;QAC/D,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC,CAAC;IACH,0EAA0E;IAC1E,0BAA0B;IAC1B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACvC,IAAI,MAAgB,CAAC;IACrB,IAAI,IAAI,YAAY,UAAU;QAAE,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SACjF,IAAI,IAAI,KAAK,CAAC;QAAE,MAAM,GAAG,IAAI,CAAC;;QAC9B,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACxD,MAAM,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,GAAG,EAAE,CAC5D,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC,CACrD,CAAC;IACF,MAAM,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AAC7D,CAAC;AAkCD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAuB,EACvB,SAAoB,EACpB,IAAY,EACZ,OAAO,GAAwB,EAAE;IAEjC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAC;IACpD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,UAAU,CAAC,kDAAkD,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE;QAC3D,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC,CAAC;IACH,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QAC1B,MAAM,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,GAAG,EAAE,CAC5D,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC,CACrD,CAAC;QACF,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC;IAC7C,IAAI,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7B,0EAA0E;QAC1E,2EAA2E;QAC3E,0CAA0C;QAC1C,MAAM,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,oBAAoB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC1E,MAAM,IAAI,iBAAiB,CACzB,mBAAmB,MAAM,oBAAoB,OAAO,iCAAiC,CACtF,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC;QACxB,KAAK,CAAC,KAAa,EAAE,SAAS,EAAE,IAAI;YAClC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,IAAI,EAAE,CAAC;QACT,CAAC;KACF,CAAC,CAAC;IACH,MAAM,eAAe,CAAC,MAAM,EAAE,IAAI,CAAC,oBAAoB,EAAE,GAAG,EAAE,CAC5D,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC,CACrD,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,gBAAgB,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading the file list a TeamSpeak 6 server sends for `s3ft_list_files`.
|
|
3
|
+
*/
|
|
4
|
+
import type { S3FileEntry } from "./s3.js";
|
|
5
|
+
/**
|
|
6
|
+
* The file list the server sends: base64 of the JSON
|
|
7
|
+
* `{"contents":[{"key":"dir/a.txt","last_modified":"…","size":2}]}`, each key
|
|
8
|
+
* from the channel's root without a leading slash, and an empty field for no
|
|
9
|
+
* files.
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseFileList(field: string): S3FileEntry[];
|
|
12
|
+
//# sourceMappingURL=s3-list.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3-list.d.ts","sourceRoot":"","sources":["../../../src/client/api/s3-list.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,CAmC1D"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading the file list a TeamSpeak 6 server sends for `s3ft_list_files`.
|
|
3
|
+
*/
|
|
4
|
+
import { NoDataError } from "@honeybbq/teamspeak";
|
|
5
|
+
/**
|
|
6
|
+
* The file list the server sends: base64 of the JSON
|
|
7
|
+
* `{"contents":[{"key":"dir/a.txt","last_modified":"…","size":2}]}`, each key
|
|
8
|
+
* from the channel's root without a leading slash, and an empty field for no
|
|
9
|
+
* files.
|
|
10
|
+
*/
|
|
11
|
+
export function parseFileList(field) {
|
|
12
|
+
if (field === "")
|
|
13
|
+
return [];
|
|
14
|
+
const malformed = () => new NoDataError("s3ft_list_files", "the server answered s3ft_list_files with a malformed file list");
|
|
15
|
+
let parsed;
|
|
16
|
+
try {
|
|
17
|
+
parsed = JSON.parse(Buffer.from(field, "base64").toString("utf8"));
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
throw malformed();
|
|
21
|
+
}
|
|
22
|
+
const contents = parsed?.contents;
|
|
23
|
+
if (!Array.isArray(contents))
|
|
24
|
+
throw malformed();
|
|
25
|
+
return contents.map((item) => {
|
|
26
|
+
const entry = item;
|
|
27
|
+
const key = entry?.key;
|
|
28
|
+
const size = entry?.size;
|
|
29
|
+
if (typeof key !== "string" ||
|
|
30
|
+
typeof size !== "number" ||
|
|
31
|
+
!Number.isSafeInteger(size) ||
|
|
32
|
+
size < 0) {
|
|
33
|
+
throw malformed();
|
|
34
|
+
}
|
|
35
|
+
const time = typeof entry?.last_modified === "string" ? new Date(entry.last_modified) : undefined;
|
|
36
|
+
return {
|
|
37
|
+
path: key.startsWith("/") ? key : `/${key}`,
|
|
38
|
+
size: BigInt(size),
|
|
39
|
+
modifiedAt: time === undefined || Number.isNaN(time.getTime()) ? undefined : time,
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=s3-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3-list.js","sourceRoot":"","sources":["../../../src/client/api/s3-list.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlD;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IAC5B,MAAM,SAAS,GAAG,GAAgB,EAAE,CAClC,IAAI,WAAW,CACb,iBAAiB,EACjB,gEAAgE,CACjE,CAAC;IACJ,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,SAAS,EAAE,CAAC;IACpB,CAAC;IACD,MAAM,QAAQ,GAAI,MAAwC,EAAE,QAAQ,CAAC;IACrE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QAAE,MAAM,SAAS,EAAE,CAAC;IAChD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAa,EAAe,EAAE;QACjD,MAAM,KAAK,GAAG,IAAyE,CAAC;QACxF,MAAM,GAAG,GAAG,KAAK,EAAE,GAAG,CAAC;QACvB,MAAM,IAAI,GAAG,KAAK,EAAE,IAAI,CAAC;QACzB,IACE,OAAO,GAAG,KAAK,QAAQ;YACvB,OAAO,IAAI,KAAK,QAAQ;YACxB,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC;YAC3B,IAAI,GAAG,CAAC,EACR,CAAC;YACD,MAAM,SAAS,EAAE,CAAC;QACpB,CAAC;QACD,MAAM,IAAI,GACR,OAAO,KAAK,EAAE,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACvF,OAAO;YACL,IAAI,EAAE,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE;YAC3C,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC;YAClB,UAAU,EAAE,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;SAClF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TeamSpeak 6 S3 file transfer.
|
|
3
|
+
*
|
|
4
|
+
* A TeamSpeak 6 server started with S3 file transfer keeps channel files in an
|
|
5
|
+
* S3-compatible bucket, and says so: its `extensions`
|
|
6
|
+
* (`client.serverCapabilities.extensions`) name `"s3"`. A client asks the
|
|
7
|
+
* server for a presigned URL over the voice connection and moves the bytes
|
|
8
|
+
* with a plain HTTPS request to the storage; nothing goes through the server's
|
|
9
|
+
* file transfer port.
|
|
10
|
+
*
|
|
11
|
+
* TeamSpeak does not document these commands. Everything here was measured on
|
|
12
|
+
* TeamSpeak 6 6.0.0-beta13.1 with an S3-compatible storage behind TLS:
|
|
13
|
+
*
|
|
14
|
+
* - They run on the voice connection, which is why they take a `Client`:
|
|
15
|
+
* WebQuery refuses them as unknown commands.
|
|
16
|
+
* - The server keeps each channel's file list in memory, takes a file out of it
|
|
17
|
+
* when it deletes one, and reads it from the storage again when told an
|
|
18
|
+
* upload is done: a file stored without {@link completeS3FileUpload} is not
|
|
19
|
+
* listed.
|
|
20
|
+
* - Other clients are told nothing when a file is uploaded or deleted.
|
|
21
|
+
* - The classic file commands (`ftinitupload`, `ftgetfilelist`, …) still work
|
|
22
|
+
* on such a server, and reach a separate store: a file uploaded one way is
|
|
23
|
+
* not listed the other.
|
|
24
|
+
*
|
|
25
|
+
* Every function takes the channel password as `password`, in cleartext, and
|
|
26
|
+
* sends it the way every file command does.
|
|
27
|
+
*/
|
|
28
|
+
import { Readable, Writable } from "node:stream";
|
|
29
|
+
import type { ChannelID, CommandOptions } from "@honeybbq/teamspeak";
|
|
30
|
+
import type { Client } from "../client.js";
|
|
31
|
+
/** The channel password an S3 file command needs, and the command's own options. */
|
|
32
|
+
export interface S3FileOptions extends CommandOptions {
|
|
33
|
+
/** The channel's password, in cleartext; "" by default (`chpw`). */
|
|
34
|
+
readonly password?: string | undefined;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* An upload the server signed: where to send the file, and what to tell the
|
|
38
|
+
* server once it is stored.
|
|
39
|
+
*
|
|
40
|
+
* `url` is a credential: whoever holds it can write the file until it expires,
|
|
41
|
+
* after the server's `s3ft-presigned-url-expiration` (300 seconds by default).
|
|
42
|
+
* Keep it out of logs.
|
|
43
|
+
*/
|
|
44
|
+
export interface S3FileUploadInfo {
|
|
45
|
+
/** The channel whose file area the file goes to. */
|
|
46
|
+
readonly channelID: ChannelID;
|
|
47
|
+
/** The file's path from the channel's root, as the server confirmed it. */
|
|
48
|
+
readonly path: string;
|
|
49
|
+
/** The size in bytes the URL is signed for. The upload must send exactly this many. */
|
|
50
|
+
readonly size: bigint;
|
|
51
|
+
/** The presigned URL to `PUT` the file to. */
|
|
52
|
+
readonly url: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* A download the server signed. `url` is a credential as an upload's is: whoever
|
|
56
|
+
* holds it can read the file until it expires.
|
|
57
|
+
*/
|
|
58
|
+
export interface S3FileDownloadInfo {
|
|
59
|
+
/** The channel whose file area the file is in. */
|
|
60
|
+
readonly channelID: ChannelID;
|
|
61
|
+
/** The file's path from the channel's root, as the server confirmed it. */
|
|
62
|
+
readonly path: string;
|
|
63
|
+
/** The presigned URL to `GET` the file from. */
|
|
64
|
+
readonly url: string;
|
|
65
|
+
}
|
|
66
|
+
/** One file in a channel's S3 file area. */
|
|
67
|
+
export interface S3FileEntry {
|
|
68
|
+
/** The file's path from the channel's root, with a leading slash: `/docs/a.txt`. */
|
|
69
|
+
readonly path: string;
|
|
70
|
+
/** The size in bytes. */
|
|
71
|
+
readonly size: bigint;
|
|
72
|
+
/** When the storage last wrote it; undefined when the server sent no time it could read. */
|
|
73
|
+
readonly modifiedAt: Date | undefined;
|
|
74
|
+
}
|
|
75
|
+
/** How an S3 transfer reaches the storage. */
|
|
76
|
+
export interface S3TransferOptions {
|
|
77
|
+
/** Abandons the request; it then rejects with the signal's reason. */
|
|
78
|
+
readonly signal?: AbortSignal | undefined;
|
|
79
|
+
/**
|
|
80
|
+
* The `fetch` the request goes through; the global `fetch` by default. Pass
|
|
81
|
+
* one to route through a proxy, trust another certificate authority, time
|
|
82
|
+
* or watch the request, or to test.
|
|
83
|
+
*/
|
|
84
|
+
readonly fetch?: typeof globalThis.fetch | undefined;
|
|
85
|
+
}
|
|
86
|
+
/** How {@link downloadS3FileData} reads the file. */
|
|
87
|
+
export interface S3DownloadDataOptions extends S3TransferOptions {
|
|
88
|
+
/**
|
|
89
|
+
* The byte offset to start from, to resume; 0 by default. The bytes written
|
|
90
|
+
* are the file's from here to its end. The storage answers an offset at or
|
|
91
|
+
* past the end with 416, as an {@link S3TransferError}.
|
|
92
|
+
*/
|
|
93
|
+
readonly seekPosition?: bigint | undefined;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Ask the server to sign an upload of `size` bytes to `path` in a channel's S3
|
|
97
|
+
* file area. Pass the result to {@link uploadS3FileData} to send the file, then
|
|
98
|
+
* to {@link completeS3FileUpload}; {@link uploadS3File} does all three.
|
|
99
|
+
*
|
|
100
|
+
* The upload replaces a file already at the path: the storage keeps no other
|
|
101
|
+
* copy, and nothing asks first. A client without upload power is refused with
|
|
102
|
+
* 2049 (invalid file permissions). A path into a directory the channel's file
|
|
103
|
+
* list does not have yet needs directory create power as well, and is refused
|
|
104
|
+
* with 2049 without it; an area with no files at all takes any path. The
|
|
105
|
+
* directory is no object of its own: it is there while a file is in it.
|
|
106
|
+
*
|
|
107
|
+
* Rejects with an {@link S3UnsupportedError} unless the server names `"s3"`
|
|
108
|
+
* among its extensions, and with a `TypeError` for a path that cannot be sent
|
|
109
|
+
* (see {@link uploadS3File}).
|
|
110
|
+
*/
|
|
111
|
+
export declare function initS3FileUpload(client: Client, channelID: ChannelID, path: string, size: bigint, options?: S3FileOptions): Promise<S3FileUploadInfo>;
|
|
112
|
+
/**
|
|
113
|
+
* Ask the server to sign a download of `path` from a channel's S3 file area.
|
|
114
|
+
* Pass the result to {@link downloadS3FileData}; {@link downloadS3File} does
|
|
115
|
+
* both.
|
|
116
|
+
*
|
|
117
|
+
* The server signs a download whether or not the file is there: a missing one
|
|
118
|
+
* is the 404 of the download itself. A client without download power is
|
|
119
|
+
* refused with 2049 (invalid file permissions), as is a channel that does not
|
|
120
|
+
* exist.
|
|
121
|
+
*/
|
|
122
|
+
export declare function initS3FileDownload(client: Client, channelID: ChannelID, path: string, options?: S3FileOptions): Promise<S3FileDownloadInfo>;
|
|
123
|
+
/**
|
|
124
|
+
* Tell the server an upload is stored, after {@link uploadS3FileData}. The
|
|
125
|
+
* server then reads the channel's file list from the storage again, and lists
|
|
126
|
+
* the file; without this it does not.
|
|
127
|
+
*
|
|
128
|
+
* Rejects with an {@link S3TransferError} when the server reports that its own
|
|
129
|
+
* request to the storage failed.
|
|
130
|
+
*/
|
|
131
|
+
export declare function completeS3FileUpload(client: Client, info: S3FileUploadInfo, options?: S3FileOptions): Promise<void>;
|
|
132
|
+
/**
|
|
133
|
+
* Every file in a channel's S3 file area, in the storage's order (by path), as
|
|
134
|
+
* the server last read them from the storage.
|
|
135
|
+
*
|
|
136
|
+
* The list is the whole area, files in directories included: there are no
|
|
137
|
+
* directories, only paths. A file uploaded without
|
|
138
|
+
* {@link completeS3FileUpload} is missing from it until the server reads the
|
|
139
|
+
* list again. A channel that does not exist has no files.
|
|
140
|
+
*/
|
|
141
|
+
export declare function listS3Files(client: Client, channelID: ChannelID, options?: S3FileOptions): Promise<S3FileEntry[]>;
|
|
142
|
+
/**
|
|
143
|
+
* Delete one file from a channel's S3 file area. The server deletes it from
|
|
144
|
+
* the storage and from the file list it keeps.
|
|
145
|
+
*
|
|
146
|
+
* Deleting a file that is not there succeeds, as the storage's delete does. A
|
|
147
|
+
* client without delete power is refused with 2568 (insufficient client
|
|
148
|
+
* permissions). Rejects with an {@link S3TransferError} when the server reports
|
|
149
|
+
* that its own request to the storage failed.
|
|
150
|
+
*/
|
|
151
|
+
export declare function deleteS3File(client: Client, channelID: ChannelID, path: string, options?: S3FileOptions): Promise<void>;
|
|
152
|
+
/**
|
|
153
|
+
* Send a file to the storage, over an upload {@link initS3FileUpload} signed.
|
|
154
|
+
* `data` must be exactly `info.size` bytes: bytes or a `Blob` of another size
|
|
155
|
+
* are refused before anything is sent, and a stream that gives fewer or more
|
|
156
|
+
* fails the upload.
|
|
157
|
+
*
|
|
158
|
+
* Resolves once the storage has answered that it stored the file. Then call
|
|
159
|
+
* {@link completeS3FileUpload}, or the server does not list it. A failure is an
|
|
160
|
+
* {@link S3TransferError}: 403 for a URL that expired.
|
|
161
|
+
*/
|
|
162
|
+
export declare function uploadS3FileData(info: S3FileUploadInfo, data: Uint8Array | Blob | Readable, options?: S3TransferOptions): Promise<void>;
|
|
163
|
+
/**
|
|
164
|
+
* Read a file from the storage into `dest`, over a download
|
|
165
|
+
* {@link initS3FileDownload} signed. Resolves once the file is written; `dest`
|
|
166
|
+
* is not ended, so it may take another download.
|
|
167
|
+
*
|
|
168
|
+
* A file that is not there is an {@link S3TransferError} with status 404; a URL
|
|
169
|
+
* that expired, one with 403.
|
|
170
|
+
*/
|
|
171
|
+
export declare function downloadS3FileData(info: S3FileDownloadInfo, dest: Writable, options?: S3DownloadDataOptions): Promise<void>;
|
|
172
|
+
/**
|
|
173
|
+
* How {@link uploadS3File} signs and sends the file: the options of the
|
|
174
|
+
* commands and those of the request. `signal` applies to both.
|
|
175
|
+
*/
|
|
176
|
+
export interface UploadS3FileOptions extends S3FileOptions, S3TransferOptions {
|
|
177
|
+
/**
|
|
178
|
+
* The size in bytes of a stream passed as the data, which the server signs
|
|
179
|
+
* the upload for. Required for a `Readable`; for bytes or a `Blob` it is
|
|
180
|
+
* their size, and a different value here is refused.
|
|
181
|
+
*/
|
|
182
|
+
readonly size?: bigint | number | undefined;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Upload a file into a channel's S3 file area: sign the upload
|
|
186
|
+
* ({@link initS3FileUpload}), send the file to the storage
|
|
187
|
+
* ({@link uploadS3FileData}) and tell the server it is stored
|
|
188
|
+
* ({@link completeS3FileUpload}), in one call.
|
|
189
|
+
*
|
|
190
|
+
* `data` is the bytes, a `Blob` (such as `fs.openAsBlob(file)`), or a
|
|
191
|
+
* `Readable` with `options.size` the number of bytes it will give. Resolves
|
|
192
|
+
* once the storage has stored the file and the server lists it. The file
|
|
193
|
+
* replaces one already at the path.
|
|
194
|
+
*
|
|
195
|
+
* `path` runs from the channel's root; a leading slash is added when missing,
|
|
196
|
+
* and the directories in it need not exist. A path is refused with a
|
|
197
|
+
* `TypeError` when an HTTP client would not send the URL the server signs for
|
|
198
|
+
* it: one with an empty, `.` or `..` segment, a control character, or a slash
|
|
199
|
+
* at its end.
|
|
200
|
+
*
|
|
201
|
+
* A refusal by the server is the ServerError it sends (2049 for a client
|
|
202
|
+
* without upload power); a failure of the storage request, or a server that
|
|
203
|
+
* reports its own request to the storage failed, is an {@link S3TransferError}. A
|
|
204
|
+
* server that does not name `"s3"` among its extensions is refused with an
|
|
205
|
+
* {@link S3UnsupportedError} before anything is sent.
|
|
206
|
+
*/
|
|
207
|
+
export declare function uploadS3File(client: Client, channelID: ChannelID, path: string, data: Uint8Array | Blob | Readable, options?: UploadS3FileOptions): Promise<void>;
|
|
208
|
+
/**
|
|
209
|
+
* How {@link downloadS3File} signs and reads the file. With a `seekPosition`
|
|
210
|
+
* the bytes are the file's from there to its end.
|
|
211
|
+
*/
|
|
212
|
+
export interface DownloadS3FileOptions extends S3FileOptions, S3DownloadDataOptions {
|
|
213
|
+
/**
|
|
214
|
+
* Write the file into this stream instead of returning its bytes. The stream
|
|
215
|
+
* is neither ended nor destroyed, so it may take several downloads; a failed
|
|
216
|
+
* download still rejects the call.
|
|
217
|
+
*/
|
|
218
|
+
readonly dest?: Writable | undefined;
|
|
219
|
+
/**
|
|
220
|
+
* The most bytes to hold in memory when no `dest` is given; 268435456
|
|
221
|
+
* (256 MiB) by default. A larger download is refused with a
|
|
222
|
+
* {@link FileTransferError} before its body is read.
|
|
223
|
+
*/
|
|
224
|
+
readonly maxSize?: number | undefined;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Download a file from a channel's S3 file area into memory: sign the download
|
|
228
|
+
* ({@link initS3FileDownload}) and read the file ({@link downloadS3FileData}),
|
|
229
|
+
* in one call. With `options.dest` the bytes go into that stream instead and
|
|
230
|
+
* nothing is held, which is the way to fetch a large file.
|
|
231
|
+
*
|
|
232
|
+
* A file that is not there is an {@link S3TransferError} with status 404. Paths
|
|
233
|
+
* and refusals are as for {@link uploadS3File}.
|
|
234
|
+
*/
|
|
235
|
+
export declare function downloadS3File(client: Client, channelID: ChannelID, path: string, options: DownloadS3FileOptions & {
|
|
236
|
+
readonly dest: Writable;
|
|
237
|
+
}): Promise<void>;
|
|
238
|
+
export declare function downloadS3File(client: Client, channelID: ChannelID, path: string, options?: DownloadS3FileOptions): Promise<Uint8Array>;
|
|
239
|
+
//# sourceMappingURL=s3.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3.d.ts","sourceRoot":"","sources":["../../../src/client/api/s3.ts"],"names":[],"mappings":"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"}
|