Как написать дискорд бота на javascript

Время на прочтение
12 мин

Количество просмотров 152K

Введение

В этой статье я подробно расскажу о том, как работать с библиотекой discord.js, создать своего Discord-бота, а также покажу несколько интересных и полезных команд.

Сразу хочу отметить, что я планирую сделать ряд подобных статей, начиная с простых команд, заканчивая музыкой, системой экономики и распознаванием голоса ботом.

Начало работы

Если вы уже знакомы с приведёнными ниже материалами, — смело можете пролистать этот раздел.

Установка среды разработки

Для начала работы с кодом нам нужно установить среду разработки, это может быть:

  • Sublime Text
  • Notepad++
  • Atom
  • Brackets
  • InteliJ Idea
  • Eclipse
  • Visual Studio Code

… и так далее.

Среда разработки выбирается по удобству использования и практичности, она у вас может быть любая, но мы рассмотрим её на примере Visual Studio Code, так как она является одной из самых приемлемых для новичков, а также для опытных программистов.

Для установки переходим по этой ссылке.


Выбираем свою операционную систему и запускаем скачивание.

Установка среды выполнения

Для создания бота мы используем среду выполнения node.js. Для её установки нам необходимо перейти на этот сайт.

На данный момент нас интересует версия долгосрочной поддержки (LTS), скачиваем её.

Установка полезных расширений

В Visual Studio Code присутствует возможность устанавливать расширения.
Для этого, кликните по отмеченной ниже иконке.

В открывшемся окне вписываем название название/идентификатор нужного нам расширения, после чего устанавливаем его.

Из полезных расширений могу отметить:

  1. Discord Presence — расширение, позволяющее отображать рабочую область и файл, в котором вы работаете в вашей игровой активности (функция работает только при использовании приложения Discord).

    Идентификатор расширения: icrawl.discord-vscode

  2. Code runner — расширение, с помощью которого предоставляется возможность запускать определённые фрагменты кода.
    Идентификатор расширения: formulahendry.code-runner

Создание бота

Теперь, когда вы установили все нужные компоненты, мы можем приступить к созданию самого бота.

Здесь всё просто. Переходим на портал разработчиков и нажимаем на кнопку с надписью «New Application» — она находится в правом верхнем углу.

В открывшемся окне вписываем имя бота, после чего, нажимаем на кнопку с надписью «Create».

На этой странице мы можем изменить имя бота, загрузить для него иконку, заполнить описание.

Теперь наша задача — воплотить бота в жизнь. Для этого переходим во вкладку «Bot».

Нажимаем на кнопку с надписью «Add Bot» и воплощаем бота в жизнь.

Поздравляю! Вы создали аккаунт для вашего бота. Теперь у него есть тег, токен, ник и иконка.

Подготовка к написанию кода

После создания аккаунта для бота, мы должны установить нужные пакеты и модули, чтобы в дальнейшем он корректно работал.

Первым делом создаём папку, после чего открываем её в VS Code (Файл > Открыть папку) / (Ctrl + K Ctrl + O)

