Создание Discord – бота на .NET Core с деплоем на VPS-сервер

  • Tutorial


Привет, Хабровчане!

Сегодня вы ознакомитесь со статьей, в которой будет рассказано, как создать бота, используя C# на .NET Core, и о том, как его завести на удаленном сервере.

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

Надеюсь, данная статья поможет многим начинающим.

Предыстория


Все началось в одну бессонную осеннюю ночь, которую я проводил на Discord – сервере. Так как я относительно недавно к нему присоединился, я стал его изучать вдоль и поперёк. Обнаружив текстовый канал «Вакансии», я заинтересовался, открыл его, и отыскал среди не интересующих меня предложений, это:

«Программист (разработчик бота)
Требования:

  • знание языков программирования;
  • способность к самообучению.

Пожелания:

  • умение разбираться в чужом коде;
  • знание функционала DISCORD.

Задачи:

  • разработка бота;
  • поддержка и сопровождение работы бота.

Ваша выгода:

  • Возможность поддержать и повлиять на приглянувшийся проект;
  • Приобретение опыта работы в команде;
  • Возможность продемонстрировать и улучшить имеющиеся навыки.»


Это мгновенно меня заинтересовало. Да, за данную работу не платили, но от тебя никаких обязательств не требовали, да и в портфолио лишним не будет. Поэтому я написал админу сервера, и он попросил написать бота, который будет показывать статистику игрока в World of Tanks.

Подготовительный этап



Discrod
Прежде, чем приступить к написанию нашего бота, его необходимо создать для Discord. Вам необходимо:

  1. Войти в Discord аккаунт по ссылке
  2. Во вкладе “Applications” нажать на кнопку “New Application” и назвать бота
  3. Получить токен бота, войдя в вашего бота и найдя в списке “Settings” вкладку “Bot”
  4. Сохранить где-нибудь токен

Wargaming

Также, необходимо создать приложение в Wargaming, чтобы получить доступ к API Wargaming. Тут тоже все просто:

  1. Заходим в аккаунт Wargaming по данной ссылке
  2. Заходим в «Мои приложения» и нажимаем на кнопку «Добавить новое приложение», дав имя приложения и выбрав его тип
  3. Сохраняем ID приложения

Software

Тут уже имеется свобода выбора. Кто-то использует Visual Studio, кто-то Rider, кто-то вообще мощный, и пишет код в Vim (все же настоящие программисты используют только клавиатуру, верно?). Однако, чтобы не реализовывать Discord API, можно использовать неофициальную библиотеку для C# “DSharpPlus”. Его можно установить либо из NuGet, либо самому собрав исходники с репозитория.

Для тех, кто не знает, или забыл, как устанавливать приложения из NuGet.
Инструкция для Visual Studio

  1. Переходим во вкладку Проект – Управление пакетами NuGet;
  2. Нажимаем на обзор и в поле поиска вводим “DSharpPlus”;
  3. Выбираем и устанавливаем framework;
  4. PROFIT!


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

Написание логики




Всю логику приложения рассматривать не будем, я лишь покажу, как работать с перехватом сообщений ботом, и как работать с Wargaming API.

Работа с Discord бот происходит через функцию static async Task MainTask(string[] args);
Чтобы вызвать данную функцию, в Main необходимо прописать

MainTask(args).ConfigureAwait(false).GetAwaiter().GetResult();

Далее, вам необходимо инициализировать своего бота:

discord = new DiscordClient(new DiscordConfiguration
{
    Token = token,
    TokenType = TokenType.Bot,
    UseInternalLogHandler = true,
    LogLevel = LogLevel.Debug
});

Где token – токен вашего бота.
Потом, через лямбду, прописываем необходимые команды, которые должен выполнять бот:
discord.MessageCreated += async e =>
{
    string message = e.Message.Content;
    if (message.StartsWith("&"))
    {
        await e.Message.RespondAsync(“Hello, ” + e.Author.Username);
    }
};

Где e.Author.Username – получение никнейма пользователя.

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

В конце данной функции, необходимо прописать await discord.ConnectAsync(); и await Task.Delay(-1);

Это позволит выполнять команды на фоне, не занимая основной поток.

Теперь необходимо разобраться с Wargaming API. Тут все просто – пишете CURL-запросы, получаете ответ в виде JSON – строки, вытягиваете оттуда необходимые данные и делаете над ними манипуляции.

