Merge pull request #15 from FrauJulian/13_unit_tests_and_fix_memory_leak

13 unit tests and fix memory leak
This commit is contained in:
2025-08-02 17:58:35 +02:00
committed by GitHub
4 changed files with 7381 additions and 3691 deletions
+25 -1
View File
@@ -18,9 +18,32 @@ Please create an [issue](https://github.com/FrauJulian/DiscordAudioStreamNPM/iss
### Install package
```bash
npm install discord-audio-stream opusscript @discordjs/voice ffmpeg-static sodium-native
npm install discord-audio-stream
yarn add discord-audio-stream
pnpm add discord-audio-stream
bun add discord-audio-stream
```
**Encryption Libraries (npm install):**
> You only need to install one of these libraries if your system does not support `aes-256-gcm` (verify by running `require('node:crypto').getCiphers().includes('aes-256-gcm')`).
- `sodium-native`
- `sodium`
- `@stablelib/xchacha20poly1305`
- `@noble/ciphers`
- `libsodium-wrappers`
**Opus Libraries (npm install):**
- `@discordjs/opus`
- `opusscript`
**FFmpeg:**
- [`FFmpeg`](https://ffmpeg.org/) (installed and added to environment)
- `ffmpeg-static`
### Create Instance
```js
@@ -65,6 +88,7 @@ let audioManager = new AudioManager({
| `StopAudioOnConnection` | | void | Method to stop the audio without destroying voice connection. |
| `CreateConnectionAndPlayAudio` | | void | Method to join the voice connection and play audio. |
| `DestroyConnection` | | void | Method to destroy the voice connection. |
| `Dispose` | | void | Dispose all data in object. |
| `SetVolume` | `volume` (type of number, 0 - 100 percent) | void | Method to set the audio volume. | Method to set the volume of the audio. |
| `SetMaxListeners` | `maxListeners` (type of number) | void | Method to set the max listeners of the audio stream. |
+7244 -3598
View File
File diff suppressed because it is too large Load Diff
+64 -76
View File
@@ -1,79 +1,67 @@
{
"name": "discord-audio-stream",
"version": "0.6.12",
"license": "LGPL-2.1-only",
"description": "NodeJS library to make stream any audio on discord easier.",
"exports": {
".": {
"require": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
}
}
},
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"directories": {
"lib": "src"
},
"scripts": {
"updateDependencies": "npx npm-check-updates --upgrade && npm install && echo SUCCEED UPDATE",
"cleanSolution": "del-cli dist && echo SUCCEED CLEAN",
"updateVersion": "npm version patch --no-git-tag-version && echo SUCCEED UPDATE VERSION",
"buildPackage": "tsup && echo SUCCEED BUILD && npm run updateVersion",
"rolloutBuild": "npm run updateDependencies && npm run cleanSolution && tsup"
},
"repository": "https://github.com/FrauJulian/Discord-Audio-Stream",
"bugs": "https://github.com/FrauJulian/Discord-Audio-Stream/issues",
"funding": "https://ko-fi.com/FrauJulian",
"keywords": [
"discordjs",
"discord.js",
"discord",
"audio",
"voice",
"stream"
],
"contributors": [
{
"name": "Lechner Julian",
"nickname": "FrauJulian",
"email": "office@lechner-systems.at",
"website": "https://lechner-systems.at/"
}
],
"dependencies": {
"@noble/ciphers": "^1.3.0",
"@stablelib/xchacha20poly1305": "^2.0.1",
"sodium-native": "^5.0.6"
},
"devDependencies": {
"@types/ejs": "^3.1.5",
"@types/node": "^24.1.0",
"del-cli": "^6.0.0",
"npm-check-updates": "^18.0.2",
"tsup": "^8.5.0",
"typescript": "^5.8.3"
},
"peerDependencies": {
"@discordjs/voice": "^0.18.0",
"libsodium-wrappers": "^0.7.15",
"opusscript": "^0.1.1",
"ffmpeg-static": "^5.2.0"
},
"engines": {
"node": ">=18"
},
"private": false,
"publishConfig": {
"access": "public"
"name": "discord-audio-stream",
"version": "0.6.13",
"license": "LGPL-2.1-only",
"description": "NodeJS library to make stream any audio on discord easier.",
"exports": {
".": {
"require": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"import": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
}
}
},
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"directories": {
"lib": "src"
},
"scripts": {
"updateDependencies": "npx npm-check-updates --upgrade && npm install && echo SUCCEED UPDATE",
"cleanSolution": "del-cli dist && echo SUCCEED CLEAN",
"updateVersion": "npm version patch --no-git-tag-version && echo SUCCEED UPDATE VERSION",
"buildPackage": "tsup && echo SUCCEED BUILD && npm run updateVersion",
"rolloutBuild": "npm run updateDependencies && npm run cleanSolution && tsup"
},
"repository": "https://github.com/FrauJulian/Discord-Audio-Stream",
"bugs": "https://github.com/FrauJulian/Discord-Audio-Stream/issues",
"funding": "https://ko-fi.com/FrauJulian",
"keywords": [
"discordjs",
"discord.js",
"discord",
"audio",
"voice",
"stream"
],
"contributors": [
"Lechner Julian - FrauJulian <office@lechner-systems.at>"
],
"dependencies": {
"@discordjs/voice": "^0.18.0"
},
"devDependencies": {
"@types/ejs": "^3.1.5",
"@types/node": "^24.1.0",
"del-cli": "^6.0.0",
"npm-check-updates": "^18.0.2",
"ts-jest": "^29.4.0",
"tsup": "^8.5.0",
"typescript": "^5.9.2"
},
"engines": {
"node": ">=18"
},
"private": false,
"publishConfig": {
"access": "public"
}
}
+48 -16
View File
@@ -11,22 +11,27 @@ import {VoiceConnectionDataModel} from "./types/VoiceConnectionDataModel";
import {VoiceAudioDataModel} from "./types/VoiceAudioDataModel";
export default class AudioManager {
public VoiceConnection: VoiceConnection | null = null;
public AudioPlayer: AudioPlayer | null = null;
public AudioResource: AudioResource | null = null;
public VoiceConnection?: VoiceConnection = undefined;
public AudioPlayer?: AudioPlayer = undefined;
public AudioResource?: AudioResource = undefined;
protected IsActive: boolean = false;
protected IsAudioPlaying: boolean = false;
protected IsActive?: boolean = undefined;
protected IsAudioPlaying?: boolean = undefined;
protected ConnectionData: VoiceConnectionDataModel | null;
protected AudioData: VoiceAudioDataModel | null;
protected ConnectionData?: VoiceConnectionDataModel;
protected AudioData?: VoiceAudioDataModel;
constructor(connectionData: VoiceConnectionDataModel | null = null, audioData: VoiceAudioDataModel | null = null) {
private TimeoutHandle?: NodeJS.Timeout;
private RenewInMs?: number;
constructor(connectionData?: VoiceConnectionDataModel, audioData?: VoiceAudioDataModel, renewInMs = 5400000) {
this.RenewInMs = renewInMs;
this.ConnectionData = connectionData;
this.AudioData = audioData;
}
public OverrideOptions(connectionData: VoiceConnectionDataModel | null = null, audioData: VoiceAudioDataModel | null = null): void {
public OverrideOptions(connectionData?: VoiceConnectionDataModel, audioData?: VoiceAudioDataModel, renewInMs = 5400000): void {
this.RenewInMs = renewInMs;
this.ConnectionData = connectionData;
this.AudioData = audioData;
}
@@ -48,9 +53,9 @@ export default class AudioManager {
adapterCreator: this.ConnectionData!.VoiceAdapter
});
setTimeout((): void => {
this.TimeoutHandle = setTimeout((): void => {
this.RenewConnectionAndAudio();
}, 5400000);
}, this.RenewInMs);
}
public PlayAudioOnConnection(): void {
@@ -82,13 +87,21 @@ export default class AudioManager {
}
public PauseAudio(): void {
this.CheckIfNull(this.AudioPlayer);
this.AudioPlayer!.pause();
if (this.IsAudioPlaying) {
this.AudioPlayer!.pause();
this.IsAudioPlaying = false;
} else {
throw new TypeError("Audio is not playing.");
}
}
public ResumeAudio(): void {
this.CheckIfNull(this.AudioPlayer);
this.AudioPlayer!.unpause();
if (!this.IsAudioPlaying) {
this.AudioPlayer!.unpause();
this.IsAudioPlaying = true;
} else {
throw new TypeError("Audio is playing.");
}
}
public CreateConnectionAndPlayAudio(): void {
@@ -107,15 +120,34 @@ export default class AudioManager {
}
public SetMaxListeners(maxListeners: number): void {
this.CheckIfNull(this.VoiceConnection);
this.VoiceConnection!.setMaxListeners(maxListeners);
}
public SetVolume(volumeInPercent: number): void {
if (volumeInPercent < 0 || volumeInPercent > 100) throw new Error("Volume must be between 0 and 100.");
this.CheckIfNull(this.VoiceConnection);
this.AudioResource!.volume!.setVolume(volumeInPercent / 100);
}
public Dispose(): void {
if (this.IsActive != undefined) {
this.DestroyConnection();
this.ConnectionData = undefined;
this.VoiceConnection = undefined;
}
if (this.IsAudioPlaying != undefined) {
this.AudioData = undefined;
this.AudioResource = undefined;
this.AudioPlayer = undefined;
}
if (this.TimeoutHandle) {
clearTimeout(this.TimeoutHandle);
this.TimeoutHandle = undefined;
}
}
private RenewConnectionAndAudio(): void {
this.DestroyConnection(false);
if (this.IsActive) {