Далее нам нужно открыть терминал (Терминал > Создать терминал) / (Ctrl + Shift + `)

Теперь мы должны создать файл с неким «описанием» нашего бота, сделаем это через терминал.

Вписываем данную строку в терминал и нажимаем Enter:

npm init

После каждой появившейся строки нажимаем Enter или вписываем свои значения.
Значения в этом файле можно будет изменить в любой момент.

Далее, мы должны поочерёдно вводить в терминал эти строки:

npm install

npm install discord.js

«Install» также можно сокращать в «I», но необязательно.

Итого, если вы следовали инструкциям и всё сделали правильно, в вашей папке должны были появиться 3 объекта:

Написание кода

Об удобстве написания кода

Для того, чтобы наш бот появился в сети и мог реагировать на команды, нам нужно написать для него код.

Существует множество вариантов для его написания: используя один файл, два, несколько, и т.д

Мы рассмотрим вариант с двумя файлами, так как его использовать очень легко и удобно, но у каждого варианта есть свои недостатки — например, у этого недостатком является сложность в написании начального кода.

Но не волнуйтесь, весь код вам писать не придётся.

О хранении данных

Для начала, нам нужно где-то хранить основные параметры и информацию о боте.

Мы можем сделать это двумя способами:

  1. Создать отдельный файл
  2. Записать всё в константы

Я не советую вам использовать второй вариант, так как в будущем вам придётся работать с большим объёмом информации, и такая запись будет доставлять неудобства.

Разберём хранение параметров в отдельном файле.

Итак, создаем файл config.json

Вставляем в него следующий код:

{
    "token" : "Ваш_токен",
    "prefix" : "Ваш_префикс"
}

* Для получения токена зайдите на портал разработчиков, перейдите во вкладку «Bot» и скопируйте его.

* Самым распространённым среди разработчиков префиксом является !

Далее нам нужно создать файл bot.js и вставить в него данный код:

const Discord = require('discord.js'); // Подключаем библиотеку discord.js
const robot = new Discord.Client(); // Объявляем, что robot - бот
const comms = require("./comms.js"); // Подключаем файл с командами для бота
const fs = require('fs'); // Подключаем родной модуль файловой системы node.js  
let config = require('./config.json'); // Подключаем файл с параметрами и информацией
let token = config.token; // «Вытаскиваем» из него токен
let prefix = config.prefix; // «Вытаскиваем» из него префикс

robot.on("ready", function() {
  /* При успешном запуске, в консоли появится сообщение «[Имя бота] запустился!» */
  console.log(robot.user.username + " запустился!");
});


robot.on('message', (msg) => { // Реагирование на сообщения
  if (msg.author.username != robot.user.username && msg.author.discriminator != robot.user.discriminator) {
    var comm = msg.content.trim() + " ";
    var comm_name = comm.slice(0, comm.indexOf(" "));
    var messArr = comm.split(" ");
    for (comm_count in comms.comms) {
      var comm2 = prefix + comms.comms[comm_count].name;
      if (comm2 == comm_name) {
        comms.comms[comm_count].out(robot, msg, messArr);
      }
    }
  }
});


robot.login(token); // Авторизация бота

Теперь создаём файл comms.js, в нём будут сами команды.

В нём должен быть следующий код:

const config = require('./config.json'); // Подключаем файл с параметрами и информацией
const Discord = require('discord.js'); // Подключаем библиотеку discord.js
const prefix = config.prefix; // «Вытаскиваем» префикс

// Команды //

function test(robot, mess, args) {
  mess.channel.send('Test!')
}


// Список команд //

var comms_list = [{
  name: "test",
  out: test,
  about: "Тестовая команда"
}];

// Name - название команды, на которую будет реагировать бот
// Out - название функции с командой
// About - описание команды 

module.exports.comms = comms_list;

Чтобы добавить больше команд — просто объявляйте больше функций и добавляйте их в список, например:

const config = require('./config.json');
const Discord = require('discord.js');
const prefix = config.prefix;
const versions = config.versions;


// Команды //

function test(robot, mess, args) {
  mess.channel.send("Тест!")
}

function hello(robot, mess, args) {
  mess.reply("Привет!")
}


// Список комманд //

var comms_list = [{
    name: "test",
    out: test,
    about: "Тестовая команда"
  },
  {
    name: "hello",
    out: hello,
    about: "Команда для приветствия!"
  }
}

module.exports.comms = comms_list;

И вот, мы вышли на финишную прямую!

Осталось всего ничего — запустить бота.

Для этого открываем терминал и вставляем в него следующую строку:

node bot.js

Готово! Бот запущен и вы можете им пользоваться, ура!

Чтобы пригласить бота на свой сервер, воспользуемся нам уже известным порталом разработчиков.

Перейдём во вкладку OAuth2, пролистаем чуть ниже, выберем «Bot» и отметим нужные боту привилегии.

Теперь осталось скопировать ссылку-приглашение и добавить бота на свой сервер.

Как вывести ссылку-приглашение в терминал, при запуске бота?

Существует два способа:

  1. Заранее отметить нужные привилегии.

    Для этого, сначала мы должны скопировать ссылку-приглашение.
    После чего перейти в файл bot.js и вставить данную строчку кода сюда:

    
    robot.on("ready", function(){
        console.log(robot.user.username + " запустился!");
        console.log("Ссылка-приглашение")  // << //
    })
    

    Итоговый код должен быть таким:

    
    const Discord = require('discord.js'); 
    const robot = new Discord.Client();
    var comms = require("./comms.js");
    const fs = require('fs');
    let config = require('./config.json');
    let token = config.token;
    let prefix = config.prefix; 
    
    robot.on("ready", function(){
        console.log(robot.user.username + " запустился!");
        console.log("Ссылка-приглашение")
    })
    
    
    robot.on('message', (msg) => {
    	if(msg.author.username != robot.user.username && msg.author.discriminator != robot.user.discriminator){
        	var comm = msg.content.trim()+" ";
    	    var ok = false;
    	    var comm_name = comm.slice(0, comm.indexOf(" "));
    	    var messArr = comm.split(" ");
    	    for(comm_count in comms.comms){
    	    	var comm2 = prefix + comms.comms[comm_count].name;
    	    	if(comm2 == comm_name){
    	    		comms.comms[comm_count].out(robot, msg, messArr);
    	    	}
    	    }
        } 
    });
    
    robot.login(token)
    
    
    
      
    
    robot.login(token);
    

  2. Отметить нужные привилегии в самом коде.

    Повторяем процедуры из первого способа, но уже с другими строками кода:

    
    robot.on("ready", function(){
        console.log(robot.user.username + " запустился!");
        robot.generateInvite(["ADMINISTRATOR"]).then((link) => { // < //
            console.log(link); // < //
    })})
    

    Итоговый код:

    
    const Discord = require('discord.js'); 
    const robot = new Discord.Client();
    var comms = require("./comms.js");
    const fs = require('fs');
    let config = require('./config.json');
    let token = config.token;
    let prefix = config.prefix;
    
    robot.on("ready", function(){
        console.log(robot.user.username + " запустился!");
        robot.generateInvite(["ADMINISTRATOR"]).then((link) => { 
            console.log(link);
    })})
    
    
    robot.on('message', (msg) => {
    	if(msg.author.username != robot.user.username && msg.author.discriminator != robot.user.discriminator){
        	var comm = msg.content.trim()+" ";
    	    var ok = false;
    	    var comm_name = comm.slice(0, comm.indexOf(" "));
    	    var messArr = comm.split(" ");
    	    for(comm_count in comms.comms){
    	    	var comm2 = prefix + comms.comms[comm_count].name;
    	    	if(comm2 == comm_name){
    	    		comms.comms[comm_count].out(robot, msg, messArr);
    	    	}
    	    }
        } 
    }); 
    
    
    
      
    
    robot.login(token);
    

    Чтобы указать несколько привилегий, мы должны перечислить их в квадратных скобках, через запятую:

    
        robot.generateInvite(['KICK_MEMBERS', 'BAN_MEMBERS', 'SEND_MESSAGES']).then((link) => { 
            console.log(link);
    

    * Все привилегии указываются заглавными буквами

    Список доступных привилегий:

    ADMINISTRATOR
    CREATE_INSTANT_INVITE
    KICK_MEMBERS
    BAN_MEMBERS
    MANAGE_CHANNELS
    MANAGE_GUILD
    ADD_REACTIONS
    VIEW_AUDIT_LOG
    PRIORITY_SPEAKER
    STREAM
    VIEW_CHANNEL
    SEND_MESSAGES
    SEND_TTS_MESSAGES
    MANAGE_MESSAGES
    EMBED_LINKS
    ATTACH_FILES
    READ_MESSAGE_HISTORY
    MENTION_EVERYONE
    USE_EXTERNAL_EMOJIS
    VIEW_GUILD_INSIGHTS
    CONNECT
    SPEAK
    MUTE_MEMBERS
    DEAFEN_MEMBERS
    MOVE_MEMBERS
    USE_VAD
    CHANGE_NICKNAME
    MANAGE_NICKNAMES
    MANAGE_ROLES
    MANAGE_WEBHOOKS
    MANAGE_EMOJIS

    Я не советую вам из привилегий выбирать только ADMINISTRATOR, поэтому лучше указать только те привилегии, которые бот действительно использует для корректной работы

Полезные и интересные команды

В предыдущем разделе я показал вам, как запустить бота и как писать для него команды.
Теперь я хочу поделиться с вами несколькими своими командами.

  1. !say — с помощью этой команды бот может повторить ваше сообщение.

    Код:

    if (!mess.member.hasPermission("MANAGE_MESSAGES")) return mess.channel.send("У  вас нет прав"); /* Если у исполнителя команды нету привилегии MANGAGE_MESSAGES, он не сможет её использовать */
    
    args = mess.content.split(' ');
    args.shift();
    args = args.join(' ');
    
    mess.delete().catch(); // Удаление сообщения пользователя после отправки 
    
    mess.channel.send(args)
    

  2. !heads_or_tails — игра «Орёл или Решка».

    Код:

    mess.channel.send('Монета подбрасывается...')
    
    var random = Math.floor(Math.random() * 4) + 1; // Объявление переменной random - она вычисляет случайное число от 1 до 3
    
    if (random === 1) { // Если вычислено число 1, то выпадает орёл.
        mess.channel.send(':full_moon: Орёл!')
    } else if (random === 2) { // Если вычислено число 2, то выпадает решка.
        mess.channel.send(':new_moon: Решка!')
    } else if (random === 3) { // Если вычислено число 3, то монета падает ребром.
        mess.channel.send(':last_quarter_moon: Монета упала ребром!')
    }
    

  3. !clear — удаление определённого количества сообщений.

    Код:

    const arggs = mess.content.split(' ').slice(1); // Все аргументы за именем команды с префиксом
    const amount = arggs.join(' '); // Количество сообщений, которые должны быть удалены
    if (!amount) return mess.channel.send('Вы не указали, сколько сообщений нужно удалить!'); // Проверка, задан ли параметр количества
    if (isNaN(amount)) return mess.channel.send('Это не число!'); // Проверка, является ли числом ввод пользователя 
    
    if (amount > 100) return mess.channel.send('Вы не можете удалить 100 сообщений за раз'); // Проверка, является ли ввод пользователя числом больше 100
    if (amount < 1) return mess.channel.send('Вы должны ввести число больше чем 1'); // Проверка, является ли ввод пользователя числом меньше 1
    
    async function delete_messages() { // Объявление асинхронной функции
    
        await mess.channel.messages.fetch({
            limit: amount
        }).then(messages => {
            mess.channel.bulkDelete(messages)
            mess.channel.send(`Удалено ${amount} сообщений!`)
        })
    };
    delete_messages(); // Вызов асинхронной функции
    
  4. !random_name — генерация случайного имени.

    Не стоит пугаться большого кода, здесь всё предельно просто.

    Код:

    var name = [ // Объявление массива name и занесение в него большого количества имён
      'Абрам', ' Аваз', ' Аввакум', ' Август', ' Августин',
      ' Авдей', ' Авраам', ' Автандил', ' Агап', ' Агафон',
      ' Аггей', ' Адам', ' Адис', ' Адольф', ' Адриан',
      ' Азамат', ' Айдар', ' Айнур', ' Айрат', ' Аким',
      ' Алан', ' Алей', ' Александр', ' Алексей', ' Али',
      ' Альберт', ' Альфред', ' Амадей', ' Амадеус',
      ' Амаяк', ' Амвросий', ' Ананий', ' Анастасий',
      ' Анатолий', ' Анвар', ' Ангел', ' Андоим', ' Андрей',
      ' Аникита', ' Антон', ' Арам', ' Арий', ' Аристарх',
      ' Аркадий', ' Арман', ' Арно', ' Арнольд', ' Арон', ' Арсен',
      ' Арсений', ' Арслан', ' Артем', ' Артемий', ' Артур', ' Архип', ' Аскар', ' Аскольд', ' Аслан', ' Афанасий', ' Ахмет', ' Ашот', ' Бальтазар', ' Бежен', ' Бенедикт', ' Берек', ' Бернард',
      ' Бертран', ' Богдан', ' Болеслав', ' Борис', ' Бронислав',
      ' Булат', ' Вадим', ' Валентин', ' Валерий', ' Вальтер',
      ' Варфоломей', ' Василий', ' Вацлав', ' Велизар', ' Венедикт', ' Вениамин', ' Викентий', ' Виктор', ' Вилли', ' Вильгельм', ' Виссарион', ' Виталий', ' Витольд', ' Владимир', ' Владислав', ' Владлен', ' Володар', ' Вольдемар', ' Всеволод', ' Вячеслав', ' Гавриил', ' Галактион', ' Гарри', ' Гастон', ' Гаяс', ' Гевор', ' Геннадий', ' Генрих', ' Георгий', ' Геракл', ' Геральд', ' Герасим', ' Герман', ' Глеб', ' Гордей', ' Гордон', ' Горислав', ' Градимир', ' Григорий', ' Гурий', ' Густав', ' Давид', ' Дамир', ' Даниил', ' Даниэль', ' Данияр', ' Дарий', ' Дементий', ' Демид', ' Демосфен', ' Демьян', ' Денис', ' Джамал', ' Джордан', ' Дмитрий', ' Добрыня', ' Дональд', ' Донат', ' Дорофей', ' Евгений', ' Евграф', ' Евдоким', ' Евсевий', ' Евсей', ' Евстафий', ' Егор', ' Елеазар', ' Елисей', ' Емельян', ' Еремей', ' Ермолай', ' Ерофей', ' Ефим', ' Ефрем', ' Жан', ' Ждан', ' Жорж', ' Захар', ' Зиновий', ' Ибрагим', ' Иван', ' Игнатий', ' Игорь', ' Илларион', ' Ильдар', ' Ильнар', ' Ильнур', ' Илья', ' Ильяс', ' Иннокентий', ' Иоанн', ' Иосиф', ' Ипполит', ' Искандер', ' Ислам', ' Камиль', ' Карим', ' Карл', ' Кирилл', ' Клим', ' Кондрат', ' Константин', ' Корней', ' Кузьма', ' Лавр', ' Лаврентий', ' Лев', ' Леон', ' Леонид', ' Леонтий', ' Леопольд', ' Лука', ' Лукьян', ' Любим', ' Макар', ' Максим', ' Максимилиан', ' Марат', ' Марк', ' Марсель', ' Мартин', ' Матвей', ' Мирон', ' Мирослав', ' Митрофан', ' Михаил', ' Михей', ' Мишель', ' Мстислав', ' Мурат', ' Муслим', ' Назар', 'Абрам', ' Аваз', ' Аввакум', ' Август', ' Августин', ' Авдей', ' Авраам', ' Автандил', ' Агап', ' Агафон', ' Аггей', ' Адам', ' Адис', ' Адольф', ' Адриан', ' Азамат', ' Айдар', ' Айнур', ' Айрат', ' Аким', ' Алан', ' Алей', ' Александр',
      ' Алексей', ' Али', ' Альберт', ' Альфред', ' Амадей', ' Амадеус', ' Амаяк', ' Амвросий', ' Ананий', ' Анастасий', ' Анатолий', ' Анвар', ' Ангел', ' Андоим', ' Андрей', ' Аникита', ' Антон', ' Арам', ' Арий', ' Аристарх', ' Аркадий', ' Арман', ' Арно', ' Арнольд', ' Арон', ' Арсен', ' Арсений', ' Арслан', ' Артем', ' Артемий', ' Артур', ' Архип', ' Аскар', ' Аскольд', ' Аслан', ' Афанасий', ' Ахмет', ' Ашот', ' Бальтазар', ' Бежен', ' Бенедикт', ' Берек', ' Бернард', ' Бертран', ' Богдан', ' Болеслав', ' Борис', ' Бронислав', ' Булат', ' Вадим', ' Валентин', ' Валерий', ' Вальтер', ' Варфоломей', ' Василий', ' Вацлав', ' Велизар', ' Венедикт', ' Вениамин', ' Викентий', ' Виктор', ' Вилли', ' Вильгельм', ' Виссарион', ' Виталий', ' Витольд', ' Владимир', ' Владислав', ' Владлен', ' Володар', ' Вольдемар', ' Всеволод', ' Вячеслав', ' Гавриил', ' Галактион', ' Гарри', ' Гастон',
      ' Гаяс', ' Гевор', ' Геннадий', ' Генрих', ' Георгий', ' Геракл',
      ' Геральд', ' Герасим', ' Герман', ' Глеб', ' Гордей', ' Гордон',
      ' Горислав', ' Градимир', ' Григорий', ' Гурий', ' Густав',
      ' Давид', ' Дамир', ' Даниил', ' Даниэль', ' Данияр',
      ' Дарий', ' Дементий', ' Демид', ' Демосфен',
      ' Демьян', ' Денис', ' Джамал', ' Джордан', ' Дмитрий', ' Добрыня',
      ' Дональд', ' Донат', ' Дорофей', ' Евгений', ' Евграф', ' Евдоким', ' Евсевий', ' Евсей', ' Евстафий', ' Егор', ' Елеазар', ' Елисей', ' Емельян', ' Еремей', ' Ермолай', ' Ерофей', ' Ефим', ' Ефрем', ' Жан', ' Ждан', ' Жорж', ' Захар', ' Зиновий', ' Ибрагим', ' Иван', ' Игнатий', ' Игорь', ' Илларион', ' Ильдар', ' Ильнар', ' Ильнур', ' Илья', ' Ильяс', ' Иннокентий', ' Иоанн', ' Иосиф', ' Ипполит', ' Искандер', ' Ислам', ' Камиль', ' Карим', ' Карл', ' Кирилл', ' Клим', ' Кондрат', ' Константин', ' Корней', ' Кузьма', ' Лавр', ' Лаврентий', ' Лев', ' Леон', ' Леонид', ' Леонтий', ' Леопольд', ' Лука', ' Лукьян', ' Любим', ' Макар', ' Максим', ' Максимилиан', ' Марат', ' Марк', ' Марсель', ' Мартин', ' Матвей', ' Мирон', ' Мирослав', ' Митрофан', ' Михаил', ' Михей', ' Мишель', ' Мстислав', ' Мурат',
      ' Муслим', ' Назар'
    ];
    
    var RandElement = name[Math.floor(Math.random() * (name.length))]; // Выбор случайного элемента из массива
    mess.channel.send(RandElement) // Отправка сообщения со случайным элементом из массива в чат
    

Заключение

Вот и подошла к концу первая часть обучения, как вы могли заметить, создать бота, используя библиотеку discord.js очень просто.

Итого, из этой статьи мы выяснили:

  • Как установить нужные модули и пакеты
  • Как установить среду разработки
  • Как установить среду выполнения
  • Как установить полезные расширения
  • Как создать аккаунт для бота
  • Как воплотить бота в жизнь
  • Как запустить бота
  • Как научить бота реагировать на команды
  • Как пригласить бота на свой сервер
  • Как писать код для работы команд

А также научились некоторым интересным и полезным командам.

Надеюсь, что вам понравилась моя статья и вы узнали из неё что-то новое.

Сайты для самостоятельного изучения

  • Основная документация discord.js
  • Документация discord.js №2
  • Руководство discord.js
  • Руководство discord.js №2

⛔ DEPRECATED

discordbotstut

Начнём. Ссылка на мой youtube канал.

Discord bot туториал. Туториал по созданию ботов для дискорда на node.js используя discord.js.

Creation date : 06.12.2019
Также отдельное спасибо Top Bots List и его создателю Angrymoyse#0444 за помощь в написании.

Установка node.js.

Давайте начнём создание бота. Если у вас установлена node.js, то пропустите сделающие 2 строчки.
Заходим на сайт node.js, скачиваем, устанавливаем. Скриншотов процесса установки нету, тк переустанавливать node.js нету желания. Но там всё интуитивно понятно.

Создание файлов, инициализация проекта, установка библиотек.

Создаём папку bot. Желательно не использовать кирилицу, юникод и т. п. в названии.
Сразу же создаём файл index.js или bot.js. Это не несёт особого смысла. Можно назвать как угодно, но принятно index.js / bot.js.
Это будет главный файл бота, т.е. первым запускается, в нём основной код бота.
Далее открываем консоль / терминал если у вас linux.
Для быстрого открытия консоли на windows можно нажать WIN + R, ввести cmd.
Далее переходим в папку бота, думаю как это сделать через консоль всем понятно. Пишим :
npm init — инициализация проекта.
Жмём enter до конца. Если ошибка в package name, то напишите bot.
npm i discord.js — установка библиотеки discord.js.

Редакторы кода.

Далее рекомендую установить один из следующих редакторов кода :

Atom.
VScode.
WebStorm (спасибо за подсказку Mice V 4.4.4#0444 )

Если очень слабый компьюер можете поставить notepad++, но это для постоянной основы не самый хороший вариант.
Лично я использую Atom.

Аккаунт бота.

Вы можете зарегистрировать его на сайте discord developers.
Жмём кнопку «New Application». Вводим название бота. Жмём «Create».
Переходим во вкладку «Bot», нажимаем «Add Bot», затем «Yes, do it!»
Находим строку «token», немного ниже есть кнопка «Copy», нажимаем. Теперь в вашем буфере обмена есть токен бота.

Код.

Начало.

Создадим первый код. Пишем :

const Discord = require("discord.js"); //Подключаем discord.js для дальнейшего использования.
const client = new Discord.Client(); 
client.login("token"); //Где token пишем токен бота.
Запуск.

Открываем консоль, переходим в папку проекта и пишем :

node название-файла-с-кодом.js

в зависимости от названия файла.
Если у вас windows, то вы можете создать файл start.bat с текстом

node название-файла-с-кодом.js
pause

Если линукс, то вы можете создать файл start.sh

node название-файла-с-кодом.js

Это будет запускать бота. Далее я не буду говорить про запуск. Делайте это сами.

Конфиг.

Создаем файл config.json с конфигурацией нашего бота.

{
"version" : "1.0", 
"prefix" : "!"
}

В начале кода бота напишем :

const config = require("./config.json");

Еще вы можете создать конфиг прямо в коде бота.

let config ={ 
"version" : "1.0",
"prefix" : "!" 
}

Но второй вариант крайне не рекомендуется использовать, ведь для того что-бы изменить конфиг бота нам придется изменять его код.

Реагирование на сообщение.

Теперь давайте делать что-то когда приходит новое сообщение.
Например логировать его текст.

client.on("message", message => { //Пришло сообщение.
console.log(message.content); //console.log логирует в консоль, message - объект сообщения, message.content - строка объекта с текстом сообщения.
})

Получение информации о авторе сообщения (отправителе).

Давайте залогируем тег автора.

client.on("message", message => { //Пришло сообщение.
console.log(message.author.tag); //message.author.tag содержит в себе тег автора.
})

Команда !ping

Давайте в ответ на сообщение !ping отправлять такое сообщение : «@user, мой пинг равен » далее пинг.

client.on("message", message => { //Пришло сообщение.
if(message.content.toLowerCase()==config.prefix + "ping") //Если текст сообщения равен префиксу плюс ping, то происходит код в {} Часть кода .toLowerCase() превращает текст в строчный. (Делает из заглавных букв обычные.) 
{
message.reply("мой пинг равен " + client.ping) //message.reply отвечает на сообщение.
//Также можно использовать message.channel.send(message.author + ", мой пинг равен " + client.ping);
}
})

Также можно писать не

if(message.content.toLowerCase()==config.prefix + "ping")

А

if(message.content.toLowerCase().startsWith(config.prefix + "ping"))

.startsWith проверят начинается ли строка с символов в аргументах.

Об отправке сообщений.

Теперь рассмотрим message.channel.send();
Когда я только начинал программировать я не понимал смысл этой фразы, но сейчас понимаю и могу рассказать вам. message — объект сообщения, в нём есть channel — канал в который было отправлено, то есть с помощью message.channel мы получаем канал, а .send() отправляет туда сообщение.

client.on("message", message => { //Пришло сообщение.
if(message.content.toLowerCase()==config.prefix + "test")
{
message.channel.send("I am working now!");
}
})

Также можно отправлять сообщение по ID канала.
Делается это так :

//some code...
client.channels.get('ID канала').send("Hi!");

client.channels — все каналы которые есть на серверах с ботом.
.get(‘ID’) получает канал из них по ID.
.send(«Text»); Отправляет сообщение.
ID канала можно получить используя devepoer mode

Eval.

Также даже начинающим программистам будет очень полезна в боте команда !eval для выполнения кода не пиша его в коде бота, т.е. вы пишите !eval какой-то код и бот выполняет этот код.
Я нашёл хороший туториал по этой команде на github. Рекомендую ознакомиться и взять себе команду в код бота. Принцип её работы мы разберём позже. Тык.

RichEmbed.

Пример.

Думаю вы все видели как боты отправляют сообщения такого типа.

Image alt

Это называется RichEmbed (Embed).
Давайте отправим простой эмбед похожий на данный. (Картинка ниже)

Image alt

Команда.

Для этого создадим новую команду !ping.

client.on("message", message => { //Пришло сообщение.
if(message.content.toLowerCase()==config.prefix + "ping") //Выше было
{
let embed = new Discord.RichEmbed() //Создаём новый эмбед.
.setTitle('Пинг бота.') //Устанавливаем заголовок.
.setColor(`GREEN`) //Цвет зелёный. Можно указать hex.
.setDescription("Пинг : " + client.ping); //Устанавливаем описание.
message.channel.send(embed); //Отправляем.
}
})
Параметры.

В Embed есть много различных параметров, вы можете прочесть их далее, либо посмотреть на оффициальном сайте discord.js

embed.setColor("Цвет в hex или один из встроенных."); // Устанавливает цвет боковой полосы.
embed.setDescription("Описание") //Устанавливает описание.
embed.serFooter("Подпись") //Устанавливает подпись мелким шрифтом под эмбедом.
embed.setThumbnail("url") //Миниатюра эмбеда.
embed.setAuthor("Имя", "Url") //Устанавливает автора.
embed.addField("Заголовок", "Текст") //Добавляет поле.
embed.setImage("URL") //Добавляет картинку.
Пример.

Команда !avatar.

client.on("message", message => { //Пришло сообщение.
if(message.content.toLowerCase().startsWith(config.prefix + "avatar")) //Выше было
{
let mb = message.mentions.members.first() || message.member; // Если есть упомянание человека в сообщении, то берём его, если нету, то себя. Расскажу чуть позже.
let color = mb.displayHexColor; //Цвет самой высокой роли человека, если цвет невидимый то самой высокой отображаемой роли.
if (color == '#000000') color = mb.hoistRole.hexColor;//Цвет самой высокой роли человека.
let embed = new Discord.RichEmbed() //Создаём эмбед
.setImage(mb.user.avatarURL) //Устанавливаем картинку - аватар человека.
.setColor(color) //Цвет.
.setFooter("Аватар пользователя " + mb.user.tag); //Устанавливаем в подпись чей это аватар.
message.channel.send({embed}); //Отправляем.
}
})

Вышло так

Image alt

Команда !userinfo.

Давайте сделаем команду для получения информации о пользователе. Команда взята из моего бота.
Будем использовать библиотеку moment.js, устанавливаем npm i moment.js

const status = { //Создадим переменную со статусами чтобы они были не английском.
  "online": "Онлайн.",
  "idle": "Не на месте.",
  "dnd": "Не беспокоить.",
  "offline": "Оффлайн."
}

let mbr = message.mentions.members.first() || message.member; //Если есть упомянание, то mbr = тот кого упомянули, если нету то автору сообщения.
      if (mbr){ //Если всё ок.
      let embed = new Discord.RichEmbed() //Создаём эмбед
      .setAuthor(mbr.user.tag, mbr.user.avatarURL) //Устанавливаем автора
      .setColor(`GREEN`) //Цвет зелёный
      .setTitle("Тег") //Устанавливаем заголовок
      .setDescription(mbr.user.tag) //Описание - тег юзера.
      .addField("ID",  mbr.user.id) //Первое поле - айди автора.
      .addField("Никнейм",  mbr.nickname !== null ? mbr.nickname : "No nickname") //Второе поле - никнейм (НЕ ПУТАТЬ С НИКОМ И ТЕГОМ)!
      .addField("Статус", status[mbr.user.presence.status]) //Статус человека
      .addField("Играет в ", mbr.user.presence.game ? mbr.user.presence.game.name : "Ничего") //Во что играет
      .addField("Присоединился", moment(mbr.joinedAt).format('MMMM Do YYYY h:mm:ss')) //Когда зашёл на сервер
      .addField("Аккаунт создан", mbr.user.createdAt.toLocaleString()) //Когда создан аккаунт
      .addField("Роли на сервере", mbr.roles.filter(r => r.id !== message.guild.id).map(roles => ``${roles.name}``).join(" **|** ") || "No Roles") //Роли человека на сервере
      .setThumbnail(mbr.user.displayAvatarURL) //Аватар человека
      .setFooter("Информация о пользователе.") //Футер
      message.channel.send({embed}); //Отправляем
}
else message.reply("Вы забыли упомянуть пользователя."); //Это вряд-ли сможет произойти, но на всякий случай

Вышло так.

Image alt

Мой дискорд сервер!

Прошу зайти на мой дискорд сервер, ведь я долго делал туториал, а вам не сложно зайти на мой сервер в виде благодарности.

В разработке..

Как создать бота Discord с Node.js, Discord.js и OpenAI GPT-3

В настоящее время ИИ набирает стремительные темпы развития, и многие разработчики начинают задействовать его в создании проектов. Однако обучение собственного ИИ может оказаться непростой задачей для новичков в этой области.

Фотомонтаж, созданный искусственным интеллектом (ИИ): робот преследует кричащего человека

К счастью, в последние годы работать с ИИ стало намного проще: все благодаря таким компаниям, как OpenAI, которые публикуют API для взаимодействия с предварительно обученными крупными нейронными сетями.

В данном руководстве мы создадим гениального бота Discord, который сможет отвечать на сложные вопросы и выполнять требуемые задания. Для этой цели воспользуемся Node.js, Discord.js и OpenAI API для GPT-3, одной из самых крупных и умных обученных нейронных сетей.  

Переходим от слов к делу и погружаемся в увлекательную работу с ИИ. 

Требования к проекту 

Для создания проекта потребуются пара аккаунтов и установка нужного ПО. 

Аккаунты:

  • бета-аккаунт OpenAI (регистрация по ссылке); 
  • аккаунт Discord (скачивание и регистрация по ссылке). 

Установка ПО:

  • Node.js (скачивание и установка по ссылке); 
  • VS Code (скачивание и установка по ссылке), если отсутствует редактор кода. 

Подготовка Discord

Шаг 1. Вход в Discord и создание сервера 

Данный этап касается тех, у кого нет сервера. Обратите внимание, вы должны иметь собственный сервер или знать кого-то с правом на добавление аккаунта бота на дальнейших этапах. Создаем новый сервер, нажимая на значок + в левом боковом меню. 

Шаг 2. Добавление нового приложения разработчика 

Переходим по ссылке https://discord.com/developers/applications, в верхнем правом углу нажимаем кнопку New Application и создаем новое приложение:

Добавление нового приложения разработчика путем нажатия на кнопку New Application в правом верхнем углу 

Шаг 3. Именование приложения

Выбираем имя AiBot и нажимаем Create:

Именование приложения путем нажатия на Create

Шаг 4. Создание бота 

Переходим в раздел Bot в левом боковом меню и нажимаем Add bot в правой части экрана:

Раздел Bot для приложения 
Добавление бота путем нажатия на кнопку 

Шаг 5. Создание токена бота 

Нажимаем на кнопку сброса Reset token для создания нового токена бота. Данный токен является конфиденциальной информацией и не допускает разглашения. Сохраняем его в текстовом файле для дальнейшего использования, поскольку он отображается только один раз. 

Шаг 6. Установка области действия бота и выбор разрешений 

В меню настроек переходим в раздел OAuth2 >URL Generator

Раздел OAuth2 > URL Generator

Устанавливаем область действия на bot и выбираем следующие разрешения: Read messages/View channels (чтение сообщений/просмотр каналов), Send messages (отправка сообщений). Благодаря таким настройкам бот сможет читать и писать сообщения в чате сервера:

Установка области действия на bot
Выбор разрешений, позволяющих боту читать и писать сообщения в чате 

Шаг 7. Копирование URL-приглашения и вставка его в браузер 

Прокручиваем вниз и находим Generated URL (сгенерированный URL-адрес). Он выглядит следующим образом:

https://discord.com/api/oauth2/authorize?client_id={YOUR_CLIENT_ID}&permissions=3072&scope=bot

Вставляем этот URL в адресную строку браузера. Выбираем сервер, предназначенный для авторизации бота, и нажимаем Next или Weiter:

Авторизация бота на сервере 

Принимаем необходимые разрешения и завершаем процедуру нажатием Authorize

Шаг 8. Встреча с созданным ботом на сервере

Закрываем вкладку и возвращаемся на сервер. Если все сделано правильно, то бот появляется среди участников сервера:

Бот на сервере

Активация бота ИИ 

Теперь, когда бот отображается на сервере, приведем его в действие с помощью кода. 

Шаг 9. Инициализация нового проекта 

Выбираем место на компьютере, создаем там новую папку и называем ее aiBot. В данном случае папка на рабочем столе:

Новая папка для хранения кода 

Открываем приложение VSCode и вновь созданную папку в разделе File > Open Folder:

Открытие папки в редакторе кода 

В строке меню в разделе Terminal > New Terminal открываем новый терминал, который появляется снизу. 

В терминале с помощью следующей команды инициализируем новое приложение Node.js: 

npm init -y

Инициализация нового приложения Node.js

Нажимаем Enter. В файловом проводнике слева видим результат выполнения команды  —  создание нового файла package.json:

Новый файл package.json

Шаг 10. Создание нового файла с кодом для бота 

Редактируем файл package.json, чтобы при запуске выполнялся скрипт файла с кодом для бота. 

Нажимаем на значок New File для создания нового скрипта Node. Присваиваем файлу имя bot.js и пишем в нем код по типу “Hello world”, после чего сохраняем:  

Новый файл с именем bot.js и кодом по типу Hello world

Далее переходим к файлу package.json и редактируем его, а именно вносим изменения в строки с main и start, как показано на скриншоте: 

Теперь выполняем команду: 

npm start

В терминале выводится сообщение Hello AI bot!:

Выполнение команды выводит в терминале сообщение Hello AI bot!

Шаг 11. Установка зависимостей Discord.js 

Мы сделали все необходимое для выполнения скрипта bot.js, приступаем к установке библиотеки Discord.js для взаимодействия с Discord.

В терминале выполняем команду: 

npm install discord.js

Установка библиотеки Discord.js

Данная команда устанавливает библиотеку Discord.js, которая упрощает взаимодействие с API Discord. Если вы получаете только предупреждения, то проблем быть не должно. Однако в случае возникновения ошибок следует поискать решения в интернете. 

Шаг 12. Написание кода для активации бота 

Открываем файл bot.js, в котором пишем следующий код: 

//В bot.js
const token = <"YOUR_SAVED_BOT_TOKEN">; //Токен, сохраненный на 5-м шаге данного руководства
const {Client, Intents} = require("discord.js");
const client = new Client({
intents:[
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES
]
});
client.on("ready", () =>{
console.log("The AI bot is online"); //Сообщение, когда бот в сети
});
client.login(token);

Заменяем <YOUR_SAVED_BOT_TOKEN> на токен, сохраненный для дальнейшей работы на 5-ом шаге руководства, и заключаем его в кавычки. Далее сохраняем файл. 

Токен не подлежит разглашению, поэтому не следует отправлять код для данного проекта прямо на GitHub. Можно воспользоваться пакетом dotenv в сочетании с файлом .gitignore и таким образом безопасно сохранить токен. В этом же руководстве больше хотелось сосредоточиться на простоте процесса, чем на IT-безопасности.

Шаг 13. Бот активирован

В терминале выполняем следующую команду и смотрим на сервер: в сети должен появиться бот. 

npm start

Устранение ошибок. При получении сообщения об ошибке Error: Cannot find module ‘node:events (Ошибка: Не удается найти модуль ‘node:events) убедитесь, что установленная версия Node.js новее, чем 16.6.0. Узнать текущую версию Node можно с помощью команды:

node -v

Если же ваша версия предшествует 16.6.0, перейдите на сайт Node.js и установите поновее. Вы всегда можете закрыть команду, которая зависла в терминале с помощью: 

[Ctrl + C] (на Windows) или [Cmd + C] на MacOS

Пробуем перезапустить команду npm start и снова проверяем сервер Discord. Бот AiBot должен появиться в сети! 

Ура! Бот AiBot в сети 😀

Шаг 14. Обеспечение бота кодом для ответов на сообщения на сервере 

Редактируем файл bot.js, снабжая его кодом для ответа на сообщения, содержащие восклицательный знак ! в качестве первого символа:

//В bot.js
const token = <"YOUR_SAVED_BOT_TOKEN">; //Токен, сохраненный на 5-м шаге данного руководства
const {Client, Intents} = require("discord.js");
const client = new Client({
intents:[
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES
]
});
client.on("ready", () =>{
console.log("The AI bot is online"); //Сообщение, когда бот в сети
});
client.on("message", (message) => {
if (message.content.substring(0, 1) === "!") {
message.channel.send("Hello from AI bot"); //Ответ на сообщение, если оно содержит "!" в качестве первого символа
}
});
client.login(token);

Сохраняем изменения. Перезапускаем приложение, нажимая в терминале Ctrl + C и снова выполняя команду npm start.

Отправляем на сервер сообщение с восклицательным знаком в качестве первого символа. В ответ бот AiBot реагирует приветственной фразой Hello from AI bot. Он не будет отвечать на сообщения, не соответствующие заданному формату:

Ответ бота на сообщение с ! в начале фразы

Подготовка OpenAI GPT-3

Созданный бот отвечает на сообщения, теперь добавим ему интеллекта. Для этого необходимо получить токен с сайта OpenAI. 

Шаг 15. Получение токена OpenAI API 

Переходим по ссылке https://beta.openai.com/account/api-keys. На момент создания руководства сервис GPT-3 все еще находился на этапе бета-тестирования. Возможно, сейчас вышеуказанный URL уже изменился. В этом случае нужно войти в свой аккаунт OpenAI, перейти в раздел Personal в правом верхнем углу веб-сайта, нажать на Personal и выбрать опцию просмотра ключей API View API keys:

Поиск ключей API в случае изменения их URL-адреса 

Открывается следующий раздел: 

Раздел API keys на сайте OpenAI

Нажимаем на Reveal (“Показать”) и сохраняем ключ API в надежном месте. Нельзя разглашать ключи API или загружать их на GitHub. В случае отсутствия секретного ключа нажимаем на Create new secret key для его создания. 

Отметим, что бесплатный аккаунт ограничивает размер и, возможно, количество задаваемых ИИ вопросов. 

Подключение к OpenAI GPT-3

Получив требуемый токен с сайта OpenAI, приступаем к написанию кода для взаимодействия с GPT-3. 

Шаг 16. Установка библиотеки OpenAI

Переходим в VSCode. Если бот в настоящий момент работает, останавливаем его командой Ctrl + C в терминале. 

Устанавливаем библиотеку OpenAI для Node.js следующей командой: 

npm install openai

Шаг 17. Создание скрипта для взаимодействия с GPT-3

В VSCode создаем новый файл ai.js:

Создание нового файла скрипта ai.js

Вставляем в этот файл нижеуказанный код и заменяем <YOUR_OPENAI_API_KEY> на токен API, полученный на 15-м шаге. Не забываем заключить его в двойные кавычки: 

//В ai.js
const { Configuration, OpenAIApi } = require("openai");
const configuration = new Configuration({
apiKey: <YOUR_OPENAI_API_KEY>,
});
const openai = new OpenAIApi(configuration);
async function ask(prompt) {
const response = await openai.createCompletion({
model: "text-davinci-002",
prompt,
temperature: 0.7,
max_tokens: 256,
top_p: 1,
frequency_penalty: 0,
presence_penalty: 0,
});
const answer = response.data.choices[0].text;
console.log(answer);
}
//Пример вопроса: Как называются планеты Солнечной системы?
ask("What are the names of the planets in the solar system?");

Шаг 18. Проверка подключения к OpenAI GPT3

Сохраняем файл и переходим в терминал. Далее выполняем команду: 

node ai.js

Если все сработало правильно, то в терминале появится ответ ИИ:

После выполнения node ai.js вы получаете ответ от GPT-3

Прокачаем бота суперинтеллектом

Почти готово! Уже проделана большая работа! Осталось соединить все части вместе и вывести бота на уровень супергения. 

Шаг 19. Подключение бота Discord к GPT-3

В файле ai.js удаляем примерный вызов функции ask и экспортируем функцию с помощью module.exports. Помимо этого, убираем console log и возвращаем ответ в функции ask

//В  ai.js
const { Configuration, OpenAIApi } = require("openai");
const configuration = new Configuration({
apiKey: <YOUR_OPENAI_API_KEY>,
});
const openai = new OpenAIApi(configuration);
async function ask(prompt) {
const response = await openai.createCompletion({
model: "text-davinci-002",
prompt,
temperature: 0.7,
max_tokens: 256,
top_p: 1,
frequency_penalty: 0,
presence_penalty: 0,
});
const answer = response.data.choices[0].text;
return answer;
}
//Экспорт функции "ask"
module.exports = {
ask,
};

Переходим в файл bot.js и применяем следующие изменения: 

//В bot.js
const { ask } = require("./ai.js"); //Импорт функции "ask" из файла "ai.js"
const token = <"YOUR_SAVED_BOT_TOKEN">; //Токен, сохраненный на 5-м шаге руководства
const {Client, Intents} = require("discord.js");
const client = new Client({
intents:[
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES
]
});
client.on("ready", () =>{
console.log("The AI bot is online"); //Сообщение, когда бот в сети
});
client.on("message", async (message) => {
if (message.content.substring(0, 1) === "!") {
const prompt = message.content.substring(1); //Удаление восклицательного знака из сообщения
const answer = await ask(prompt); //Ответ GPT-3
message.channel.send(answer); //Ответное сообщение в Discord с ответом от GPT-3
}
});
client.login(token);

Сохраняем изменения. В последний раз с помощью Ctrl + C останавливаем работу бота и перезапускаем его командой: 

npm start

Переходим на сервер Discord и проверяем, все ли работает должным образом. Напишем в чате сообщение с вопросом или заданием, поставив в начале восклицательный знак:

Бот ИИ получает задание создать таблицу с планетами Солнечной системы и указать расстояние от них до Земли

На следующем скриншоте бота просят рассказать анекдот про программистов:

 — Why did the programmer quit his job? Почему программист бросил свою работу?

 — Because he didn’t get arrays (игра слов: arrays  —  массивы и a raise  — прибавка к зарплате). Потому что он не получил прибавки к зарплате.

Печально, но факт

Поздравляем!

Вы создали своего первого ИИ-бота в Discord с использованием Node.js, Discord.js и API OpenAI. Теперь можно показать его друзьям или позадавать ему разные интересные вопросы!

Читайте также:

  • Генерация видео из текста стала возможной
  • Создание музыкального бота с помощью Discord.js
  • Будущее практического применения чат-ботов

Читайте нас в Telegram, VK и Дзен


Перевод статьи christianschuller: Build a Discord Bot Using Node.js, Discord.js, and OpenAI GPT-3

Vojta

Vojta

Posted on Feb 5, 2022



 



 



 



 



 

 

What Will You Need

  • Visual Studio Code (or any other code editor)
  • Node.js 16.6.0 or newer
  • Discord Account

1) Make a New Discord Application

Go to the Discord Developer Portal and click on New Application
Discord Developer Portal

Name it and hit Create
Create Application

Now let’s go to the Bot section and Add a Bot
Add a Bot

2) Invite The Bot to Your Server

Go to the URL Generator, and select bot and Administrator
URL Generator
Scopes
Bot permissions

Copy the URL at the bottom of the page and open it in a new tab
Copy URL

You should see something like this:
Connect bot to Discord
Select a server you want to add the bot to, and click Continue and Authorize

The bot has joined the server, hurray 🎉
Bot has joined the server

3) Add functionality to the bot

First, you’ll need to go back to Discord Developer Portal, go back to the Bot section, and Copy the bot token (here you can also name the bot and add a profile picture)
Copy bot token
The bot token is like a password for the bot, so DON’T SHARE IT!

Now create a new folder for the project if you haven’t done that yet and open it in VSCode

We’re gonna need to install discord.js first, which you can do in the integrated terminal (ctrl+J, select Terminal).

Type these two commands into it, and that’s it

npm init -y
npm i discord.js

Enter fullscreen mode

Exit fullscreen mode

Now create a new file (bot.js) and paste this in (don’t forget to replace ‘your token’ with the bot token) :

const { Client } = require('discord.js');

const client = new Client({
  intents: ['GUILDS', 'GUILD_MESSAGES'],
});

client.once('ready', () => console.log('Ready!'));

client.on('messageCreate', (message) => {
  if (message.content.includes('dn')) {
    return message.reply('deez nuts haha gotem');
  }

  if (message.content === '!help') {
    return message.reply("there's no help lmao");
  }
});

client.login('your token');

Enter fullscreen mode

Exit fullscreen mode

Run this using

node bot.js

Enter fullscreen mode

Exit fullscreen mode

And now you can see the result:
Deez Nuts showcase

Tutorial Completed!

here, have a cat as a reward
cat
(image by Tuqa Nabi on Unsplash)

This tutorial will show you how to use JavaScript and Node.js to build your own Discord bot completely in the cloud.

You do not need to install anything on your computer, and you do not need to pay anything to host your bot.

We are going to use a number of tools, including the Discord API, Node.js libraries, and a cloud computing platform called Repl.it.

If you’d rather code your discord bot using Python instead of JavaScript, read this tutorial instead.

There is also a video version of this written tutorial. The video is embedded below and the written version is after the video.

How to Create a Discord Bot Account

In order to work with the Node.js library and the Discord API, we must first create a Discord Bot account.

Here are the step to creating a Discord Bot account.

1. Make sure you’re logged on to the Discord website.

2. Navigate to the application page.

3. Click on the “New Application” button.

image-117

4. Give the application a name and click “Create”.

image-118

5. Go to the “Bot” tab and then click “Add Bot”. You will have to confirm by clicking «Yes, do it!»

image-119

Keep the default settings for Public Bot (checked) and Require OAuth2 Code Grant (unchecked).

Your bot has been created. The next step is to copy the token.

image-122

This token is your bot’s password so don’t share it with anybody. It could allow someone to log in to your bot and do all sorts of bad things.

You can regenerate the token if it accidentally gets shared.

How to Invite Your Bot to Join a Server

Now you have to get your Bot User into a server. To do this, you should create an invite URL for it.

Go to the «OAuth2» tab. Then select «bot» under the «scopes» section.

image-123

Now choose the permissions you want for the bot. Our bot is going to mainly use text messages so we don’t need a lot of the permissions. You may need more depending on what you want your bot to do. Be careful with the «Administrator» permission.

image-124

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 «Manage Server» permissions.

Now that you’ve created the bot user, we’ll start writing the Python code for the bot.

How to Code a Basic Discord Bot with the discord.js Library

We’ll be using the discord.js Node library to write the code for the bot. discord.js is an API wrapper for Discord that makes it easier to create a Discord bot in Node.js / JavaScript.

How to Create a Repl and Install discord.js

You can develop the bot on your local computer with any code editor. However, in this tutorial, we’ll be using Repl.it because it will make it simpler for anyone to follow along. Repl.it is an online IDE that you can use in your web browser.

Start by going to Repl.it. Create a new Repl and choose «Node.js» as the language. This means the programming language will be JavaScript.

To use the discord.js library, just add const Discord = require("discord.js"); at the top of main.js. Repl.it will automatically install this dependency when you press the «run» button.

How to Set Up Discord Events for Your Bot

discord.js revolves around the concept of events. An event is something you listen to and then respond to. For example, when a message happens, you will receive an event about it that you can respond to.

Let’s make a bot that replies to a specific message. This simple bot code is taken directly from the discord.js documentation. We will be adding more features to the bot later.

Add this code to main.js. I’ll explain what all this code does shortly.

const Discord = require("discord.js")
const client = new Discord.Client()

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

client.on("message", msg => {
  if (msg.content === "ping") {
    msg.reply("pong");
  }
})

client.login(process.env.TOKEN)

When you created your bot user on Discord, you copied a token. Now we are going to create a .env file to store the token.

.env files are used for declaring environment variables. On Repl.it, most files you create are visible to anyone but .env files are only visible to you.  Other people viewing a public repl will not be able to see the contents of the .env file.

So if you are developing on Repl.it, only include private information like tokens or keys in a .env file.

Click the «Add file» button and create a file named .env.

Inside the file add the following line, including your actual token you copied previously:

TOKEN=[paste token here]

Now let’s go over what each line of code is doing in your Discord bot code.

The first line imports the discord.js library.  Next, we create an instance of a Client. This is the connection to Discord.

The client.on() is used to check for events.  It accepts an event name, and then a callback function to be called when the event takes place. In this code, the ready event is called when the bot is ready to start being used. Then, when the Discord server has a new message, the message event is called.

The code checks if the msg.content equals 'ping'. If so, then the bot replies with 'pong' to the channel.

Now that the bot is set up, the final line runs the bot with the login token. It gets the token from out .env file.

We have the code for the bot so now we just have to run it.

How to Run the Bot

Now click run button on the top to run your bot in repl.it.

Now go to your Discord room and type «ping». Your bot should return «pong».

image

How to Improve the Bot

Now that we have a basic bot working, we’ll improve it. It is called «Encourage Bot» for a reason.

This bot will respond with a message of encouragement whenever someone sends a message containing a sad or depressing word.

Anyone will be able to add encouraging messages for the bot to use and the user-submitted messages will be stored in the Repl.it database.

The bot will also return a random inspirational quote from an API when someone types the message «$inspire» into the chat.

We’ll start with adding the «$inspire» feature.

How to Add Inspirational Quotes to the Bot

We will get inspirational quotes from an API called zenquotes.io. We need to import the node-fetch module, add a getQuote() function, and update our bot code to call the function.

Here is the updated code. After the code, I’ll explain the new parts.

const Discord = require("discord.js")
const fetch = require("node-fetch")
const client = new Discord.Client()

function getQuote() {
  return fetch("https://zenquotes.io/api/random")
    .then(res => {
      return res.json()
      })
    .then(data => {
      return data[0]["q"] + " -" + data[0]["a"]
    })
}

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

client.on("message", msg => {
  if (msg.author.bot) return
    
  if (msg.content === "$inspire") {
    getQuote().then(quote => msg.channel.send(quote))
  }
})

client.login(process.env.TOKEN)

We now have to import the node-fetch module. This module allows our code to make an HTTP request to get data from the API.

The getQuote() function is pretty straightforward. First, it uses the node-fetch module to request data from the API URL. The API returns a random inspirational quote. This function could easily be rewritten to get quotes from a different API, if the current one stops working.

Then the function converts the response from the API to JSON and creates a string to return. Through trial and error I figured out how to get the quote from the JSON into the string format I wanted. The quote is returned from the function as a string.

The final part updated in the code is toward the end. Previously it looked for the message «ping». Now it looks for «$inspire». Instead of returning «pong», it gets the quote with getQuote() and returns the quote. We use msg.channel.send() to send the message to the channel. Also, the code checks if the message comes from the bot itself and if it does, it leaves the function so it does not do anything.

At this point you can run your code and try it out.

How to Add Encouraging Messages to the Bot

Now we will implement the feature where the bot responds with encouraging messages when a user posts a message with a sad word.

How to Add Sad Words to the Bot

First we need to create an array that contains the sad words that the bot will respond to.

Add the following line after the client variable is created:

sadWords = ["sad", "depressed", "unhappy", "angry", "miserable"]

Feel free to add more words to the list.

How to Add Encouraging Messages to the Bot

Now we’ll add an array of encouraging messages that the bot will respond with.

Add the following array after the sadWords list you created:

encouragements = [
  "Cheer up!",
  "Hang in there.",
  "You are a great person / bot!"
]

Like before, feel free to add more phrases of your choice to the array . I’m just using three items for now because later we’ll add the ability for users to add more encouraging phrases for the bot to use.

How to Respond to Messages

Now we need to update our bot to use the two lists we created.

Now we will update the message function to check all messages to see if they contain a word from the sadWords list. If a sad word is found, the bot will send a random message of encouragement.

Here is the updated code:

client.on("message", msg => {
  if (msg.content === "$inspire") {
    getQuote().then(quote => msg.channel.send(quote))
  }

  if (sadWords.some(word => msg.content.includes(word))) {
    const encouragement = encouragements[Math.floor(Math.random() * encouragements.length)]
    msg.reply(encouragement)
  }

})

This is a good time to test the bot. You know enough now to create your own bot. But next you’ll learn how to implement more advanced features and store data using the Repl.it database.

How to Enable User-submitted Messages

The bot is completely functional, but now let’s make it possible to update the bot right from Discord. A user should be able to add more encouraging messages for the bot to use when it detects a sad word.

We are going to use Repl.it’s built-in database to store user-submitted messages. This database is a key-value store that’s built into every repl.

At the top of the code, under the other import statements, add:

const Database = require("@replit/database")
const db = new Database()

This will allow us to use the Repl.it database. When you run the code, Repl.it should install the database module automatically. If for some reason it doesn’t, you may have to go into the Shell tab (not the Console) and type «npm install @replit/database».

After where the encouragements array is created, insert the following code to add the encouragements to the database if needed:

db.get("encouragements").then(encouragements => {
  if (!encouragements || encouragements.length < 1) {
    db.set("encouragements", starterEncouragements)
  }  
})

Also, rename the encouragements array toward the top to starterEncouragements.

Users will be able to add custom encouraging messages for the bot to use directly from the Discord chat. Before we add new commands for the bot, let’s create two helper functions that will add custom messages to the database and delete them.

Add the following code after the getQuote() function:

function updateEncouragements(encouragingMessage) {
  db.get("encouragements").then(encouragements => {
    encouragements.push([encouragingMessage])
    db.set("encouragements", encouragements)
  })
}

function deleteEncouragment(index) {
  db.get("encouragements").then(encouragements => {
    if (encouragements.length > index) {
      encouragements.splice(index, 1)
      db.set("encouragements", encouragements)
    }
  })
}

The updateEncouragements() function accepts an encouraging message as an argument.

First it gets the «encouragements» from the database. Then, it adds the new encouragement to the array, and stores the updated array back in the database under the «encouragements» key.

The deleteEncouragement() function accepts an index as an argument.

It gets the list of encouragements from the database stored under the «encouragements» key. If the length is more than the index, then the list item at that index is deleted. Finally, the updated list is stored back in the database under the «encouragements» key.

Here is the updated code for the message function. After the code, I’ll explain the new sections.

client.on("message", msg => {
  if (msg.content === "$inspire") {
    getQuote().then(quote => msg.channel.send(quote))
  }

  
  if (sadWords.some(word => msg.content.includes(word))) {
    db.get("encouragements").then(encouragements => {
      const encouragement = encouragements[Math.floor(Math.random() * encouragements.length)]
      msg.reply(encouragement)
    })
  }

  if (msg.content.startsWith("$new")) {
    encouragingMessage = msg.content.split("$new ")[1]
    updateEncouragements(encouragingMessage)
    msg.channel.send("New encouraging message added.")
  }

  if (msg.content.startsWith("$del")) {
    index = parseInt(msg.content.split("$del ")[1])
    deleteEncouragment(index)
    msg.channel.send("Encouraging message deleted.")
  }
})

The sad words section has been updated to use the encouraging messages from the database so user submitted messages can be used.

The next new section of code is used to add a new user-submitted message to the database. If a Discord message starts with «$new», then the text after «$new» will be used as a new encouraging message.

The code msg.content.split('$new ')[1] splits off the message from the «$new» command and stores the message in a variable. In that line of code, take note of the space in '$new '. We want everything after the space.

We call the updateEncouragements helper function with the new message, and then the bot sends a message to the discord chat confirming that the message was added.

The third new section (at the end of the code above) checks if a new Discord message starts with «$del». This is the command to delete an item from the «encouragements» list in the database.

The index is split off from the Discord message starting with «$del». Then, the deleteEncouragement() function is called passing in the index to delete. The updated list of encouragements is loaded into the encouragements variable, and then the bot sends a message to Discord with the current list.

Final Bot Features

The bot should work so this is a good time to test it. We will now add a few final features.

We will add the ability to get a list of user-submitted messages right from Discord and we will add the ability to turn off and on whether the bot responds to sad words.

I will give you the full final code of the program, and then I’ll discuss the updates below the code.

const Discord = require("discord.js")
const fetch = require("node-fetch")
const Database = require("@replit/database")

const db = new Database()
const client = new Discord.Client()

const sadWords = ["sad", "depressed", "unhappy", "angry", "miserable"]

const starterEncouragements = [
  "Cheer up!",
  "Hang in there.",
  "You are a great person / bot!"
]

db.get("encouragements").then(encouragements => {
  console.log(encouragements)
  if (!encouragements || encouragements.length < 1) {
    db.set("encouragements", starterEncouragements)
  }  
})

db.get("responding").then(value => {
  if (value == null) {
    db.set("responding", true)
  }  
})

function getQuote() {
  return fetch("https://zenquotes.io/api/random")
    .then(res => {
      return res.json()
      })
    .then(data => {
      return data[0]["q"] + " -" + data[0]["a"]
    })
}

function updateEncouragements(encouragingMessage) {
  db.get("encouragements").then(encouragements => {
    encouragements.push([encouragingMessage])
    db.set("encouragements", encouragements)
  })
}

function deleteEncouragment(index) {
  db.get("encouragements").then(encouragements => {
    if (encouragements.length > index) {
      encouragements.splice(index, 1)
      db.set("encouragements", encouragements)
    }
  })
}

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

client.on("message", msg => {
  if (msg.content === "$inspire") {
    getQuote().then(quote => msg.channel.send(quote))
  }

  db.get("responding").then(responding => {
    if (responding && sadWords.some(word => msg.content.includes(word))) {
      db.get("encouragements").then(encouragements => {
        const encouragement = encouragements[Math.floor(Math.random() * encouragements.length)]
        msg.reply(encouragement)
      })
    }
  })

  if (msg.content.startsWith("$new")) {
    encouragingMessage = msg.content.split("$new ")[1]
    updateEncouragements(encouragingMessage)
    msg.channel.send("New encouraging message added.")
  }

  if (msg.content.startsWith("$del")) {
    index = parseInt(msg.content.split("$del ")[1])
    deleteEncouragment(index)
    msg.channel.send("Encouraging message deleted.")
  }

  if (msg.content.startsWith("$list")) {
    db.get("encouragements").then(encouragements => {
      msg.channel.send(encouragements)
    })
  }
    
  if (msg.content.startsWith("$responding")) {
    value = msg.content.split("$responding ")[1]

    if (value.toLowerCase() == "true") {
      db.set("responding", true)
      msg.channel.send("Responding is on.")
    } else {
      db.set("responding", false)
      msg.channel.send("Responding is off.")
    }
  }
})

client.login(process.env.TOKEN)

The first section added to the code is right under the starterEncouragements list:

db.get("responding").then(value => {
  if (value == null) {
    db.set("responding", true)
  }  
})

We create a new key in the database called «responding» and set it to «true». We’ll use this to determine if the bot should respond to sad words or not. Since the database is saved even after the program stops running, we only create the new key if it doesn’t already exist.

The next new part of the code is in the section that responds to sad words is now inside this if statement. The bot will only respond to sad words if db.get("responding") = true. The ability to update this value comes after this next section.

Next, after the code to make the bot respond to the «$del» command, there is new code to respond to the «$list» command when sent as a Discord message.

The bot sends the list of encouragements as a Discord message.

The final new section comes next. This code makes the bot respond to the «$responding» command. This command takes an argument of either «true» or «false». Here is a usage example: «$responding true».

The code first pulls off the argument with value = msg.content.split("$responding ")[1] (like before, note the space in "$responding "). Then there is an if/else statement that appropriately sets the «responding» key in the database and sends a notification message back to Discord. If the argument is anything but «true», the code assumes «false».

The code for the bot is complete! You can now run the bot and try it out. But there is one more important step that we will discuss next.

How to Set Up the Bot to Run Continuously

If you run your bot in repl.it and then close the tab it is running in, your bot will stop running.

But there are two ways you can keep your bot running continuously, even after you close your web bowser.

The first way and simplest way is to sign up for paid plan in Repl.it. Their cheapest paid plan is called the Hacker Plan and it includes five always-on Repls.

You can get three months free using this link (limited to first 1000 people):  https://repl.it/claim?code=tryalwayson2103

Once you have signed up for that plan, open your Repl and click the name at the top. Then select the «Always On» option.

image-36

There is another way to keep your code running even on the free tier but it is a little more complicated. Repl.it will continue running a web server even after the tab is closed. But even a web server will only run for up to an hour without any use.

Here is what the repl.it docs say:

Once deployed, the server will continue to run in the background, even after you close the browser tab. The server will stay awake and active until an hour after its last request, after which it will enter a sleeping stage. Sleeping repls will be woken up as soon as it receives another request; there is no need to re-run the repl. However, if you make changes to your server, you will need to restart the repl in order to see those changes reflected in the live version.

To keep the bot running continuously, we’ll use another free service called Uptime Robot at https://uptimerobot.com/.

Uptime Robot can be set up to ping the bot’s web server on repl.it every 5 minutes. With constant pings, the bot will never enter the sleeping stage and will just keep running.

So we have to do two more things to get our bot to run continuously:

  1. create a web server in repl.it and
  2. set up Uptime Robot to continuously ping the web server.

How to Create a Web Server in repl.it

Creating a web server is simpler than you may think.

To do it, create a new file in your project called server.js.

Then add the following code:

const express = require("express")

const server = express()

server.all("/", (req, res) => {
  res.send("Bot is running!")
})

function keepAlive() {
  server.listen(3000, () => {
    console.log("Server is ready.")
  })
}

module.exports = keepAlive

In this code, we use express to start a web server. The server returns «Bot is running!» to anyone who visits it. The server will run on a separate thread from our bot. We won’t discuss everything here since the rest is not really relevant to our bot.

Now we just need the bot to run this web server.

Add the following line toward the top of index.js  to import the server.

const keepAlive = require("./server")

To start the web server when index.js is run, add the following line as the second-to-last line, right before the bot runs.

keepAlive()

When you run the bot on repl.it after adding this code, a new web server window will open up. There is a URL shown for the web server. Copy the URL so you can use it in the next section.

image-1

How to Set Up Uptime Robot

Now we need to set up Uptime Robot to ping the web server every five minutes. This will cause the bot to run continuously.

Create a free account on https://uptimerobot.com/.

Once you are logged in to your account, click «Add New Monitor».

image-21

For the new monitor, select «HTTP(s)» as the Monitor Type and name it whatever you like. Then, paste in the URL of your web server from repl.it. Finally, click «Create Monitor».

image-22

We’re done! Now the bot will run continuously so people can always interact with it on Repl.it.

Conclusion

You now know how to create a Discord bot with JavaScript, and run it continuously in the cloud.

There are a lot of other things that the discord.js library can do. So if you want to give a Discord bot even more features, your next step is to check out the docs for discord.js.

Learn to code for free. freeCodeCamp’s open source curriculum has helped more than 40,000 people get jobs as developers. Get started

  • Introduction
  • Video tutorial
  • Create a Discord server
  • Create a Discord app
  • Create a bot user for your app
  • Authorize/invite the bot to your server
  • Prepare your Node.js project workspace
  • Install the Discord.js module
  • Write a simple test bot
  • Get a list of servers the bot is connected to
  • Get a list of channels from a server
  • Sending a message to a channel
  • Posting an image or file to a channel
  • Replying to a message
  • Tagging a user
  • Checking if your bot was tagged in a message
  • Creating commands
  • Changing game presence/activity
  • Adding a reaction emoji to a message
  • Playing audio files in voice chat
  • How to run the bot 24/7
  • Where to get help
  • Conclusion
  • References

Introduction

In this tutorial, we will walk through the process of creating a bot in JavaScript. We will start by creating a Discord server, creating a bot account, and inviting it to the server. Then we will demonstrate how to write JavaScript (Node.js) code to power the bot. By the end, you will have your very own bot that can be invited to any server that you have full control over.

If you are interested in learning how to make a Discord bot in Python, check out Make a Discord Bot in Python and Part 2. Be sure to also check out all of the other Discord related tutorials on DevDungeon.

Video tutorial

Create a Discord server

In order to create a Discord server you will need to have a Discord account. If you don’t have a Discord account already, sign up and log in at https://discordapp.com/channels/@me. Once you are registered, you can either use the web browser version or you can download the app. They both behave the same. Once you are logged in to the app, look to the bottom-left corner, for the plus (+) sign. Click on the plus sign and it will ask if you want to create or join a server. Click «Create a Server.» Provide a name, and click «Create.» The new server will appear in the left column.

Create a Discord app

The next step is to create a Discord App. We aren’t writing any code yet, we are just registering the app with Discord. Start by going to https://discordapp.com/developers/applications/me and create a new app. On your app detail page, save the Client ID. You will need it later to invite the bot to a server. Try to give your app a unique name.

Create a bot user for your app

After creating app, you need to take one further step and add a bot user to the app. You can do this on the app details page. On the app details page, scroll down to the section named bot, and create a bot user. Save the token, you will need it later to run the bot. If you get an error saying «Too many users have this username, please try another» then you need to rename your application to something more unique.

Note that by default, a bot has limited permissions. It can send and receive messages, add reactions, and do things a normal low-privileged user could do on a server, but it cannot perform admin actions like kicking members or managing channels. To perform those admin actions you would need to add the specific permissions to the bot as well as perform additional authentication steps. We are not going to cover that in this tutorial. We will stick with the default permissions like a regular non-admin user.

Authorize/invite the bot to your server

After you have registered your app and created the bot user for your app, you are ready to invite(authorize) the bot to your server. To do this, you will need the Client ID for your app. You can get this from your app’s «General Information» page.

When you have your Client ID, visit the URL https://discordapp.com/oauth2/authorize?client_id=XXXXXXXXXXXX&scope=bot but replace XXXXXXX with your client ID. Choose the server you want to add it to and select authorize.

The Client ID does not necessarily need to be kept secret. If you want to share your bot and allow others to invite the bot to their server, then you can share this link. It will allow them to invite your bot to their server. The bot’s token is different though. Always keep the token a secret, as that is the equivalent to your bot’s password. Anyone with the token can log in as your bot.

After you authorize the bot for the server, it should then show up in the member list of the server as an offline user. Once we write some code and run it, the bot will appear online.

Prepare your Node.js project workspace

First, you will need to have Node.js installed. If you don’t already have it installed, get it from Nodejs.org. I will be using Node.js 10.10.0. You will need Node.js 8.0.0 or newer. You will also need npm but that should come packaged with Node.js.

Once you have Node.js installed, you will need to create a new directory to store your project. Once you have a new directory, open your system terminal/command prompt/shell and navigate to your new directory. You can create the directory in your home folder or anywhere you have permission. You may prefer to create a folder on your desktop.

# For example in Windows Command Prompt:
mkdir C:UsersNanoDanomy_discord_bot
cd C:UsersNanoDanomy_discord_bot

# Or with the Mac Terminal
mkdir /Users/NanoDano/my_discord_bot
cd /Users/NanoDano/my_discord_bot

# Or with Linux Shell
mkdir /home/NanoDano/my_discord_bot
cd /home/NanoDano/my_discord_bot

Keep your terminal open. You will need it in the next step.

Install the Discord.js module

The next step is to install the Discord.js module and its dependencies. Use npm in the command prompt to install the module:

npm install discord.js    

You might see warnings. Those are OK, it is just telling you about some optional modules. As long as you do not see any errors it should be good. Keep your terminal open here so you can run the program you create in the next step.

At the time of this writing, Discord.js is at version 11.4.2. Future version might change how the code works.

Write a simple test bot

At this point, you should have your development environment ready to go with Node.js and the necessary Discord.js module installed. You should also have your own Discord server, app, and bot user that are ready to be utilized. We should take a moment to make sure everything is set up properly. Let’s write the simplest bot possible just to make sure it works. Let’s create a new JS file and write some code to have the bot log in. You can name the file my_bot.js though the file name is not important.

Create/open the new file in your favorite editor, and put the following code in the file:

const Discord = require('discord.js')
const client = new Discord.Client()

client.on('ready', () => {
    console.log("Connected as " + client.user.tag)
})

// Get your bot's secret token from:
// https://discordapp.com/developers/applications/
// Click on your application -> Bot -> Token -> "Click to Reveal Token"
bot_secret_token = "XXXXXXXXXXX"

client.login(bot_secret_token)

You will need to replace the XXXXXXXXXXX with your bot’s secret token. This is equivalent to your bot’s password, so keep it secret! You can find the bot’s token by going to https://discordapp.com/developers/applications/ and then clicking on your app. On the app detail page, click on the «Bot» section. On the bot detail page, look for the «Token» section. You will need to «click to reveal token.»

Save the file and run the code from the terminal:

node my_bot.js

The output should say Connected as [your bot’s name]. If you check the server’s member list, the bot should appear online as well. If you can see the bot online in the server, then everything is working properly and we can move on to making the bot actually do something fun! The JavaScript file will continue to run although it doesn’t do anything except connect, so use CTRL-C to terminate the program or exit the terminal to kill the process. It is normal for your bot to still appear online for a few minutes after the program is terminated. After a few minutes it will appear offline again.

If you have any errors or get stuck at this spot, try joining the DevDungeon Discord server (https://discord.gg/JWsSHJC) or post a comment to ask for help.

Get a list of servers the bot is connected to

Once your bot is connected, the client object keep a list of servers it is connected to. In Discord terminology, it is called a guild. The client object has an property named guilds which we can access through client.guilds. In the following example, we iterate through the list of servers(guilds) and print out the name of each one. Most likely your bot is only connected to just one server, your test server. Bots can be connected to many servers at once though.

const Discord = require('discord.js')
const client = new Discord.Client()

client.on('ready', () => {
    // List servers the bot is connected to
    console.log("Servers:")
    client.guilds.forEach((guild) => {
        console.log(" - " + guild.name)
    })
})

client.login("XXXXXXXXXXX") // Replace XXXXX with your bot token

The Discord.js Client object has many other properties, like how long it has been connected, all channels available, and what emojis are available. To see a full list of properties on the Client object, check out the official documentation for the Client object at https://discord.js.org/#/docs/main/stable/class/Client.

Get a list of channels from a server

In the previous example we saw how to get a list of servers the client has access to. Each server can have many channels. The guild object has a property named channels that we can access. That will give us the list of channels for that specific guild(server). Another option is to get channels property from the client object instead of the guild object. If we use client.channels as opposed to guild.channels then we will get the list of all channels from all servers.

In this example, we will extend the code from the previous section. We will still list each server we are connected to, but we will also list each channel’s name, type, and ID for each server.

const Discord = require('discord.js')
const client = new Discord.Client()

client.on('ready', () => {
    // List servers the bot is connected to
    console.log("Servers:")
    client.guilds.forEach((guild) => {
        console.log(" - " + guild.name)

        // List all channels
        guild.channels.forEach((channel) => {
            console.log(` -- ${channel.name} (${channel.type}) - ${channel.id}`)
        })
    })
})

client.login("XXXXXXXXXXX") // Replace XXXXX with your bot token

Note that there are multiple types of channels including text, voice, and category. The type «category» is not a channel that can be used directly, it is just a label for a group of channels.

Find a channel you would like to use to send messages. There is usually a text channel named «general» that you can use. Take note of the channel ID of the text channel you would like to use. You will need it in the next section to send a message to the channel. For our example, let’s pretend the channel ID is 123456789.

Sending a message to a channel

In the previous example we demonstrated how to get all of the channels available. You should have identified a text channel that you want to use. You need the channel.id. For our example, we will pretend the channel ID is 123456789, but you will want to replace that with the actual channel ID. The following code will print «Hello, world!» to the specified channel as soon as the bot connects.

const Discord = require('discord.js')
const client = new Discord.Client()

client.on('ready', () => {
    var generalChannel = client.channels.get("123456789") // Replace with known channel ID
    generalChannel.send("Hello, world!") 
})

client.login("XXXXXXXXXXX") // Replace XXXXX with your bot token

Posting an image or file to a channel

This example will extend the previous example that sends a message to a text channel. Instead of sending a regular text message though, we are going to send an attachment. An attachment can be an image or it can be a file. The attachment can come from your local hard disk or from a web URL. The code below demonstrates how to create an attachment from a local file and then send it to the channel as well as how to create an attachment from an HTTP URL. Note that for the localFileAttachment to wor, you will need to replace the example filepath with the path to a real file on your computer. The webAttachment should work as it links to the DevDungeon logo but you can change it to any image or file on the web.

const Discord = require('discord.js')
const client = new Discord.Client()

client.on('ready', () => {
    var generalChannel = client.channels.get("123456789") // Replace with known channel ID

      // Provide a path to a local file
    const localFileAttachment = new Discord.Attachment('D:\logo.png')
    generalChannel.send(localFileAttachment)

    // Provide a URL to a file
    const webAttachment = new Discord.Attachment('https://www.devdungeon.com/sites/all/themes/devdungeon2/logo.png')
    generalChannel.send(webAttachment)
})

client.login("XXXXXXXXXXX") // Replace XXXXX with your bot token

Replying to a message

In all of the previous examples, we have taken action as soon as the bot connected by using the client.on(‘ready’) event. In this example, we are going to trigger our code whenever a message is received. The client object actually has several events that we can use as triggers. For example: whenever a channel is created, whenever a message is deleted, or when a user updates their presence(e.g. starts playing a game). See the full list of events that you can use on the Client documentation page at https://discord.js.org/#/docs/main/stable/class/Client. For this example we are using the message event, which gets triggered whenever a message is received, either via private message or in a text channel.

The code below will respond any time a message is received with an acknowledgement. Note that the message event gets triggered even when the bot sends a message. This means the bot could enter an infinite loop where it keeps responds to its own messages. To prevent that, the first thing we are going to do is make sure the message received did not come from our bot itself. If it does, we will just return and take no action. If the message received comes from another user, it will continue and reply with the acknowledgement message.

To test the code below, run the bot and using your own Discord user (not the bot) send a message to a text channel on your server that the bot has access to. You can also send the bot a direct/private message and it will respond in the same channel.

const Discord = require('discord.js')
const client = new Discord.Client()

client.on('message', (receivedMessage) => {
    // Prevent bot from responding to its own messages
    if (receivedMessage.author == client.user) {
        return
    }

    receivedMessage.channel.send("Message received: " + receivedMessage.content)
})

client.login("XXXXXXXXXXX") // Replace XXXXX with your bot token

Tagging a user

Let’s extend the previous example to also tag the user who sent the message. To tag the user, we can take the user who sent the message, receivedMessage.author, and use the toString method to get the properly formatted tag.

const Discord = require('discord.js')
const client = new Discord.Client()

client.on('message', (receivedMessage) => {
    // Prevent bot from responding to its own messages
    if (receivedMessage.author == client.user) {
        return
    }

    receivedMessage.channel.send("Message received from " + receivedMessage.author.toString() + ": " + receivedMessage.content)
})

client.login("XXXXXXXXXXX") // Replace XXXXX with your bot token

Checking if your bot was tagged in a message

Let’s extend the previous example even further by only responding to messages if the bot user was tagged. We will have to inspect the message content and see if our bot’s tag was mentioned. We do this by converting our bot’s user to a string, and then seeing if the message includes that string.

const Discord = require('discord.js')
const client = new Discord.Client()

client.on('message', (receivedMessage) => {
    // Prevent bot from responding to its own messages
    if (receivedMessage.author == client.user) {
        return
    }

        // Check if the bot's user was tagged in the message
    if (receivedMessage.content.includes(client.user.toString())) {
        // Send acknowledgement message
        receivedMessage.channel.send("Message received from " +
            receivedMessage.author.toString() + ": " + receivedMessage.content)
    }
})

client.login("XXXXXXXXXXX") // Replace XXXXX with your bot token

Creating commands

A common task with Discord bots is to create «commands». A command in this sense is a message that triggers a special action. Commands are often specified by beginning a message with a special character. For example !help or ?help or something similar.

In this example we will create a few functions to break up the logic. We will still have our event triggered when a message is received, but this time, we will see if the message starts with an exclamation mark (!) and if it does, we will route it to a custom processCommand function. The processCommand function is responsible for taking the full message from the user and breaking it in to pieces. The user can provide extra parameters to the command by separating words with a space. For example, commands can have no parameters or multuiple parameters like this:

!help
!help someTopic
!multiply 2 4

Inside the processCommand function, after we remove the leading exclamation mark and separate the command from the arguments, we then inspect the main command and then pass the logic to another function. We create a helpCommand and a multiplyCommand. Depending on what command is triggered, the corresponding function is called.

There are limitless ways to abstract out a command handler, but this method should be simple enough to understand and be flexible enough for the needs of most people. I provided two sample commands in order to provide a template for creating your own commands. Try extending this example with a custom command of your own. Here are a few ideas:

  • A !ping command that simply responds with «Pong!»
  • An !8ball command that returns random Yes, No, or Maybe responses.
  • A !fortune command that replies with a random fortune cookie quote.
  • A !weather [zip_code] command that queries a weather API and replies with the local weather.
  • A !bitcoin command that looks up the current BitCoin price.
const Discord = require('discord.js')
const client = new Discord.Client()

client.on('message', (receivedMessage) => {
    if (receivedMessage.author == client.user) { // Prevent bot from responding to its own messages
        return
    }

        if (receivedMessage.content.startsWith("!")) {
        processCommand(receivedMessage)
    }
})

function processCommand(receivedMessage) {
    let fullCommand = receivedMessage.content.substr(1) // Remove the leading exclamation mark
    let splitCommand = fullCommand.split(" ") // Split the message up in to pieces for each space
    let primaryCommand = splitCommand[0] // The first word directly after the exclamation is the command
    let arguments = splitCommand.slice(1) // All other words are arguments/parameters/options for the command

    console.log("Command received: " + primaryCommand)
    console.log("Arguments: " + arguments) // There may not be any arguments

    if (primaryCommand == "help") {
        helpCommand(arguments, receivedMessage)
    } else if (primaryCommand == "multiply") {
        multiplyCommand(arguments, receivedMessage)
    } else {
        receivedMessage.channel.send("I don't understand the command. Try `!help` or `!multiply`")
    }
}

function helpCommand(arguments, receivedMessage) {
    if (arguments.length > 0) {
        receivedMessage.channel.send("It looks like you might need help with " + arguments)
    } else {
        receivedMessage.channel.send("I'm not sure what you need help with. Try `!help [topic]`")
    }
}

function multiplyCommand(arguments, receivedMessage) {
    if (arguments.length < 2) {
        receivedMessage.channel.send("Not enough values to multiply. Try `!multiply 2 4 10` or `!multiply 5.2 7`")
        return
    }
    let product = 1
    arguments.forEach((value) => {
        product = product * parseFloat(value)
    })
    receivedMessage.channel.send("The product of " + arguments + " multiplied together is: " + product.toString())
}

client.login("XXXXXXXXXXX") // Replace XXXXX with your bot token

Try running this code and then sending a message to the bot or to the channel with !help and !multiply.

Changing game presence/activity

Changing the bot’s activity is relatively simple. We just need to call setActivity() on the bot’s user object. By default it will say «Playing ____» but you can also change the verb to «Streaming», «Listening», or «Watching». Try out the code below. After running the code, look at the bot in the member list of the server and you should see it’s status change.

const Discord = require('discord.js')
const client = new Discord.Client()

client.on('ready', () => {
    // Set bot status to: "Playing with JavaScript"
    client.user.setActivity("with JavaScript")

    // Alternatively, you can set the activity to any of the following:
    // PLAYING, STREAMING, LISTENING, WATCHING
    // For example:
    // client.user.setActivity("TV", {type: "WATCHING"})
})

client.login("XXXXXXXXXXX") // Replace XXXXX with your bot token

Adding a reaction emoji to a message

There are two types of emojis you can use to react to messages. Each server is allowed to have custom emojis. You can also use Unicode emojis. Unicode is an international standard. You can actually copy and paste the Unicode emoji right in to the source code. The code below demonstrates how to use Unicode emojis and custom emojis. It will react using two standard Unicode emojis and then react with every custom emoji on the server (if the server has any). You can upload custom emojis by going to your Server Settings -> Emoji -> Upload Emoji. Note that not every single Unicode emoji is supported, but Discord does support a huge number of them.

const Discord = require('discord.js')
const client = new Discord.Client()

client.on('message', (receivedMessage) => {
    if (receivedMessage.author == client.user) { // Prevent bot from responding to its own messages
        return
    }

    // You can copy/paste the actual unicode emoji in the code (not _every_ unicode emoji works)
    receivedMessage.react("👍")
    receivedMessage.react("🛐")
    // Unicode emojis: https://unicode.org/emoji/charts/full-emoji-list.html

    // Get every custom emoji from the server (if any) and react with each one
    receivedMessage.guild.emojis.forEach(customEmoji => {
        console.log(`Reacting with custom emoji: ${customEmoji.name} (${customEmoji.id})`)
        receivedMessage.react(customEmoji)
    })
    // If you know the ID of the custom emoji you want, you can get it directly with:
    // let customEmoji = receivedMessage.guild.emojis.get(emojiId)
})

client.login("XXXXXXXXXXX") // Replace XXXXX with your bot token

Playing audio files in voice chat

Playing audio in voice channels requires installing extra dependencies. We will not cover this topic here, but you can find more details and instructions in the official documentation on this page: https://discord.js.org/#/docs/main/stable/topics/voice. Time permitting in the future, this topic might be covered here in more detail.

How to run a bot 24/7

To keep a bot online all the time, you will need to leave the program running. You can do this by simply leaving your computer on and never turning it off. This is not practical for most people. An alternative is to rent a cheap $5/month server from a provider like Linode or Digital Ocean. They provide cheap linux servers that run all the time in their datacenter. You can run your code there. Another alternative is to use a Raspberry Pi from your house that you leave running all the time. If you want to set up the bot as a systemd service in Linux, check out the creating systemd service files tutorial.

Where to get help

If you have questions or are having any trouble, you can join the DevDungeon community Discord server at https://discord.gg/JWsSHJC or leave a comment on this page.

Conclusion

After following the examples in this tutorial, you should have a solid understanding of some common tasks like sending messages, receiving messages, and adding emoji reactions. With these building blocks, you can build bigger, better, more complex bots. I did not cover every possible aspect though. There are still more advanced things you can do like waiting for replies to messages, waiting for reactions on messages, and creating embedded messages. You can find out more about all of those things inside the official Discord.js documentation. If you have questions about any advanced topics, hop in the DevDungeon Discord server https://discord.gg/JWsSHJC and ask.

References

  • DevDungeon community Discord server
  • Discord Developer Portal
  • Discord API documentation
  • Discord.js documentation
  • Discord.js Source on GitHub
  • Discord.js on NPM

Introduction

Communicating online and staying in touch with people all over the globe has been a major promise from the dawn of the internet — a web of communication and information. Fairly early on, applications sprung up that connected people all over the globe, allowing them to send messaged, multimedia, perform live video and audio calls, allowing for international communication in a more interactive and engaging format than just phone calls.

The 2020 pandemic further increased the need to work remotely and communicate with friends and family online. Communication services, which were well-established by that point saw a new wave of users and applications such as Zoom, Google Teams, Skype, Discord and Webex rose in popularity.

Discord is the application we’ll be focusing on in this guide. As of 2021, it’s one of the most popular communication platforms, used to fascillitate communities of users in servers, the sharing of text, audio and video as well as live streaming to channels.

What sets Discord apart is how easily it can be adapted to certain themes and communities, with custom roles, authorization and channels, which allows users to interact with given servers in a unique way — more than just a group chat.

At the heart of this customizability are Discord bots, which can be set up to react to messages, reactions or perform tasks periodically, allowing server administrators to give structure and create protocols of conduct.

Creating bots is fairly easy, and can be done in a wide variety of languages — such as C#, Java, Go, Lua, NodeJS, PHP, Python and Ruby, and in this guide, we’ll take a look at how to create a Discord bot in JavaScript, as well as how to make the bot react to messages with its own responses, handle custom commands and how to change the bot’s presence.

Discord bots are based on an Event-Driven Architecture, which is natural given the nature of the platform they’re running on.

Before diving into the bot itself, if you’re not familiar with the terminology used within Discord — we’ll take a look at the basics.

Basics of Discord

What started as a gamers based application, nowadays became a general use application for communication. As previously mentioned, Discord is one of the most popular communication applications on the web.

As most applications of this type, it has options for text, audio and video communication and is also completely free. While one-on-one communication is available, a major appeal of Discord are its servers, which can serve as simple groups chats, but can be expanded into being full-blown communities of thousands.

  • Discord servers

You can think of a Discord server as a big house consisting of multiple rooms. These rooms can be broken down into text and voice channels. If you would like to check out some of the most popular servers, you can use services that list servers and their invite links on websites such as Top.gg.

An individual enters a server through an invite link which can be permanent (anyone with it can join as long as the server is available), temporary (anyone can join in a given timeframe) or limited to certain individuals. Additionally, based on a user’s authorization, they may or may not create invite links — and this is oftentimes automated through bots.

  • Discord channels

If server is a house, one Discord channel is one room in that house. Channels are used to organize topics of discussion — such as a workplace having a Marketing channel, Development channel and a Memes channel.

Text channels allow users to send text, video files and images and you can ban multimedia and force text-only and vice-versa (you can delete text messages, and enforce only images) via bots.

Voice channels are only used for voice communication regardless of a user’s presence in other text channels. A user can talk to other users in a voice channel and type messages in a separate text channel or stream a video within the voice channel.

Furthermore, a user may enter a channel only if their authorization allows it. By default, everyone can enter every channel, but through role-based authorization, you can hide channels from individuals with certain roles.

  • Discord bot

A Discord bot is a program written to automate certain tasks or moderate predictable behavior. For instance, you can use a bot to detect foul language and delete messages that contains it.

Discord bots are, ultimately, users.

Whatever a user can do, a bot can do — faster, and around the clock. Typically, bots are given superadmin authorization so they can kick, ban, create invites, delete messages, assign roles, etc. They’re typically used to coordinate and maintain servers when user moderators and admins are not around, as well as to handle menial tasks.

Many public bots exist, which are open-source and work great as general purpose bots! Some of them even have APIs that you can fiddle around with, as well as web user interfaces that let you customize them to your liking so the average Joe can create a bot without any coding knowledge.

While these work well, it’s a similar analogy to creating a website with services such as WordPress — you might want to build it from scratch yourself instead.

That being said, let’s go ahead and create a Discord Bot user that we’ll be automating.

Creating a Discord Bot User

Bots are ultimately users, but they have to be transparently bots. They’re a type of user and people in the server know when a bot is a bot. To create a bot, and to avoid abuse and misuse — you have to register it through Discord’s Developer portal:

discord.com/developers/applications

This page serves as a dashboard for all the applications you write:

When the page loads, in the top right corner you’ll see a purple button — New Application.

You’ll be prompted to enter a name for your bot. In this guide, we’ll be calling it test-bot since it’ll be a general simple bot, but you can get more creative! This bot will send a welcome message every time someone joins, which is a pretty typical use for a bot in a community. Additionally, it’ll react to certain messages containing inappropriate language, reacts to people calling for it, as well as handle commands from users.

Let’s enter a name for the bot:

When you click Create, you’ll be taken to the application’s settings. We’ll be focusing on the Bot and OAuth2 tabs. The Rich Presence tab is used for integrating Discord into games (can be used by game devs to intertwine the features) and the App Testers tab is used to invite testers to test your app. This is a useful feature if your bot has superadmin powers, and you’re skeptical about publishing it before testing it.

The first tab useful for us is the Bot tab. Here you can create a bot, change its profile picture, name and set a token.

Note: A token is practically a password for your bot. It is best if you do not reveal it to anybody, since it can be used to manipulate the bot in ways that can harm your Discord server.

Each application needs to be authorized and Discord uses OAuth2 for authorization — the industry-standard. Under the OAuth2 tab, we can select scopes for applications, and since we’re created a bot, we’ll be checking the box next to the bot scope. Right after checking it, another tab called Bot Permissions should pop up underneath the Scopes.

Here we will set all the permissions that the bot will have. Since we are making the bot that will mostly send text messages, this is the only part that is interesting for us:

You might have noticed that the only General Permission we set is View Channels — because the bot needs the permission to move from channel to channel in order to interact with the users.

As you select permissions, the OAuth2 URL generator will add your options with a unique client_id live. Once you select all of the options you wish to apply to the bot, copy and follow the link. Once you do — you’ll be prompted to select a server to which to add the bot.

After selecting a server and verifying that you are not a robot, a bot should appear in the bot list. The bot will appear offline in the chat until it’s coded, so no need to panic about its permissions quite yet, even if you haven’t coded it.

Programming a Discord Bot in Node.js

With a Bot user set up, we can go ahead and actually code it!

Installing Discord.js

To code the bot, we’ll be using Discord’s SDK — Discord.js. It’s available for download via NPM:

$ npm install discord.js

Once installed, we’re ready to go! Let’s create a folder for the project and initialize an empty Node project within it:

$ mkdir discord_bot
$ cd discord_bot
$ npm init

You can leave all the default options when instantiating the project, or set some of your own.

Important Note: In order to use the Discord.js module, you need to have Node 16.x+ installed on your sistem. Otherwise, a missing module 'node:events' error will be raised.

Understanding Bot Intents

Bot Intents are probably the most important concept to understand in order to manage your bot properly. Bot intents are a group of events that the bot will react to. They have their own FLAGS which can be set in order to precisely define which events we want our bot to react to.

If you don’t define them properly, your bot will simply not react, even if you have the right code.

Intents are passed as an array when initializing the bot, which we’ll see a bit later. For now, keep the syntax in mind:

Intents.FLAGS.INTENT_NAME

The macro INTENT_NAME is the only part we will be changing when wanting to add different intents. To let bot react to intents, go to the Bot tab at The Developer Dashboard. Under Privileged Gateway Intents, turn on Presence Intent and Server Members Intent.

Let’s look into some of the intents defined in the Discord.js documentation:

  • GUILDS — reacts to any events containing a Create or Delete action — such as messageCreate.
  • GUILD_MEMBERS — reacts to events such as adding, updating and removing a new user to the server.
  • GUILD_MESSAGES — reacts to events such as Sending a message, Editing a message and Deleting a message.
  • GUILD_MESSAGE_REACTIONS — reacts to events such as Adding or removing a reaction to a message.

You may be wondering, what is a Guild all of a sudden? Just another name for a server. According to the Developer Portal:

Guilds in Discord represent an isolated collection of users and channels, and are often referred to as «servers» in the UI.

There’s a decent list of intents, though, you’ll generally be using only a few for most basic tasks.

Initializing a Discord Bot

The first action a bot could take is, well, being online. It’s a passive action and can be scheduled to be online during certain times of the day, for instance. For now, let’s just get the bot to be online on the server.

In the Bot tab of the dashboard, copy your bot’s token — this token is used on the client-side to authenticate it. Then, in the index.js file of your Node project, let’s import the Discord.js SDK, define the intents of the bot and set it to be online:

const {
    Client,
    Intents
} = require('discord.js');

const bot = new Client({
    intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MEMBERS, Intents.FLAGS.GUILD_MESSAGES]
});

bot.on('ready', () => {
    console.log(`Bot ${bot.user.tag} is logged in!`);
});

bot.login('YOUR_BOT_TOKEN'); // Replace the macro with your token

Here, we just initialize a Client object, which is the main interface for interacting with Discord’s APIs. The Client is the bot. When initializing it, we pass in the array of intents.

Let’s look at the other chunk of code:

bot.on('ready', () => {
  console.log(`Bot ${bot.user.tag} is logged in!`);
});

Again, Discord bots are based on an Event-Driven Architecture. The Client is an EventEmitter and we can listen to the emitted events and react to them.

If you’d like to read more about Event-Driven Architectures and handling events with Node — read our Guide to Handling Events in Node.js with EventEmitter!

In this case, we’re listening to the ready event, and on() that event, we log that the bot is logged in. This requires prerequisite knowledge of when Discord sends events — for instance, it sends a ready event when a client logs in. The user object of the Client represents the Discord user that the bot really is.

The login() method, given the bot token will log the bot in and emit this event, and the on() listener fires then, logging the message. Go ahead and run the script and observe the bot going online on the server:

$ node index.js
Bot [BOT-NAME] is logged in!

Awesome! It’s online and logged in. Let’s add another event listener to send welcome messages when users join.

Send Welcome Messages to a Channel

A classic task for a bot is to welcome users to a server. These can be as simple as «Welcome [user]!» to more elaborate welcomes, including randomized messages. The string you return is fully up to you and your imagination is the limit.

When a member is added to a discord server a guildMemberAdd event is fired, which you can listen to just like you’d listen to other events. In order to catch this event, we previously added an intent called GUILD_MEMBERS which allows us to listen to it.

First, let’s capture the member that enters and print them to the console:

bot.on('guildMemberAdd', (member) => {
    console.log(member)
});

Run the script again, and when a new user enters, you’ll be greeted with something along the lines of:

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

GuildMember {
  guild: <ref *1> Guild {
    id: '<USER_ID>',
    name: undefined,
    icon: undefined,
    features: undefined,
    commands: GuildApplicationCommandManager {
      permissions: [ApplicationCommandPermissionsManager],
      guild: [Circular *1]
    },
    members: GuildMemberManager { guild: [Circular *1] },
    channels: GuildChannelManager { guild: [Circular *1] },
    bans: GuildBanManager { guild: [Circular *1] },
    roles: RoleManager { guild: [Circular *1] },
    presences: PresenceManager {},
    voiceStates: VoiceStateManager { guild: [Circular *1] },
    stageInstances: StageInstanceManager { guild: [Circular *1] },
    invites: GuildInviteManager { guild: [Circular *1] },
    deleted: false,
    available: false,
    shardId: 0,
    memberCount: NaN
  },
  joinedTimestamp: 1633939430866,
  premiumSinceTimestamp: null,
  deleted: false,
  nickname: null,
  pending: false,
  _roles: [],
  user: User {
    id: '<USER_ID>',
    bot: false,
    system: false,
    flags: UserFlags { bitfield: 0 },
    username: '<MEMBER_USERNAME>',
    discriminator: '<MEMBER_DISCRIMINATOR>',
    avatar: null,
    banner: undefined,
    accentColor: undefined
  },
  avatar: null
}

There’s a bunch of information on the GuildMember (Discord user within a server) that just joined, though, the interesting bits for us are:

  • guild — server information, with properties such as id, name, members, channels, presences, etc.
  • _roles — an array containing user’s roles in the server, if any exist.
  • user — user information, with properties such as id, bot, username, discriminator, etc.
  • discriminator is an integer which is a part of the full username, which usually looks like: randomUser#1234, so 1234 is a discriminator.

There’s a lot of confusion as to what’s the difference between a User and a GuildMember, and it really just boils down to:

A User is a global Discord user, and a GuildMember is that user within a server. It’s a representation of a user, with permissions, roles, nicknames, etc. Each User can have multiple GuildMembers bound to it, with a GuildMember for each server. You can essentially see it as a «face» of a user in a given context.

Now, let’s tweak the code so that it doesn’t print the GuildMember instance, but rather greet them. Typically, there’s a dedicated text channel for greetings and welcomes — and you don’t want to use the #general channel for this.

Additionally, there’s also oftentimes a #bot-spam channel for menial bot output that might clutter actual chat channels. You can, of course, simply not send certain messages, but it helps to log them either on the server or an external file for later use.
You can hide this channel from regular users if you don’t want it to be public.

You can create a new channel by clicking on the dropdown menu next to the server’s name and clicking on Create Channel. The prompt will ask you whether you want a Text or Voice channel. We’ll select a text one, and name it #welcome.

We can send a message to a channel by obtaining its instance and the send() method. Instances are obtained through a channel’s ID, which is known as a constant during your bot’s lifetime.

To fetch a channel’s ID, we must turn the Developer Mode on, and use the UI of the application. Head over to your Discord settings, by clicking the little gear wheel at the bottom left of the application. Under App Settings in the left part of the window, you’ll find an Advanced tab. There, turn on the Developer Mode. This will allow us to retrieve the Channel ID. This is done by right-clicking on the channel’s name and clicking Copy ID.

Let’s use that ID to fetch() a channel and send a message to it, on() the event of a user joining in:

bot.on('guildMemberAdd', (member) => {
    const channelId = 'CHANNEL_ID'; // The Channel ID you just copied
    const welcomeMessage = `Hey <@${member.id}>! Welcome to my server!`;
    member.guild.channels.fetch(channelId).then(channel => {
        channel.send(welcomeMessage)
    });
});

As we’ve seen previously, a guild has information about its channels, which we can retrieve with member.guild.channels. Finally, in order to get the channel that we want, we call the method fetch() and pass the channel ID as a parameter. This method returns a Promise, so it must be followed with a then(), where we define a function to be executed after we retrieve the desired channel. In this case, this will be a simple .send() containing a text of the message.

Again, you can do much more here, such as pick a random message from a list of templates, log the information outside of the channel, etc.

If you’d like to read more about Promises, read our Guide to Promises in Node.js!

The <@${member.id}> message simply tags the user in a message, so they receive a notification for this message when joining the server. You can omit the @ in the beginning to skip the tagging part, though, servers oftentimes tag people to get their attention and redirect them to read a server’s rules, for instance.

When a user joins your server, they’ll be greeted with your message:

Awesome! Let’s go ahead and give our bot a bit more autonomy, by allowing it to pick up certain phrases or words and reacting to them.

Detect and React to Messages in the Channel

Once people join your server, they’ll be sending messages. Each message that’s sent creates a messageCreate event, which you can, unsurprisingly, listen to. You don’t want to spam users on every message, but there are cases where your bot might want to react to something.

For instance, if someone’s calling the bot or a user includes insensitive words, you might want to have the bot respond or take action. For instance, let’s add two listeners — one that gets the bot to react to users calling for it and one that reacts to when people send inapproprate words within their messages.

To detect messages, you need the GUILDS and GUILD_MESSAGES intents.

When catching a message, the message object contains the content of the message, channel from which the message came, etc. Then, it’s just a matter of checking whether that string contains other strings:

bot.on('messageCreate', (message) => {
    if(message.content.toLowerCase().includes('hey bot') || message.content.toLowerCase().includes('general kenobi')){
        message.channel.send('Hello there!');
    }
});

bot.on('messageCreate', (message) => {
    if(message.content.toLowerCase().includes('fudge') || message.content.toLowerCase().includes('pudding')){
        message.channel.send('Such language is prohibited!');
    }
});

The bot will only respond to messages defined in the if clause and will respond in the same channel that the message originated from, as obtained from the message object itself. You can, of course, send the message to a different channel as well or direct it to a hidden channel reserved only for admins.

Once you run the script again, and type in a few messages, the bot will talk back!

Note: The bot will react to its own messages, as they also fire the messageCreate event when sent.

If your response to a user contains words that might match other if statements, your bot may end up replying to itself ad infinitum:

bot.on('messageCreate', (message) => {
    if(message.content.toLowerCase().includes('fudge') && message.content.toLowerCase().includes('pudding')) {
			message.channel.send('Why of course, I love fudgy pudding cake!');
	} else if(message.content.toLowerCase().includes('fug') || message.content.toLowerCase().includes('pudding')){
        message.channel.send('Such language is prohibited!');
	}
});

Fudgy pudding cake is delicious, so if someone tells us to fudge the pudding, they must be referring to the process of creating the cake, so we respond with a nice message back — however, the «pudding» in the response is matches to a new event handler created by the response. Thus, the bot responds to that message with its own:

Yikes. You can easily create an infinite loop like this. For instance:

bot.on('messageCreate', (message) => {
    if(message.content.toLowerCase().includes('a')) {
			message.channel.send('a');
	}
});

This piece of code will respond with "a" whenever a message contains "a" — which results in an infinite stream of 5-message bursts of the bot saying "a":

Be careful when checking and responding to messages, and be careful of how powerful methods such as includes() or contains() can be. Thankfully, avoiding this issue is pretty simple.

Stop Bot From Replying to Itself

You don’t want the bot to reply to itself, or contradict itself in examples such as the one with fudgy pudding cake. Thankfully, you can easily check who sent the message and ignore it if it’s sent by a bot, totally avoiding the infinite loop issue:

if(message.author.bot) {
    return;
}

Let’s add this check in our earlier example:

bot.on('messageCreate', (message) => {
	if (message.author.bot) {
		return;
	} else if(message.content.toLowerCase().includes('fudge') && message.content.toLowerCase().includes('pudding')) {
			message.channel.send('Why of course, I love fudgy pudding cake!');
	} else if(message.content.toLowerCase().includes('fug') || message.content.toLowerCase().includes('pudding')){
        message.channel.send('Such language is prohibited!');
	}
});

The first if statement checks whether a bot sent the message or not. If it did, the rules below don’t really apply, so we never enter the infinite state. Let’s send another heart-felt message to the bot, regarding their cake:

Works great!

Creating Bot Commands

Since we’ve seen how to process the messages sent to the server, let’s now define some commands for it to allow users to command it through a controlled environment. First of all, let’s welcome our users with a different message. We have to let them now how to find the list of commands, and how to use them:

bot.on('guildMemberAdd', (member) => {
    const channelId = 'CHANNEL_ID';
    const welcomeMessage = `Hey <@${member.id}>! Welcome to my server! n See commands list by typing: $listCommands`;
    member.guild.channels.fetch(channelId).then(channel => {
        channel.send(welcomeMessage)
    });
});

Commands are, really, just messages that follow a certain form you’ve set for yourself, and we can check for commands just as we’ve checked for messages so far.

You don’t have to use the $ symbol to denote commands. Some use dots (.), slashes (/), etc. Generally, some symbol is used to denote a command rather than a message.

Let’s code the commands, including the $listCommands one. We can do this inside one of the existing messageCreate listeners or a new one — we’ll just process different message.content. To stylize the response of the command list, we’ll use a MessageEmbed which looks similar to a quoteblock. It allows us to set a color, title, description as well as fields as with their keys (names) and values to describe commands.

To use MessageEmbed instances, we need to import it from Discord.js first so let’s update the initially imported classes:

const {
    Client,
    Intents,
	MessageEmbed
} = require('discord.js');

Now, we can create a new if statement to handle the commands:

bot.on('messageCreate', (message) => {
    if(message.content.toLowerCase().includes('hey bot') || message.content.toLowerCase().includes('general kenobi')){
        message.channel.send('Hello there!');
    }
	
	if (message.content == '$listCommands') {
        const exampleEmbed = new MessageEmbed()
            .setColor('#ffd046')
            .setTitle('Server Commands')
            .setDescription('Here you can see the list of the commands used on the server: ')
            .addFields(
                { name: "`$like`", value: 'Likes the current message' },
                { name: "`$dislike`", value: 'Dislikes the current message'},
                { name: "`$random`", value: 'Returns a random number'},
            )
        message.channel.send({embeds: [exampleEmbed]})
    }

    if (message.content == '$like') {
        message.react('👍');
    }

    if (message.content == '$dislike') {
        message.react('👎');
    }

    if(message.content == '$random'){
        message.react('✅');
        let randomNumber = getRandomNumber(0, 1000);
        message.reply(`Your random number is ${randomNumber}.`)
    }
});

We also have an auxiliary method to generate a random number within a certain range:

function getRandomNumber(min, max){
    return Math.floor(Math.random() * (max-min) + min);
}

The if-else clause may not be the best option for processing commands, but if there are a few of them, it’s just fine. However, if you wish for your server to have a wide range of commands, you should probably consider putting them in a file and have a bot find a proper command and reaction to it when a message is sent instead.

Running the script again allows us to use these commands:

Changing a Bot’s Presence

When a bot is logged in, you can change its presence. This could be to signify that the bot is on standby, waiting for commands or tasks, or simply to set the tone of your served. For instance, you can set it to «play a game» while being online or «serve the community».

It’s an optional little gig, but can go a long way in terms of humor and denoting when and whether the bot is available and online:

bot.login('YOUR_BOT_TOKEN').then(() => {
    bot.user.setPresence({ activities: [{ name: 'a random game', type: 'PLAYING' }], status: 'online' });
});

Presence is defined by activities and a status. Activities are an array of activities a user is doing. They have a name and a type. The type is a macro and can be set to PLAYING, WATCHING, LISTENING, STREAMING and COMPETING. They resemble the start of the sentence for the presence, so the name is its continuation.

A presence for the code above should look like this:

Conclusion

Discord bots are malleable and your imagination is the limit when it comes to coding them. They are undeniably one of the major reasons Discord broke out as a community-building platform and an excellent messenger and communication application.

Discord has a really large community and a nice tradition of Discord servers, with a lot of really useful ones. If you have an idea of your own, now is the time to start developing a server!

Like this post? Please share to your friends:
  • Как написать дирижер или дерижер
  • Как написать директору школы жалобу на педагога
  • Как написать директору что я увольняюсь
  • Как написать директору что ты увольняешься
  • Как написать директору что приболела