Build a lo-fi cafe for your Discord Server in 5 minutes
Tags: discord, node, voice, javascript
Published: 2021-06-14 13:03:36


This blog was originally published at [my personal website](blog.ayush.contact) 

I decided to have a chill voice channel where we all could sit together (virtually) and co-work while listening to a lo-fi audio stream and maybe have some occasional talks too.

We will be learning how to create a bot that automatically joins a voice channel whenever someone joins, starts broadcasting music & leaves after 5 minutes of inactivity. 

Do you need something cool like this in your own server?

**TL;DR**
[here's the github code](https://github.com/heyAyushh/lo-fi-discord-cafe) with one click deploy button for heroku, ready.

Less gooo 🥳

## Setup

Prerequisites

- [NodeJS LTS](https://nodejs.org/en/)  and VScode or IDE of your choice.
- Pen
- Pineapple
- Apple
- pen
- Just kidding, let's setup the project now,

    ```jsx
    git init
    npm init -y 
    npm i -s discord.js dotenv ytdl-core-discord lodash
    ```

- Go to [Discord Developer Portal](https://discord.com/developers/applications) and create an application.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9qlxw6ias53lvnf0ag1w.png) 

- Go to Bot in menu

    ![./images/1.png](https://blog.ayush.contact/static/d7d6dca1c0c1b6e4228b9cf69f6fb19c/4665c/1.png/)

    In the Build-A-Bot section here 

    ![./images/2.png](https://blog.ayush.contact/static/030846760472ed4560580ebe4fbd1579/0f41c/2.png/)

    Add copy the token and store it in a file. call it .env

    ```jsx
    // in .env file
    DISCORD_BOT_TOKEN="Your Bot Token here"
    ```

- Now let's invite the bot to our server  
  Go to OAuth2 Page
  ![./images/3.png](https://blog.ayush.contact/static/322837a4e59c81950f6920b17288ff96/df43e/3.png)
  Scroll down to OAuth2 url generator andselect the bot permission
  ![./images/4.png](https://blog.ayush.contact/static/b5c48bc3248b505ad02a2643435e88a7/cbcb6/4.png)
  Scroll more and select these bot permission, 
  It allows the bot to connect, speak , viewchannels, and use voice activity 
  ![https://blog.ayush.contact/static/c7242f8f9e0147cf8492d02531acdd53/f9260/5.png](https://blog.ayush.contact/static/c7242f8f9e0147cf8492d02531acdd53/f9260/5.png)
  After selecting the appropriate permissions, click the 'copy' button above the permissions. That will copy a URL which can be used to add the bot to a server.  
  Paste the URL into your browser, choose a server to invite the bot to, and click “Authorize”.  
  To add the bot, your account needs "ManageServer" permissions.  
  Now that you've created the bot user, we'll start writing the NodeJS code for the bot.  
## Code

Here's the file and folder structure → 

```jsx
|—/client.js
|—/index.js
|—/.env
|—/.gitignore
```

We don't want to push Petabytes of node modules to GitHub. so, we'll create a .gitignore file.
Whatever we add inside here will be ignored by git and that's what we want.

```jsx
// in .gitignore

node_modules/
.env
```

Inside .env file you should have the bot token, If you don't see the setup section once again.
You skippin' lines bro.

[Copy your github server id](https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-) and save it in your .env file.
Also create a voice channel in your discord server, add the exact channel name in .env file. (avoid using ' ' in discord channel name.

```jsx
// in ./.env

DISCORD_BOT_TOKEN="Your Bot Token here"
DISCORD_GUILD_ID="Your discord server id here"
DISCORD_CHANNEL_NAME="lofi-channel-🎵"
VOICE_URLS="add more than two urls, seperated by comma"
```

Create a file called client.js and add these lines there.
line number one implies that we are requiring dependency.

```jsx
// ./client

const Discord = require('discord.js');
require('dotenv').config();

const client = new Discord.Client();

client.login(process.env.DISCORD_BOT_TOKEN);

module.exports = client;
```

line number 2 means that we want to setup all variables,
inside .env file to the environment variables.
line number 6 and 8 wants the bot to login and then export it,
so we can use it inside any file now.

Now that we have our client ready, 
Let's code the Bot.

Create a file index.js and require client.js.

```jsx
// ./index

const client = require('./client');
const ytdl = require('ytdl-core-discord');
const _ = require('lodash')
```

This line means whenever the bot is ready (after login) announce it in console.

```jsx
// ./index

client.on('ready', async () => {
  console.log(`Bot client Logged in as ${client.user.tag}!`);
});
```

Now after the bot is ready, we will react on all the events that discord sends whenever there's a voice activity using the line below, *(voiceStateUpdate)*

```jsx
// ./index

client.on('voiceStateUpdate', lofiCafe);
```

lofiCafe is a function that will handle this event, let's declare the function above the *voiceStateUpdate* event handler.

```jsx
const lofiCafe = async (oldMember, newMember) => {
  const guild_id = process.env.DISCORD_GUILD_ID;
	const channel_name = process.env.DISCORD_CHANNEL_NAME;
  const VOICE_URLS = process.env.VOICE_URLS.split(',')

	// find the voice channel 
  const voiceChannel = await guild.channels.cache.find(ch => ch.name === channel_name);

  let newUserChannel = newMember.channelID;
  let oldUserChannel = oldMember.channelID;

	// a function to play audio in loop
  const play = async (connection) => connection.play(
    await ytdl(_.sample(VOICE_URLS)),
    { type: 'opus', highWaterMark: 50, volume: 0.7 },
  )
  // When the song is finished, play it again.
    .on('finish', play);

  const Guild = await client.guilds.fetch(guild_id); 
  const botUserId = await client.user.id;
  const discordBotUser = await Guild.members.cache.get(botUserId); 

  if (newUserChannel === voiceChannel.id) {
    // if a user joins lo-fi music channel 

    // if bot not in voice channel and users connected to the channel
    if (!discordBotUser.voice.channel && voiceChannel.members.size > 0) {
      // play music
      voiceChannel.join()
        .then(await play)
        .catch(console.error);
    }
  } else if (oldMember && oldMember.channel && oldMember.channel.members
    && !(oldMember.channel.members.size - 1) && oldUserChannel === voiceChannel.id
    && discordBotUser.voice.channel) {
		
		// if there is only one member in the channel (bot itself)
		// leave the server after five minutes

    setTimeout(() => { 
					// wait five minutes
      if (!(oldMember.channel.members.size - 1)) { 
					// if there's still 1 member,
        oldMember.channel.leave();
      }
    }, 60000); // leave in 1 minute
  }
};
```

After writing these files, your client.js and index.js files should look exactly [like this repo](https://github.com/heyAyushh/lo-fi-discord-cafe).

## Deploy

- [Install Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli)
- Login to your heroku account in cli

    ```jsx
    heroku login
    ```

- Create a new app

    ```jsx
    heroku create
    ```

- Push your local git repository to heroku

    ```jsx
    git push heroku main
    ```

- Go into your heroku app settings and add the config vars, like you added in .env .
Just because .env file won't be pushed to GitHub.

## Enjoy 🎉

Have your friends sit and co-work in your new lo-fi cafe.

**Acknowledgements**  
icon: Cafe by Andrejs Kirma from the Noun Project  
background: Jack Berry on Unsplash