mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-14 18:43:31 +01:00
chore: monorepo setup (#7175)
This commit is contained in:
2
packages/voice/examples/radio-bot/.gitignore
vendored
Normal file
2
packages/voice/examples/radio-bot/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
config.json
|
||||
package-lock.json
|
||||
64
packages/voice/examples/radio-bot/README.md
Normal file
64
packages/voice/examples/radio-bot/README.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Discord Radio Bot 🎧
|
||||
|
||||
A proof-of-concept radio bot that uses @discordjs/voice and discord.js. Streams audio from an audio output hardware device on your computer over a Discord voice channel.
|
||||
|
||||
**Works on:**
|
||||
|
||||
- Linux (via PulseAudio `pulse`)
|
||||
- Windows (via DirectShow `dshow`)
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Clone the main @discordjs/voice repo, then install dependencies and build
|
||||
$ npm install
|
||||
$ npm run build
|
||||
|
||||
# Enter this example's directory, create a config file and start!
|
||||
$ cd examples/radio-bot
|
||||
$ npm install
|
||||
$ nano config.json
|
||||
$ npm start
|
||||
|
||||
# Join a voice channel in Discord, then send "-join"
|
||||
```
|
||||
|
||||
## Configuring on Windows via `dshow`
|
||||
|
||||
Run `ffmpeg -list_devices true -f dshow -i dummy` and observe output containing something similar:
|
||||
|
||||
```
|
||||
DirectShow audio devices
|
||||
"Stereo Mix (Realtek(R) Audio)"
|
||||
Alternative name "@device_cm_{ID1}\wave_{ID2}"
|
||||
```
|
||||
|
||||
For example, playing the above device will mirror audio from the speaker output of your machine. Your `config.json` should then be considered like so:
|
||||
|
||||
```json
|
||||
{
|
||||
"token": "discord_bot_token",
|
||||
"device": "Stereo Mix (Realtek(R) Audio)",
|
||||
"type": "dshow",
|
||||
"maxTransmissionGap": 5000
|
||||
}
|
||||
```
|
||||
|
||||
## Configuring on Linux via `pulse`
|
||||
|
||||
Run `pactl list short sources` and observe output containing something similar:
|
||||
|
||||
```
|
||||
5 alsa_output.pci.3.analog-stereo.monitor module-alsa-card.c s16le 2ch 44100Hz IDLE
|
||||
```
|
||||
|
||||
Then configure your `config.json` with the device you'd like to use:
|
||||
|
||||
```json
|
||||
{
|
||||
"token": "discord_bot_token",
|
||||
"device": "alsa_output.pci.3.analog-stereo.monitor",
|
||||
"type": "pulse",
|
||||
"maxTransmissionGap": 5000
|
||||
}
|
||||
```
|
||||
6
packages/voice/examples/radio-bot/config.example.json
Normal file
6
packages/voice/examples/radio-bot/config.example.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"token": "discord_bot_token",
|
||||
"device": "audio_hw_device_id",
|
||||
"type": "pulse",
|
||||
"maxTransmissionGap": 5000
|
||||
}
|
||||
104
packages/voice/examples/radio-bot/index.js
Normal file
104
packages/voice/examples/radio-bot/index.js
Normal file
@@ -0,0 +1,104 @@
|
||||
require('module-alias/register');
|
||||
|
||||
const { Client } = require('discord.js');
|
||||
const prism = require('prism-media');
|
||||
const config = require('./config.json');
|
||||
const {
|
||||
NoSubscriberBehavior,
|
||||
StreamType,
|
||||
createAudioPlayer,
|
||||
createAudioResource,
|
||||
entersState,
|
||||
AudioPlayerStatus,
|
||||
VoiceConnectionStatus,
|
||||
joinVoiceChannel,
|
||||
} = require('@discordjs/voice');
|
||||
|
||||
const player = createAudioPlayer({
|
||||
behaviors: {
|
||||
noSubscriber: NoSubscriberBehavior.Play,
|
||||
maxMissedFrames: Math.round(config.maxTransmissionGap / 20),
|
||||
},
|
||||
});
|
||||
|
||||
player.on('stateChange', (oldState, newState) => {
|
||||
if (oldState.status === AudioPlayerStatus.Idle && newState.status === AudioPlayerStatus.Playing) {
|
||||
console.log('Playing audio output on audio player');
|
||||
} else if (newState.status === AudioPlayerStatus.Idle) {
|
||||
console.log('Playback has stopped. Attempting to restart.');
|
||||
attachRecorder();
|
||||
}
|
||||
});
|
||||
|
||||
function attachRecorder() {
|
||||
player.play(
|
||||
createAudioResource(
|
||||
new prism.FFmpeg({
|
||||
args: [
|
||||
'-analyzeduration',
|
||||
'0',
|
||||
'-loglevel',
|
||||
'0',
|
||||
'-f',
|
||||
config.type,
|
||||
'-i',
|
||||
config.type === 'dshow' ? `audio=${config.device}` : config.device,
|
||||
'-acodec',
|
||||
'libopus',
|
||||
'-f',
|
||||
'opus',
|
||||
'-ar',
|
||||
'48000',
|
||||
'-ac',
|
||||
'2',
|
||||
],
|
||||
}),
|
||||
{
|
||||
inputType: StreamType.OggOpus,
|
||||
},
|
||||
),
|
||||
);
|
||||
console.log('Attached recorder - ready to go!');
|
||||
}
|
||||
|
||||
async function connectToChannel(channel) {
|
||||
const connection = joinVoiceChannel({
|
||||
channelId: channel.id,
|
||||
guildId: channel.guild.id,
|
||||
adapterCreator: channel.guild.voiceAdapterCreator,
|
||||
});
|
||||
try {
|
||||
await entersState(connection, VoiceConnectionStatus.Ready, 30_000);
|
||||
return connection;
|
||||
} catch (error) {
|
||||
connection.destroy();
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const client = new Client({ intents: ['GUILDS', 'GUILD_MESSAGES', 'GUILD_VOICE_STATES'] });
|
||||
|
||||
client.on('ready', async () => {
|
||||
console.log('discord.js client is ready!');
|
||||
attachRecorder();
|
||||
});
|
||||
|
||||
client.on('messageCreate', async (message) => {
|
||||
if (!message.guild) return;
|
||||
if (message.content === '-join') {
|
||||
const channel = message.member?.voice.channel;
|
||||
if (channel) {
|
||||
try {
|
||||
const connection = await connectToChannel(channel);
|
||||
connection.subscribe(player);
|
||||
await message.reply('Playing now!');
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
} else {
|
||||
await message.reply('Join a voice channel then try again!');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
void client.login(config.token);
|
||||
32
packages/voice/examples/radio-bot/package.json
Normal file
32
packages/voice/examples/radio-bot/package.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "discord-radio-bot",
|
||||
"version": "1.0.0",
|
||||
"description": "A proof-of-concept radio bot for @discordjs/voice",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "node index.js"
|
||||
},
|
||||
"keywords": [
|
||||
"discord",
|
||||
"radio",
|
||||
"bot",
|
||||
"audio",
|
||||
"speakers",
|
||||
"hardware",
|
||||
"dj"
|
||||
],
|
||||
"author": "Amish Shah <amish@shah.gg>",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@discordjs/voice": "file:../../",
|
||||
"discord.js": "^13.0.0-dev.f7eeccba4b7015496df811f10cc2da2b0fab0630",
|
||||
"libsodium-wrappers": "^0.7.9",
|
||||
"module-alias": "^2.2.2",
|
||||
"prism-media": "^1.3.1"
|
||||
},
|
||||
"_moduleAliases": {
|
||||
"@root": ".",
|
||||
"@discordjs/voice": "../../",
|
||||
"libsodium-wrappers": "./node_modules/libsodium-wrappers"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user