{"id":26505560,"url":"https://github.com/tf2pickup-org/mumble-client","last_synced_at":"2026-02-13T19:01:05.485Z","repository":{"id":37044772,"uuid":"490466349","full_name":"tf2pickup-org/mumble-client","owner":"tf2pickup-org","description":"A simple mumble client for managing mumble servers","archived":false,"fork":false,"pushed_at":"2026-02-10T18:37:01.000Z","size":13069,"stargazers_count":9,"open_issues_count":6,"forks_count":5,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-02-10T21:57:38.608Z","etag":null,"topics":["bot","mumble","mumble-client","mumble-server","murmur","nodejs"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tf2pickup-org.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-05-09T22:43:52.000Z","updated_at":"2026-02-08T05:00:12.000Z","dependencies_parsed_at":"2024-05-03T23:28:27.004Z","dependency_job_id":"ca4062e3-c0bc-4d92-8a05-1161d359ea87","html_url":"https://github.com/tf2pickup-org/mumble-client","commit_stats":{"total_commits":341,"total_committers":4,"mean_commits":85.25,"dds":"0.33137829912023464","last_synced_commit":"1f194dcfeeea358fa5a63534709c2d6f027a5fb5"},"previous_names":["tf2pickup-org/simple-mumble-bot"],"tags_count":37,"template":false,"template_full_name":null,"purl":"pkg:github/tf2pickup-org/mumble-client","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tf2pickup-org%2Fmumble-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tf2pickup-org%2Fmumble-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tf2pickup-org%2Fmumble-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tf2pickup-org%2Fmumble-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tf2pickup-org","download_url":"https://codeload.github.com/tf2pickup-org/mumble-client/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tf2pickup-org%2Fmumble-client/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29414342,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-13T06:24:03.484Z","status":"ssl_error","status_checked_at":"2026-02-13T06:23:12.830Z","response_time":78,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bot","mumble","mumble-client","mumble-server","murmur","nodejs"],"created_at":"2025-03-20T21:47:40.389Z","updated_at":"2026-02-13T19:01:05.477Z","avatar_url":"https://github.com/tf2pickup-org.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003emumble-client\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003eA simple mumble client for managing mumble servers\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/@tf2pickup-org/mumble-client\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/v/@tf2pickup-org/mumble-client\" alt=\"Latest release\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/tf2pickup-org/mumble-client/actions?query=workflow%3Atest\"\u003e\n    \u003cimg src=\"https://github.com/tf2pickup-org/mumble-client/actions/workflows/test.yml/badge.svg\" alt=\"Test status\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://opensource.org/licenses/MIT\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/License-MIT-yellow.svg\" alt=\"MIT license\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## Features\n\n- Connect to any Mumble server over TLS\n- Manage channels: create, remove, link/unlink, fetch ACLs\n- Manage users: move, mute/deafen, register/deregister, rename\n- Query channel permissions\n- Event-driven architecture with full TypeScript support\n- Automatic keep-alive pinging\n\n## Installation\n\n```bash\nnpm i @tf2pickup-org/mumble-client\n```\n\n## Quick start\n\n```typescript\nimport { Client } from '@tf2pickup-org/mumble-client';\n\nconst client = new Client({\n  host: 'mumble.example.com',\n  port: 64738,\n  username: 'my-bot',\n  rejectUnauthorized: false,\n});\n\nawait client.connect();\nconsole.log(`Connected! Welcome message: ${client.welcomeText}`);\nconsole.log(`Logged in as ${client.self?.name}`);\n\n// ... do work ...\n\nclient.disconnect();\n```\n\n## Examples\n\n### Connect with a password and access tokens\n\n```typescript\nconst client = new Client({\n  host: 'mumble.example.com',\n  port: 64738,\n  username: 'my-bot',\n  password: 'server-password',\n  tokens: ['token-for-acl-group'],\n  clientName: 'my-awesome-bot',\n  rejectUnauthorized: false,\n});\n\nawait client.connect();\n```\n\n### List all channels\n\n```typescript\nimport { type Channel } from '@tf2pickup-org/mumble-client';\n\nfunction printChannel(channel: Channel, level = 0) {\n  if (channel.name) {\n    console.log(' '.repeat(level * 2) + channel.name);\n  }\n\n  for (const subChannel of channel.subChannels) {\n    printChannel(subChannel, level + 1);\n  }\n}\n\nprintChannel(client.channels.root);\n```\n\n### Find a channel\n\n```typescript\n// by name\nconst lobby = client.channels.byName('Lobby');\n\n// by path (from root)\nconst redTeam = client.channels.byPath('Match 1', 'RED');\n\n// by custom predicate\nconst tempChannels = client.channels.findAll(ch =\u003e ch.temporary);\n```\n\n### Create and manage channels\n\n```typescript\nconst root = client.channels.root;\n\n// create a sub-channel under root\nconst matchChannel = await root.createSubChannel('Match 1');\n\n// create team channels\nconst red = await matchChannel.createSubChannel('RED');\nconst blu = await matchChannel.createSubChannel('BLU');\n\n// link two channels together\nawait red.link(blu);\n\n// unlink them\nawait red.unlink(blu);\n\n// remove a channel (and all its sub-channels)\nawait matchChannel.remove();\n```\n\n### Move users between channels\n\n```typescript\nconst user = client.users.byName('PlayerOne');\nconst targetChannel = client.channels.byName('RED');\n\nif (user \u0026\u0026 targetChannel) {\n  await user.moveToChannel(targetChannel.id);\n}\n```\n\n### Mute/deafen yourself\n\n```typescript\n// self-mute\nawait client.self.setSelfMute(true);\n\n// self-deafen\nawait client.self.setSelfDeaf(true);\n\n// unmute\nawait client.self.setSelfMute(false);\n```\n\n### Register and manage users\n\n```typescript\n// register the currently logged-in user\nawait client.self.register();\n\n// fetch all registered users from the server\nconst registeredUsers = await client.fetchRegisteredUsers();\nfor (const user of registeredUsers) {\n  console.log(`${user.userId}: ${user.name}`);\n}\n\n// rename a registered user (does not need to be online)\nawait client.renameRegisteredUser(userId, 'NewName');\n\n// deregister a user (does not need to be online)\nawait client.deregisterUser(userId);\n```\n\n### Check channel permissions\n\n```typescript\nconst channel = client.channels.byName('Lobby');\nif (channel) {\n  const permissions = await channel.getPermissions();\n  console.log('Can join:', permissions.canJoinChannel);\n  console.log('Can create sub-channels:', permissions.canCreateChannel);\n  console.log('Can remove:', permissions.canRemoveChannel);\n  console.log('Can link:', permissions.canLinkChannel);\n}\n```\n\n### Listen to events\n\n```typescript\n// user connected\nclient.on('userCreate', user =\u003e {\n  console.log(`${user.name} connected`);\n});\n\n// user disconnected\nclient.on('userRemove', user =\u003e {\n  console.log(`${user.name} disconnected`);\n});\n\n// user state changed (e.g. moved channel, muted, etc.)\nclient.on('userUpdate', (user, changes) =\u003e {\n  if (changes.channelId) {\n    const from = client.channels.byId(changes.channelId.previousValue);\n    const to = client.channels.byId(changes.channelId.currentValue);\n    console.log(`${user.name} moved from ${from?.name} to ${to?.name}`);\n  }\n});\n\n// channel created\nclient.on('channelCreate', channel =\u003e {\n  console.log(`Channel created: ${channel.name}`);\n});\n\n// channel removed\nclient.on('channelRemove', channel =\u003e {\n  console.log(`Channel removed: ${channel.name}`);\n});\n\n// speaking state changes\nclient.on('speakingStateChange', ({ user, speaking }) =\u003e {\n  console.log(`${user.name} ${speaking ? 'started' : 'stopped'} speaking`);\n});\n\n// disconnected from server\nclient.on('disconnect', payload =\u003e {\n  console.log(`Disconnected: ${payload?.reason ?? 'unknown reason'}`);\n});\n```\n\n### Error handling\n\n```typescript\nimport {\n  Client,\n  ConnectionRejectedError,\n  PermissionDeniedError,\n  NoSuchChannelError,\n} from '@tf2pickup-org/mumble-client';\n\ntry {\n  await client.connect();\n} catch (error) {\n  if (error instanceof ConnectionRejectedError) {\n    console.error('Connection rejected by server');\n  }\n}\n\ntry {\n  await client.channels.root.createSubChannel('test');\n} catch (error) {\n  if (error instanceof PermissionDeniedError) {\n    console.error('Insufficient permissions to create channel');\n  }\n}\n```\n\n## API overview\n\n### `Client`\n\nThe main entry point. Connects to the server and provides access to channels, users, and events.\n\n| Property / Method | Description |\n|---|---|\n| `channels` | `ChannelManager` instance for finding channels |\n| `users` | `UserManager` instance for finding users |\n| `self` | The currently logged-in `User` |\n| `welcomeText` | Server welcome message |\n| `serverVersion` | Server version info |\n| `connect()` | Connect to the Mumble server |\n| `disconnect()` | Disconnect from the server |\n| `isConnected()` | Returns `true` if connected |\n| `fetchRegisteredUsers()` | Fetch all registered users |\n| `deregisterUser(userId)` | Deregister a user by ID |\n| `renameRegisteredUser(userId, name)` | Rename a registered user |\n\n### `ChannelManager`\n\n| Method | Description |\n|---|---|\n| `root` | The root channel |\n| `byId(channelId)` | Find channel by ID |\n| `byName(name)` | Find channel by name |\n| `byPath(...path)` | Find channel by path segments |\n| `find(predicate)` | Find first matching channel |\n| `findAll(predicate)` | Find all matching channels |\n\n### `Channel`\n\n| Property / Method | Description |\n|---|---|\n| `id` | Channel ID |\n| `name` | Channel name |\n| `temporary` | Whether the channel is temporary |\n| `users` | Users currently in this channel |\n| `subChannels` | Direct sub-channels |\n| `linkedChannels` | Linked channels |\n| `createSubChannel(name)` | Create a sub-channel |\n| `remove()` | Remove this channel |\n| `link(channel)` | Link with another channel |\n| `unlink(channel)` | Unlink from another channel |\n| `getPermissions()` | Fetch permissions for this channel |\n| `fetchAcl()` | Fetch the channel ACL |\n| `saveAcl(acl)` | Save the channel ACL |\n\n### `UserManager`\n\n| Method | Description |\n|---|---|\n| `bySession(session)` | Find user by session ID |\n| `byName(name)` | Find user by name |\n| `findAll(predicate)` | Find all matching users |\n\n### `User`\n\n| Property / Method | Description |\n|---|---|\n| `session` | Session ID |\n| `name` | Username |\n| `channel` | Current channel |\n| `channelId` | Current channel ID |\n| `isRegistered` | Whether the user is registered |\n| `mute` / `deaf` / `suppress` | Server mute/deaf/suppress state |\n| `selfMute` / `selfDeaf` | Self-mute/deaf state |\n| `moveToChannel(channelId)` | Move user to a channel |\n| `setSelfMute(mute)` | Set self-mute state |\n| `setSelfDeaf(deaf)` | Set self-deaf state |\n| `register()` | Register the user |\n| `deregister()` | Deregister the user |\n| `rename(name)` | Rename a registered user |\n\n### `Permissions`\n\n| Property / Method | Description |\n|---|---|\n| `canJoinChannel` | Can join/enter the channel |\n| `canCreateChannel` | Can create sub-channels |\n| `canRemoveChannel` | Can remove channels |\n| `canLinkChannel` | Can link channels |\n| `canSelfRegister` | Can self-register |\n| `canRegister` | Can register other users |\n\n### Events\n\n| Event | Payload | Description |\n|---|---|---|\n| `connect` | — | Client connected successfully |\n| `disconnect` | `{ reason?: string }` | Client disconnected |\n| `channelCreate` | `Channel` | A channel was created |\n| `channelUpdate` | `Channel, ChannelChanges` | A channel was updated |\n| `channelRemove` | `Channel` | A channel was removed |\n| `userCreate` | `User` | A user connected |\n| `userUpdate` | `User, UserChanges` | A user's state changed |\n| `userRemove` | `User` | A user disconnected |\n| `speakingStateChange` | `{ user: User, speaking: boolean }` | A user started/stopped speaking |\n\n### `ClientOptions`\n\nExtends Node.js `tls.ConnectionOptions`.\n\n| Option | Type | Default | Description |\n|---|---|---|---|\n| `host` | `string` | — | Server hostname |\n| `port` | `number` | `64738` | Server port |\n| `username` | `string` | — | Username for authentication |\n| `password` | `string?` | — | Server or user password |\n| `tokens` | `string[]?` | `[]` | Access tokens for server ACL groups |\n| `clientName` | `string?` | `'simple mumble bot'` | Client name sent to the server |\n| `pingInterval` | `number?` | `10000` | Keep-alive ping interval in ms |\n\nSince `ClientOptions` extends `tls.ConnectionOptions`, you can pass any TLS option such as `rejectUnauthorized`, `cert`, `key`, `ca`, etc.\n\n## License\n\n[MIT](https://opensource.org/licenses/MIT)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftf2pickup-org%2Fmumble-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftf2pickup-org%2Fmumble-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftf2pickup-org%2Fmumble-client/lists"}