initial music stuff

This commit is contained in:
ReaperOfVeriod
2026-01-31 02:50:20 +01:00
parent e262300def
commit f00cbb2091
9 changed files with 535 additions and 35 deletions
+2
View File
@@ -0,0 +1,2 @@
node_modules
Dockerfile
+78
View File
@@ -0,0 +1,78 @@
const { SlashCommandBuilder } = require('discord.js');
const {
joinVoiceChannel,
createAudioPlayer,
createAudioResource,
StreamType,
} = require('@discordjs/voice');
const { spawn } = require('node:child_process');
module.exports = {
data: new SlashCommandBuilder()
.setName('play')
.setDescription('Proof-of-life music command'),
async execute(interaction) {
const voiceChannel = interaction.member.voice.channel;
if (!voiceChannel) {
return interaction.reply({
content: '❌ You need to join a voice channel first!',
ephemeral: true,
});
}
// 1️⃣ Defer reply immediately to prevent 3s timeout
await interaction.deferReply();
try {
// 2️⃣ Spawn yt-dlp → ffmpeg → Discord
const ytdlp = spawn('yt-dlp', [
'-f', 'bestaudio',
'-o', '-',
'https://www.youtube.com/watch?v=dQw4w9WgXcQ', // test URL
]);
const ffmpeg = spawn('ffmpeg', [
'-i', 'pipe:0',
'-f', 's16le', // raw PCM for Discord
'-ar', '48000', // sample rate
'-ac', '2', // stereo
'pipe:1',
]);
ytdlp.stdout.pipe(ffmpeg.stdin);
const resource = createAudioResource(ffmpeg.stdout, {
inputType: StreamType.Raw,
});
const player = createAudioPlayer();
player.play(resource);
const connection = joinVoiceChannel({
channelId: voiceChannel.id,
guildId: interaction.guild.id,
adapterCreator: interaction.guild.voiceAdapterCreator,
});
connection.subscribe(player);
// 3️⃣ Edit deferred reply
await interaction.editReply('▶️ Now playing: Rick Astley!');
// Optional logging
ytdlp.stderr.on('data', (data) => console.error('yt-dlp:', data.toString()));
ffmpeg.stderr.on('data', (data) => console.error('ffmpeg:', data.toString()));
player.on('error', (err) => console.error('AudioPlayer error:', err));
} catch (err) {
console.error(err);
// 4️⃣ Safe error reply
if (interaction.deferred || interaction.replied) {
await interaction.editReply('❌ Failed to play audio!');
} else {
await interaction.reply('❌ Failed to play audio!');
}
}
},
};
+9
View File
@@ -0,0 +1,9 @@
services:
app:
container_name: reapersbeepboop
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/opt/app
- /opt/app/node_modules
+16
View File
@@ -0,0 +1,16 @@
FROM node:24-alpine
# Install system dependencies
RUN apk add --no-cache \
ffmpeg \
python3 \
yt-dlp
WORKDIR /app
COPY package*.json ./
RUN npm install --omit=dev
COPY . .
CMD ["node", "main.js"]
+31 -31
View File
@@ -1,34 +1,38 @@
const { Events, MessageFlags, Collection, GuildMember, PermissionsBitField } = require('discord.js');
const { Events, MessageFlags, Collection } = require('discord.js');
async function safeReply(interaction, content) {
if (interaction.replied || interaction.deferred) {
await interaction.editReply(content).catch(() => {
interaction.followUp({ content, flags: MessageFlags.Ephemeral }).catch(console.error);
});
} else {
await interaction.reply({ content, flags: MessageFlags.Ephemeral }).catch(console.error);
}
}
module.exports = {
name: Events.InteractionCreate,
async execute(interaction) {
if (interaction.isChatInputCommand()) {
const command = interaction.client.commands.get(interaction.commandName);
if (!command) {
console.error(`No command matching ${interaction.commandName} was found.`);
return;
}
if (!command) return console.error(`No command matching ${interaction.commandName} found.`);
const { cooldowns } = interaction.client;
if (!cooldowns.has(command.data.name)) {
cooldowns.set(command.data.name, new Collection());
}
if (!cooldowns.has(command.data.name)) cooldowns.set(command.data.name, new Collection());
const now = Date.now();
const timestamps = cooldowns.get(command.data.name);
const defaultCooldownDuration = 3;
const cooldownAmount = (command.cooldown ?? defaultCooldownDuration) * 1000;
const defaultCooldown = 3;
const cooldownAmount = (command.cooldown ?? defaultCooldown) * 1000;
if (timestamps.has(interaction.user.id)) {
const expirationTime = timestamps.get(interaction.user.id) + cooldownAmount;
if (now < expirationTime) {
const expiredTimestamp = Math.round(expirationTime / 1000);
return interaction.reply({ content: `Please wait, you are on a cooldown for \`${command.data.name}\`. You can use it again <t:${expiredTimestamp}:R>.`, flags: MessageFlags.Ephemeral });
const expired = Math.round(expirationTime / 1000);
return interaction.reply({
content: `Please wait, you are on cooldown for \`${command.data.name}\`. Try again <t:${expired}:R>.`,
flags: MessageFlags.Ephemeral,
});
}
}
@@ -39,43 +43,39 @@ module.exports = {
await command.execute(interaction);
} catch (error) {
console.error(error);
if (interaction.replied || interaction.deferred) {
await interaction.followUp({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral });
} else {
await interaction.reply({ content: 'There was an error while executing this command!', flags: MessageFlags.Ephemeral });
}
await safeReply(interaction, '❌ There was an error while executing this command!');
}
} else if (interaction.isButton()) {
if (interaction.customId === 'acceptnotifications') {
const notifiRoleId = "1401849479149391882";
const notifiRoleId = '1401849479149391882';
try {
if (interaction.member.roles.cache.has(notifiRoleId)) {
await interaction.reply({ content: 'you already have the notification role!', flags: MessageFlags.Ephemeral });
await interaction.reply({ content: 'You already have the notification role!', flags: MessageFlags.Ephemeral });
} else {
await interaction.member.roles.add(notifiRoleId);
await interaction.reply({ content: 'Thank you hope to see you soon in my streams!', flags: MessageFlags.Ephemeral });
await interaction.reply({ content: 'Thank you! Hope to see you soon in my streams!', flags: MessageFlags.Ephemeral });
}
} catch (error) {
await interaction.reply({ content: 'something went wrong', flags: MessageFlags.Ephemeral });
console.log(error);
console.error(error);
await interaction.reply({ content: 'Something went wrong', flags: MessageFlags.Ephemeral });
}
}
if (interaction.customId === 'acceptrules') {
const viewerRoleId = "1401153107601395774";
const viewerRoleId = '1401153107601395774';
try {
if (interaction.member.roles.cache.has(viewerRoleId)) {
await interaction.reply({ content: 'you already have accepted the rules!', flags: MessageFlags.Ephemeral });
await interaction.reply({ content: 'You already accepted the rules!', flags: MessageFlags.Ephemeral });
} else {
await interaction.member.roles.add(viewerRoleId);
await interaction.reply({ content: 'Thank you for accepting the rules!', flags: MessageFlags.Ephemeral });
}
} catch (error) {
await interaction.reply({ content: 'something went wrong', flags: MessageFlags.Ephemeral });
console.log(error);
console.error(error);
await interaction.reply({ content: 'Something went wrong', flags: MessageFlags.Ephemeral });
}
}
} else if (interaction.isStringSelectMenu()) {
// respond to the select menu
// handle select menu
}
},
};
+6 -1
View File
@@ -3,7 +3,12 @@ const path = require('node:path');
const { Client, Collection, Events, GatewayIntentBits, MessageFlags } = require('discord.js');
const { token } = require('./config.json');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildVoiceStates,
],
});
client.cooldowns = new Collection();
client.commands = new Collection();
+364 -1
View File
@@ -9,7 +9,10 @@
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"discord.js": "^14.21.0"
"@discordjs/voice": "^0.19.0",
"@snazzah/davey": "^0.1.9",
"discord.js": "^14.21.0",
"opusscript": "^0.0.8"
}
},
"node_modules/@discordjs/builders": {
@@ -104,6 +107,25 @@
"url": "https://github.com/discordjs/discord.js?sponsor"
}
},
"node_modules/@discordjs/voice": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.19.0.tgz",
"integrity": "sha512-UyX6rGEXzVyPzb1yvjHtPfTlnLvB5jX/stAMdiytHhfoydX+98hfympdOwsnTktzr+IRvphxTbdErgYDJkEsvw==",
"license": "Apache-2.0",
"dependencies": {
"@types/ws": "^8.18.1",
"discord-api-types": "^0.38.16",
"prism-media": "^1.3.5",
"tslib": "^2.8.1",
"ws": "^8.18.3"
},
"engines": {
"node": ">=22.12.0"
},
"funding": {
"url": "https://github.com/discordjs/discord.js?sponsor"
}
},
"node_modules/@discordjs/ws": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@discordjs/ws/-/ws-1.2.3.tgz",
@@ -139,6 +161,53 @@
"url": "https://github.com/discordjs/discord.js?sponsor"
}
},
"node_modules/@emnapi/core": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz",
"integrity": "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==",
"license": "MIT",
"optional": true,
"dependencies": {
"@emnapi/wasi-threads": "1.1.0",
"tslib": "^2.4.0"
}
},
"node_modules/@emnapi/runtime": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz",
"integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==",
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@emnapi/wasi-threads": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz",
"integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==",
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@napi-rs/wasm-runtime": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.1.tgz",
"integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==",
"license": "MIT",
"optional": true,
"dependencies": {
"@emnapi/core": "^1.7.1",
"@emnapi/runtime": "^1.7.1",
"@tybys/wasm-util": "^0.10.1"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/Brooooooklyn"
}
},
"node_modules/@sapphire/async-queue": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.5.tgz",
@@ -172,6 +241,268 @@
"npm": ">=7.0.0"
}
},
"node_modules/@snazzah/davey": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@snazzah/davey/-/davey-0.1.9.tgz",
"integrity": "sha512-vNZk5y+IsxjwzTAXikvzz5pqMLb35YytC64nVF2MAFVhjpXu9ITOKUriZ0JG/llwzCAi56jb5x0cXDRIyE2A2A==",
"license": "MIT",
"engines": {
"node": ">= 10"
},
"funding": {
"url": "https://github.com/sponsors/Snazzah"
},
"optionalDependencies": {
"@snazzah/davey-android-arm-eabi": "0.1.9",
"@snazzah/davey-android-arm64": "0.1.9",
"@snazzah/davey-darwin-arm64": "0.1.9",
"@snazzah/davey-darwin-x64": "0.1.9",
"@snazzah/davey-freebsd-x64": "0.1.9",
"@snazzah/davey-linux-arm-gnueabihf": "0.1.9",
"@snazzah/davey-linux-arm64-gnu": "0.1.9",
"@snazzah/davey-linux-arm64-musl": "0.1.9",
"@snazzah/davey-linux-x64-gnu": "0.1.9",
"@snazzah/davey-linux-x64-musl": "0.1.9",
"@snazzah/davey-wasm32-wasi": "0.1.9",
"@snazzah/davey-win32-arm64-msvc": "0.1.9",
"@snazzah/davey-win32-ia32-msvc": "0.1.9",
"@snazzah/davey-win32-x64-msvc": "0.1.9"
}
},
"node_modules/@snazzah/davey-android-arm-eabi": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@snazzah/davey-android-arm-eabi/-/davey-android-arm-eabi-0.1.9.tgz",
"integrity": "sha512-Dq0WyeVGBw+uQbisV/6PeCQV2ndJozfhZqiNIfQxu6ehIdXB7iHILv+oY+AQN2n+qxiFmLh/MOX9RF+pIWdPbA==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@snazzah/davey-android-arm64": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@snazzah/davey-android-arm64/-/davey-android-arm64-0.1.9.tgz",
"integrity": "sha512-OE16OZjv7F/JrD7Mzw5eL2gY2vXRPC8S7ZrmkcMyz/sHHJsGHlT+L7X5s56Bec1YDTVmzAsH4UBuvVBoXuIWEQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@snazzah/davey-darwin-arm64": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@snazzah/davey-darwin-arm64/-/davey-darwin-arm64-0.1.9.tgz",
"integrity": "sha512-z7oORvAPExikFkH6tvHhbUdZd77MYZp9VqbCpKEiI+sisWFVXgHde7F7iH3G4Bz6gUYJfgvKhWXiDRc+0SC4dg==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@snazzah/davey-darwin-x64": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@snazzah/davey-darwin-x64/-/davey-darwin-x64-0.1.9.tgz",
"integrity": "sha512-f1LzGyRGlM414KpXml3OgWVSd7CgylcdYaFj/zDBb8bvWjxyvsI9iMeuPfe/cduloxRj8dELde/yCDZtFR6PdQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@snazzah/davey-freebsd-x64": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@snazzah/davey-freebsd-x64/-/davey-freebsd-x64-0.1.9.tgz",
"integrity": "sha512-k6p3JY2b8rD6j0V9Ql7kBUMR4eJdcpriNwiHltLzmtGuz/nK5RGQdkEP68gTLc+Uj3xs5Cy0jRKmv2xJQBR4sA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@snazzah/davey-linux-arm-gnueabihf": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@snazzah/davey-linux-arm-gnueabihf/-/davey-linux-arm-gnueabihf-0.1.9.tgz",
"integrity": "sha512-xDaAFUC/1+n/YayNwKsqKOBMuW0KI6F0SjgWU+krYTQTVmAKNjOM80IjemrVoqTpBOxBsT80zEtct2wj11CE3Q==",
"cpu": [
"arm"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@snazzah/davey-linux-arm64-gnu": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@snazzah/davey-linux-arm64-gnu/-/davey-linux-arm64-gnu-0.1.9.tgz",
"integrity": "sha512-t1VxFBzWExPNpsNY/9oStdAAuHqFvwZvIO2YPYyVNstxfi2KmAbHMweHUW7xb2ppXuhVQZ4VGmmeXiXcXqhPBw==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@snazzah/davey-linux-arm64-musl": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@snazzah/davey-linux-arm64-musl/-/davey-linux-arm64-musl-0.1.9.tgz",
"integrity": "sha512-Xvlr+nBPzuFV4PXHufddlt08JsEyu0p8mX2DpqdPxdpysYIH4I8V86yJiS4tk04a6pLBDd8IxTbBwvXJKqd/LQ==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@snazzah/davey-linux-x64-gnu": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@snazzah/davey-linux-x64-gnu/-/davey-linux-x64-gnu-0.1.9.tgz",
"integrity": "sha512-6Uunc/NxiEkg1reroAKZAGfOtjl1CGa7hfTTVClb2f+DiA8ZRQWBh+3lgkq/0IeL262B4F14X8QRv5Bsv128qw==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@snazzah/davey-linux-x64-musl": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@snazzah/davey-linux-x64-musl/-/davey-linux-x64-musl-0.1.9.tgz",
"integrity": "sha512-fFQ/n3aWt1lXhxSdy+Ge3gi5bR3VETMVsWhH0gwBALUKrbo3ZzgSktm4lNrXE9i0ncMz/CDpZ5i0wt/N3XphEQ==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@snazzah/davey-wasm32-wasi": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@snazzah/davey-wasm32-wasi/-/davey-wasm32-wasi-0.1.9.tgz",
"integrity": "sha512-xWvzej8YCVlUvzlpmqJMIf0XmLlHqulKZ2e7WNe2TxQmsK+o0zTZqiQYs2MwaEbrNXBhYlHDkdpuwoXkJdscNQ==",
"cpu": [
"wasm32"
],
"license": "MIT",
"optional": true,
"dependencies": {
"@napi-rs/wasm-runtime": "^1.1.0"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/@snazzah/davey-win32-arm64-msvc": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@snazzah/davey-win32-arm64-msvc/-/davey-win32-arm64-msvc-0.1.9.tgz",
"integrity": "sha512-sTqry/DfltX2OdW1CTLKa3dFYN5FloAEb2yhGsY1i5+Bms6OhwByXfALvyMHYVo61Th2+sD+9BJpQffHFKDA3w==",
"cpu": [
"arm64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@snazzah/davey-win32-ia32-msvc": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@snazzah/davey-win32-ia32-msvc/-/davey-win32-ia32-msvc-0.1.9.tgz",
"integrity": "sha512-twD3LwlkGnSwphsCtpGb5ztpBIWEvGdc0iujoVkdzZ6nJiq5p8iaLjJMO4hBm9h3s28fc+1Qd7AMVnagiOasnA==",
"cpu": [
"ia32"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@snazzah/davey-win32-x64-msvc": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@snazzah/davey-win32-x64-msvc/-/davey-win32-x64-msvc-0.1.9.tgz",
"integrity": "sha512-eMnXbv4GoTngWYY538i/qHz2BS+RgSXFsvKltPzKqnqzPzhQZIY7TemEJn3D5yWGfW4qHve9u23rz93FQqnQMA==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">= 10"
}
},
"node_modules/@tybys/wasm-util": {
"version": "0.10.1",
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
"integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
"license": "MIT",
"optional": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@types/node": {
"version": "24.1.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.1.0.tgz",
@@ -260,6 +591,38 @@
"integrity": "sha512-ThQLOhN86ZkJ7qemtVRGYM+gRgR8GEXNli9H/PMvpnZsE44Xfh3wx9kGJaldg314v85m+bFW6WBMaVHJc/c3zA==",
"license": "MIT"
},
"node_modules/opusscript": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/opusscript/-/opusscript-0.0.8.tgz",
"integrity": "sha512-VSTi1aWFuCkRCVq+tx/BQ5q9fMnQ9pVZ3JU4UHKqTkf0ED3fKEPdr+gKAAl3IA2hj9rrP6iyq3hlcJq3HELtNQ==",
"license": "MIT"
},
"node_modules/prism-media": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.5.tgz",
"integrity": "sha512-IQdl0Q01m4LrkN1EGIE9lphov5Hy7WWlH6ulf5QdGePLlPas9p2mhgddTEHrlaXYjjFToM1/rWuwF37VF4taaA==",
"license": "Apache-2.0",
"peerDependencies": {
"@discordjs/opus": ">=0.8.0 <1.0.0",
"ffmpeg-static": "^5.0.2 || ^4.2.7 || ^3.0.0 || ^2.4.0",
"node-opus": "^0.3.3",
"opusscript": "^0.0.8"
},
"peerDependenciesMeta": {
"@discordjs/opus": {
"optional": true
},
"ffmpeg-static": {
"optional": true
},
"node-opus": {
"optional": true
},
"opusscript": {
"optional": true
}
}
},
"node_modules/ts-mixer": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.4.tgz",
+4 -1
View File
@@ -10,6 +10,9 @@
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"discord.js": "^14.21.0"
"@discordjs/voice": "^0.19.0",
"@snazzah/davey": "^0.1.9",
"discord.js": "^14.21.0",
"opusscript": "^0.0.8"
}
}
+24
View File
@@ -0,0 +1,24 @@
const { spawn } = require('node:child_process');
console.log('Starting smoke test...');
const ytdlp = spawn('yt-dlp', [
'-f', 'bestaudio',
'-o', '-',
'https://www.youtube.com/watch?v=dQw4w9WgXcQ'
]);
const ffmpeg = spawn('ffmpeg', [
'-i', 'pipe:0',
'-f', 'null',
'-'
]);
ytdlp.stdout.pipe(ffmpeg.stdin);
ffmpeg.on('close', (code) => {
console.log('FFmpeg exited with code:', code);
});
ytdlp.on('error', err => console.error('yt-dlp error:', err));
ffmpeg.on('error', err => console.error('ffmpeg error:', err));