Пример работы с WargamingAPI
public Player FindPlayer(string searchNickname)
        {
            //https://api.worldoftanks.ru/wot/account/list/?application_id=y0ur_a@@_id_h3r3search=nickname
            urlRequest = resourceMan.GetString("url_find_player") + appID + "&search=" + searchNickname;
            Player player = null;
            string resultResponse = GetResponse(urlRequest);
            dynamic parsed = JsonConvert.DeserializeObject(resultResponse);

            string status = parsed.status;
            if (status == "ok")
            {
                int count = parsed.meta.count;
                if (count > 0)
                {
                    player = new Player
                    {
                        Nickname = parsed.data[0].nickname,
                        Id = parsed.data[0].account_id
                    };
                }
                else
                {
                    throw new PlayerNotFound("Игрок не найден");
                }
            }
            else
            {
                string error = parsed.error.message;
                if (error == "NOT_ENOUGH_SEARCH_LENGTH")
                {
                    throw new PlayerNotFound("Минимум три символа требуется");
                }
                else if (error == "INVALID_SEARCH")
                {
                    throw new PlayerNotFound("Неверный поиск");
                }
                else if (error == "SEARCH_NOT_SPECIFIED")
                {
                    throw new PlayerNotFound("Пустой никнейм");
                }
                else
                {
                    throw new Exception("Something went wrong.");
                }
            }

            return player;
        }


Внимание! Все токены и ID приложений хранить в открытом виде строго не рекомендуется! Как минимум – Discord банит такие токены, когда они попадают во всемирную сеть, как максимум – бот начинает пользоваться злоумышленниками.

Деплой на VPS – сервер




После того, как вы закончили с ботом, его необходимо разместить на сервере, который постоянно работает 24/7. Это связанно с тем, что когда работает ваше приложение, то работает и бот. Как только вы выключаете приложение, засыпает и ваш бот.

Много VPS серверов существует на этом свете, как на Windows, так и на Linux, однако в большинстве случаев, на Linux в разы дешевле размещать.

На Discord – сервере мне посоветовали vscale.io, и я тут же создал на нем виртуальный сервер на Ubuntu и залил бота. Я не буду описывать, как работает данный сайт, а сразу перейду к настройки бота.

Первым делом, вам необходимо установить необходимый софт, который будет запускать нашего бота, написанного на .NET Core. Как это сделать, описано здесь.

Далее, вам необходимо залить бота на Git – сервис, вроде GitHub и ему подобные и склонировать на VPS — сервер, или, другими путями скачать вашего бота. Учтите, что у вас будет только консоль, GUI не будет. Совсем.

После того, как вы скачали вашего бота, вам необходимо его запустить. Для этого, вам необходимо:

  • Восстановить все зависимости: dotnet restore
  • Построить приложение: dotnet build name_project.sln -c Release
  • Перейти к построенной DLL;
  • dotnet name_of_file.dll

Поздравляю! Ваш бот запущен. Однако, бот, к несчастью, занимает консоль, и выйти из VPS – сервера так просто не выйдет. Также, в случае перезагрузки сервера, придется по новому запускать бота. Тут есть пару выходов из ситуации. Все они связаны с запуском при старте сервера:

  • Добавить запуск скрипта в /etc/init.d
  • Создать сервис, который будет запускаться при старте.

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

Выводы


Я рад, что я взялся за это задание. Это был мой первый опыт разработки бота, и рад, что получил новые знания по C#, и работе с Linux.

