Skip to content

Repository files navigation

@honeybbq/teamspeak-client

A clean-room TeamSpeak client protocol library written in pure TypeScript.

Compatible with TeamSpeak 3, 5 & 6. No proprietary SDK. No copy-pasted code.

CI npm Node Version License: MIT

Features

  • Full protocol handshake — ECDH key exchange, RSA puzzle, EAX-encrypted transport
  • Command & notification system — Send commands, receive server events
  • Event-driven API — Register handlers for text messages, client enter/leave, channel moves, kicks, etc.
  • Voice data — Send Opus voice packets (codec 4 & 5)
  • File transfers — Upload, download, and delete files on the server
  • Address resolution — SRV records, TSDNS, and direct address support
  • Middleware — Pluggable command and event middleware chains
  • Built-in rate limiter — Token-bucket throttling to prevent server-side flood kicks
  • Identity management — Generate, import/export, and upgrade security level of identities
  • Dual format — Ships ESM and CJS with full TypeScript declarations
  • Zero native deps — Pure TypeScript, no native addons required

Installation

npm install @honeybbq/teamspeak-client
# or
pnpm add @honeybbq/teamspeak-client

Requires Node.js 20.19 or later.

Quick Start

import { Client, generateIdentity } from "@honeybbq/teamspeak-client";

// Generate a new identity (or load an existing one)
const identity = generateIdentity(8);

// Create the client
const client = new Client(identity, "localhost", "TSBot", {
  serverPassword: process.env.TEAMSPEAK_SERVER_PASSWORD,
  defaultChannel: "Lobby",
  defaultChannelPassword: process.env.TEAMSPEAK_DEFAULT_CHANNEL_PASSWORD,
});

// Register event handlers
client.on("connected", () => {
  console.log("Connected to server!");
});

client.on("textMessage", (msg) => {
  console.log(`[${msg.invokerName}]: ${msg.message}`);
});

client.on("disconnected", (err) => {
  console.log("Disconnected:", err?.message ?? "clean");
});

// Connect
await client.connect();

// Wait until connected (with 15s timeout)
await client.waitConnected(AbortSignal.timeout(15_000));

// Stay connected until interrupted
process.on("SIGINT", async () => {
  await client.disconnect();
});

API Overview

Client Lifecycle

Method Description
new Client(identity, addr, nickname, opts?) Create a new client
connect() Initiate connection to the server
waitConnected(signal?) Block until the handshake completes
disconnect() Gracefully disconnect

Events

Method Description
on("connected", handler) Fires when fully connected
on("disconnected", handler) Fires on disconnect
on("textMessage", handler) Fires on text messages
on("clientEnter", handler) Fires when a client joins
on("clientLeave", handler) Fires when a client leaves
on("clientMoved", handler) Fires when a client moves channels
on("kicked", handler) Fires when the bot is kicked
on("poke", handler) Fires when poked by a client
on("voice", handler) Fires on incoming voice data

Commands

Function Description
sendTextMessage(client, targetMode, targetID, msg) Send a text message
clientMove(client, clid, channelID, password?) Move a client to a channel
poke(client, clid, message) Poke a client
client.sendVoice(data, codec) Send Opus voice data
client.sendWhisper(data, clientIds, codec) Send Opus voice to specific clients
listChannels(client) List all channels
listClients(client) List all connected clients
getClientInfo(client, clid) Get detailed client information
client.execCommand(cmd, timeout?) Execute a raw command
client.execCommandWithResponse(cmd, timeout?) Execute a command and return response data

File Transfers

Function Description
client.fileTransferInitUpload(...) Initialize a file upload
client.fileTransferInitDownload(...) Initialize a file download
fileTransferDeleteFile(client, ...) Delete files on the server
uploadFileData(host, info, reader) Transfer file data to the server
downloadFileData(host, info, writer) Receive file data from the server

Identity

import { generateIdentity, identityFromString } from "@honeybbq/teamspeak-client";

// Generate a new identity with security level 8
const identity = generateIdentity(8);

// Export to string for persistent storage
const exported = identity.exportString();

// Import from a previously exported string
const restored = identityFromString(exported);

// Upgrade security level (CPU-intensive)
identity.upgradeToLevel(10);

Options

const client = new Client(identity, "ts.example.com", "Bot", {
  logger: consoleLogger,
  resolver: customResolver,
  commandMiddleware: [loggingMiddleware],
  eventMiddleware: [filterMiddleware],
  serverPassword: process.env.TEAMSPEAK_SERVER_PASSWORD,
  defaultChannel: "Lobby",
  defaultChannelPassword: process.env.TEAMSPEAK_DEFAULT_CHANNEL_PASSWORD,
});

Connection auth options:

  • serverPassword: plain-text server password; sent as the TeamSpeak protocol hash during clientinit
  • defaultChannel: default channel name requested during clientinit
  • defaultChannelPassword: plain-text password for defaultChannel; sent as the TeamSpeak protocol hash

Subpath Exports

The package provides granular subpath exports for advanced use cases:

import { Identity } from "@honeybbq/teamspeak-client/crypto";
import { Resolver } from "@honeybbq/teamspeak-client/discovery";
import { PacketHandler } from "@honeybbq/teamspeak-client/transport";
import { buildCommand, parseCommand } from "@honeybbq/teamspeak-client/command";
import { processInit1 } from "@honeybbq/teamspeak-client/handshake";

Architecture

teamspeak-js/
├── src/
│   ├── client.ts          # Client lifecycle, connection management
│   ├── api.ts             # High-level API (messages, channels, clients)
│   ├── commands.ts        # Command sending and response tracking
│   ├── events.ts          # Event handler registration and middleware
│   ├── notifications.ts   # Server notification parsing and dispatch
│   ├── handshake.ts       # Protocol handshake orchestration
│   ├── transfer.ts        # File transfer operations
│   ├── throttle.ts        # Token-bucket rate limiter
│   ├── types.ts           # Public type definitions
│   ├── errors.ts          # Error classes
│   ├── crypto/            # ECDH, EAX encryption, identity management
│   ├── handshake/         # Crypto handshake and license verification
│   ├── transport/         # UDP packet framing, ACK, compression
│   ├── command/           # Command builder and parser
│   └── discovery/         # SRV / TSDNS / direct address resolution
├── examples/
│   └── connect.ts         # Minimal connection example
├── vite.config.ts         # Build configuration (Vite library mode)
└── tsconfig.json

Related

  • teamspeak-go — The original Go implementation this library is ported from

Acknowledgments

Protocol knowledge was primarily informed by the TSLib implementation in TS3AudioBot by Splamy. Huge thanks to the TS3AudioBot project and its contributors.

Disclaimer

TeamSpeak is a registered trademark of TeamSpeak Systems GmbH. This project is not affiliated with, endorsed by, or associated with TeamSpeak Systems GmbH in any way.

This library is a clean-room implementation developed from publicly available documentation, protocol analysis of network traffic, and independent research. No proprietary TeamSpeak SDK code, headers, or libraries were used in its creation.

License

MIT

About

A clean-room TeamSpeak client protocol library written in pure TypeScript

Resources

Stars

7 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages