refactor: make hardcoded values configurable via env vars
This commit is contained in:
@@ -5,6 +5,15 @@ export interface AppConfig {
|
||||
recordingSegmentMs: number;
|
||||
decoderRotateMs: number;
|
||||
decoderCooldownMs: number;
|
||||
webserverPort: number;
|
||||
voiceConnectionTimeoutMs: number;
|
||||
reconnectTimeoutMs: number;
|
||||
audioStreamSilenceDurationMs: number;
|
||||
packetFilterMinSize: number;
|
||||
opusFrameSize: number;
|
||||
audioSampleRate: number;
|
||||
audioChannels: number;
|
||||
avatarSize: number;
|
||||
}
|
||||
|
||||
export function parseBoolean(
|
||||
@@ -30,7 +39,22 @@ export function loadConfig(env: NodeJS.ProcessEnv = process.env): AppConfig {
|
||||
recordingsDir: env.RECORDINGS_DIR ?? "./recordings",
|
||||
recordingSegmentMs: parsePositiveNumber(env.RECORDING_SEGMENT_MS, 5_000),
|
||||
decoderRotateMs: parsePositiveNumber(env.DECODER_ROTATE_MS, 5_000),
|
||||
decoderCooldownMs: 30_000,
|
||||
decoderCooldownMs: parsePositiveNumber(env.DECODER_COOLDOWN_MS, 30_000),
|
||||
webserverPort: parsePositiveNumber(env.WEBSERVER_PORT, 3000),
|
||||
voiceConnectionTimeoutMs: parsePositiveNumber(
|
||||
env.VOICE_CONNECTION_TIMEOUT_MS,
|
||||
15_000,
|
||||
),
|
||||
reconnectTimeoutMs: parsePositiveNumber(env.RECONNECT_TIMEOUT_MS, 5_000),
|
||||
audioStreamSilenceDurationMs: parsePositiveNumber(
|
||||
env.AUDIO_STREAM_SILENCE_DURATION_MS,
|
||||
3000,
|
||||
),
|
||||
packetFilterMinSize: parsePositiveNumber(env.PACKET_FILTER_MIN_SIZE, 8),
|
||||
opusFrameSize: parsePositiveNumber(env.OPUS_FRAME_SIZE, 960),
|
||||
audioSampleRate: parsePositiveNumber(env.AUDIO_SAMPLE_RATE, 48000),
|
||||
audioChannels: parsePositiveNumber(env.AUDIO_CHANNELS, 2),
|
||||
avatarSize: parsePositiveNumber(env.AVATAR_SIZE, 64),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ client.on("ready", async () => {
|
||||
}
|
||||
|
||||
// Start Webserver
|
||||
startWebserver(3000);
|
||||
startWebserver(config.webserverPort);
|
||||
});
|
||||
|
||||
client.on("error", (err) => {
|
||||
|
||||
@@ -59,7 +59,11 @@ export async function startRecording(
|
||||
|
||||
// Tunggu sampai benar-benar terhubung
|
||||
try {
|
||||
await entersState(connection, VoiceConnectionStatus.Ready, 15_000);
|
||||
await entersState(
|
||||
connection,
|
||||
VoiceConnectionStatus.Ready,
|
||||
config.voiceConnectionTimeoutMs,
|
||||
);
|
||||
if (config.verbose) {
|
||||
console.log("[recorder] Connected to voice channel. Recording started.");
|
||||
}
|
||||
@@ -97,7 +101,7 @@ export async function startRecording(
|
||||
|
||||
try {
|
||||
// --- OGG file recording with segment rotation ---
|
||||
const packetFilterForOgg = new PacketFilter(8);
|
||||
const packetFilterForOgg = new PacketFilter(config.packetFilterMinSize);
|
||||
const audioStream = receiver.subscribe(userId, {
|
||||
end: {
|
||||
behavior: EndBehaviorType.AfterSilence,
|
||||
@@ -201,8 +205,16 @@ export async function startRecording(
|
||||
}
|
||||
try {
|
||||
await Promise.race([
|
||||
entersState(connection, VoiceConnectionStatus.Signalling, 5_000),
|
||||
entersState(connection, VoiceConnectionStatus.Connecting, 5_000),
|
||||
entersState(
|
||||
connection,
|
||||
VoiceConnectionStatus.Signalling,
|
||||
config.reconnectTimeoutMs,
|
||||
),
|
||||
entersState(
|
||||
connection,
|
||||
VoiceConnectionStatus.Connecting,
|
||||
config.reconnectTimeoutMs,
|
||||
),
|
||||
]);
|
||||
// Berhasil reconnect
|
||||
} catch {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { EndBehaviorType, type VoiceReceiver } from "@discordjs/voice";
|
||||
import { config } from "../config";
|
||||
|
||||
export interface AudioStreamHandlers {
|
||||
onPacket: (chunk: Buffer) => void;
|
||||
@@ -14,7 +15,7 @@ export function subscribeToAudioStream(
|
||||
const audioStream = receiver.subscribe(userId, {
|
||||
end: {
|
||||
behavior: EndBehaviorType.AfterSilence,
|
||||
duration: 3000,
|
||||
duration: config.audioStreamSilenceDurationMs,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import prism from "prism-media";
|
||||
import { config } from "../config";
|
||||
|
||||
export interface OpusDecoderOptions {
|
||||
cooldownMs: number;
|
||||
@@ -23,7 +24,11 @@ export class OpusDecoder {
|
||||
this.createDecoderFn =
|
||||
options.createDecoder ??
|
||||
(() =>
|
||||
new prism.opus.Decoder({ frameSize: 960, channels: 2, rate: 48000 }));
|
||||
new prism.opus.Decoder({
|
||||
frameSize: config.opusFrameSize,
|
||||
channels: config.audioChannels as 1 | 2,
|
||||
rate: config.audioSampleRate as 8000 | 12000 | 16000 | 24000 | 48000,
|
||||
}));
|
||||
}
|
||||
|
||||
rotateIfNeeded(): void {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import path from "node:path";
|
||||
import type { Client, VoiceChannel } from "discord.js-selfbot-v13";
|
||||
import { config } from "../config";
|
||||
import type { SegmentMetadata, SegmentState, UserMetadata } from "../types";
|
||||
|
||||
export async function collectUserMetadata(
|
||||
@@ -30,8 +31,19 @@ export async function collectUserMetadata(
|
||||
tag: user?.tag ?? "Unknown#0000",
|
||||
displayName: member?.displayName ?? username,
|
||||
avatarUrl:
|
||||
user?.displayAvatarURL({ format: "png", size: 64 }) ??
|
||||
"https://cdn.discordapp.com/embed/avatars/0.png",
|
||||
user?.displayAvatarURL({
|
||||
format: "png",
|
||||
size: config.avatarSize as
|
||||
| 16
|
||||
| 32
|
||||
| 64
|
||||
| 128
|
||||
| 256
|
||||
| 512
|
||||
| 1024
|
||||
| 2048
|
||||
| 4096,
|
||||
}) ?? "https://cdn.discordapp.com/embed/avatars/0.png",
|
||||
bot: user?.bot ?? false,
|
||||
roles,
|
||||
highestRole: roles[0] ?? null,
|
||||
|
||||
Reference in New Issue
Block a user