chore: monorepo setup (#7175)

This commit is contained in:
Noel
2022-01-07 17:18:25 +01:00
committed by GitHub
parent 780b7ed39f
commit 16390efe6e
504 changed files with 25459 additions and 22830 deletions

View File

@@ -0,0 +1,2 @@
config.json
package-lock.json

View 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
}
```

View File

@@ -0,0 +1,6 @@
{
"token": "discord_bot_token",
"device": "audio_hw_device_id",
"type": "pulse",
"maxTransmissionGap": 5000
}

View 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);

View 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"
}
}