Ссылка на Discord – сервер. Для тех, кто играет в игры Wargaming.
Ссылка на репозиторий, где лежит Discord bot.
Ссылка на репозиторий DSharpPlus.
Спасибо за внимание!

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 12

    0

    Вот интересно — а как наиболее правильно организовать Continuous Delivery/Deploy на VPS-сервер?

      0

      denismaster
      Ну, можно попробовать костыли, и в скрипте прописать скачивание/клонирование вашего приложения, этот скрипт добавить в /etc/init.d. После обновления приложения, просто необходимо перезагрузить сервер. Но, это костыли, а других способов непрерывной доставки и непрерывного внедрения я пока не изучал.

        0
        Можно пойти разными путями.
        Но основные — это использовать git. С одной стороны вы заливаете код, с другой сервер его забирает. Можно использовать тут и jenkins, но как то оверкильнинько будет.
        Как вариант поставить задание в cron, можно задействовать папет или ансибел.
        В общем дальше уже как удобно. Можно и сам git в крон или некий скрипт.
          0
          У бота nadeko для этого есть вариант при каждом рестарте выкачивать из своего git репозитория последнюю версию исходников. Владельцу бота остается только выполнить команду .exit когда он хочет обновить бота.
          +1
          Далее, вам необходимо залить бота на Git – сервис, вроде GitHub и ему подобные и склонировать на VPS — сервер, или, другими путями скачать вашего бота.
          Самое простое и удобное — WinSCP

          После того, как вы скачали вашего бота, вам необходимо его запустить. Для этого, вам необходимо:
          А можно просто скомпилировать в «Self-contained», а чтобы не париться с кучей файлов — упаковать в один файл «Produce single file». Да, займет немного больше места, но зато не нужно задаваться вопросом какой .NET установлен, а просто взять и запустить.
            0
            А можно бота добавить на сервер дискорда, чтобы он читал определенные чаты?
              0

              Что вы имеете ввиду поз «засыпает» — что статус бота не онлайн? Это не влияет никак на работоспособность. По документации Discord нужно активировать токен 1 раз и можно с ним работать. Я писал на php бота — без проблем работает

                0
                Нет, что бот не будет принимать сообщения от пользователей.
                0
                Лирическое отступление. Я перешел на этот враппер с другого, когда discord опять прекратил поддержку версии API используемого мной враппера, и он не обновлялся. И два года я использовал этот враппер на сервере с пиковым онлайном до тысячи человек. Когда я прекратил поддержку, было желание сделать постмортем, но так и не сделал.
                Мои выводы профана в ботах по ботостроению в дискорде:
                • В дискорде есть эмодзи реакции на сообщения, эмбеды и эдит сообщений. Что это нам дает? Ну самый простой пример — эмбед с изображением и парой кнопок в виде эмодзи реакции на сообщение, и клик по этим эмодзи переключает изображение. И вроде здорово, но API не позволяет слишком часто редактировать сообщение, так что если решите портировать дум в виде ASCII в дискорд, с контролами в виде эмодзи — у вас наверняка будут проблемы с частотой редактирования сообщений.
                • То как организованы и написаны доки мне сильно не понравилось, но есть discord сервер враппера, где можно спрашивать. Он не безлюден. На всякий случай уточню, это не русско говорящий сервер.
                • Я имплементировал автоматизированную модерацию. Одной из проблем было то что мне нужно было знать, имеет ли вызывающий пользователь право на проведение операции над целью. Решилось парой расширений поверх враппера.
                • Это был сервер игры, и люди часто задавали однотипные вопросы. Я разрабатывал функционал по автоматическому обнаружению этих вопросов и ответу. Всплыли неколько проблем.
                  1. Вопросы могли быть в не предназначенных для вопросов каналов, и бот отвечал на них, юзер видел, что на его вопросы отвечают и задавал еще. Фиксится просто ограничением каналов для этого функционала до ботспама и вопросов.
                  2. Ложные срабатывания. Когда у тебя сотни человек в онлайне и система которая автоматически распознает вопросы — что может пойти так?
                  3. Пользователи любили шалить с этим функционалом, спрашивая заведомо бессмысленные вопросы, и радуясь ответам.

                • Если будете часто использовать одни и те же изображения — можно захостить какой-нибудь веб сервер и вставлять ссылки на изображений оттуда в эмбеды. Отлично работает, пока вы не отключите сервер с сообщениями.
                • Написать два слова как «диактрические символы» или как «Д̑йа̑к̆т̑р̆и̑ч̆е̑с̆к̑йе̑ ̮с̯и̮м̯в̮о̯л̮ы̯.̰̰̰̰̰», что по вашему выберет пользователь делая себе ник в дискорде? Пользователей второго типа больше чем хотелось бы.
                  0
                  Если будете часто использовать одни и те же изображения — можно захостить какой-нибудь веб сервер и вставлять ссылки на изображений оттуда в эмбеды. Отлично работает, пока вы не отключите сервер с сообщениями.

                  Можно и без веб сервера. В Дискорде создать скрытый канал, куда складывать нужные изображения, при просмотре изображения будет прямая ссылка «Открыть оригинал», которую и использовать (не только в Дискорде… только тссс)
                    0
                    Согласен, но так не удобно провайдить базу из сотен и тысяч иконок и иных изображений, а на моем проекте это было необходимо.
                    Мой знакомый использовал бесплатные фотохостинги для этого. Бота он использует и по сей день, а вот сидит ли он на той же реализации предоставления картинок — не знаю.
                    Будет ли дискорд выдавать пожатые версии картинок, если создавать эмбед сообщение с ссылками на картинки хранимые на серверах дискорда? Картинка которую ты приложил пожата?

                      0
                      Картинка которую ты приложил пожата?
                      Проверил, все совпадает до бита.
                      Я не спорю, хранить на Дискорде может и не очень удобно, но если в тексте с изображением использовать заметки-теги, то по ним можно неплохо искать нужные изображения.

                Only users with full accounts can post comments. Log in, please.