Привет, Хабровчане!
Сегодня вы ознакомитесь со статьей, в которой будет рассказано, как создать бота, используя C# на .NET Core, и о том, как его завести на удаленном сервере.
Статья будет состоять из предыстории, подготовительного этапа, написания логики и переноса бота на удаленный сервер.
Надеюсь, данная статья поможет многим начинающим.
Предыстория
Все началось в одну бессонную осеннюю ночь, которую я проводил на Discord – сервере. Так как я относительно недавно к нему присоединился, я стал его изучать вдоль и поперёк. Обнаружив текстовый канал «Вакансии», я заинтересовался, открыл его, и отыскал среди не интересующих меня предложений, это:
«Программист (разработчик бота)
Требования:
- знание языков программирования;
- способность к самообучению.
Пожелания:
- умение разбираться в чужом коде;
- знание функционала DISCORD.
Задачи:
- разработка бота;
- поддержка и сопровождение работы бота.
Ваша выгода:
- Возможность поддержать и повлиять на приглянувшийся проект;
- Приобретение опыта работы в команде;
- Возможность продемонстрировать и улучшить имеющиеся навыки.»
Это мгновенно меня заинтересовало. Да, за данную работу не платили, но от тебя никаких обязательств не требовали, да и в портфолио лишним не будет. Поэтому я написал админу сервера, и он попросил написать бота, который будет показывать статистику игрока в World of Tanks.
Подготовительный этап
Discrod
Прежде, чем приступить к написанию нашего бота, его необходимо создать для Discord. Вам необходимо:
- Войти в Discord аккаунт по ссылке
- Во вкладе “Applications” нажать на кнопку “New Application” и назвать бота
- Получить токен бота, войдя в вашего бота и найдя в списке “Settings” вкладку “Bot”
- Сохранить где-нибудь токен
Wargaming
Также, необходимо создать приложение в Wargaming, чтобы получить доступ к API Wargaming. Тут тоже все просто:
- Заходим в аккаунт Wargaming по данной ссылке
- Заходим в «Мои приложения» и нажимаем на кнопку «Добавить новое приложение», дав имя приложения и выбрав его тип
- Сохраняем ID приложения
Software
Тут уже имеется свобода выбора. Кто-то использует Visual Studio, кто-то Rider, кто-то вообще мощный, и пишет код в Vim (все же настоящие программисты используют только клавиатуру, верно?). Однако, чтобы не реализовывать Discord API, можно использовать неофициальную библиотеку для C# “DSharpPlus”. Его можно установить либо из NuGet, либо самому собрав исходники с репозитория.
Для тех, кто не знает, или забыл, как устанавливать приложения из NuGet.
Инструкция для Visual Studio
- Переходим во вкладку Проект – Управление пакетами NuGet;
- Нажимаем на обзор и в поле поиска вводим “DSharpPlus”;
- Выбираем и устанавливаем framework;
- 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.
Спасибо за внимание!
Комментарии (5)
GennPen
08.12.2019 12:51+1Далее, вам необходимо залить бота на Git – сервис, вроде GitHub и ему подобные и склонировать на VPS — сервер, или, другими путями скачать вашего бота.
Самое простое и удобное — WinSCP
После того, как вы скачали вашего бота, вам необходимо его запустить. Для этого, вам необходимо:
А можно просто скомпилировать в «Self-contained», а чтобы не париться с кучей файлов — упаковать в один файл «Produce single file». Да, займет немного больше места, но зато не нужно задаваться вопросом какой .NET установлен, а просто взять и запустить.
denismaster
Вот интересно — а как наиболее правильно организовать Continuous Delivery/Deploy на VPS-сервер?
hunterlan Автор
denismaster
Ну, можно попробовать костыли, и в скрипте прописать скачивание/клонирование вашего приложения, этот скрипт добавить в
/etc/init.d
. После обновления приложения, просто необходимо перезагрузить сервер. Но, это костыли, а других способов непрерывной доставки и непрерывного внедрения я пока не изучал.icCE
Можно пойти разными путями.
Но основные — это использовать git. С одной стороны вы заливаете код, с другой сервер его забирает. Можно использовать тут и jenkins, но как то оверкильнинько будет.
Как вариант поставить задание в cron, можно задействовать папет или ансибел.
В общем дальше уже как удобно. Можно и сам git в крон или некий скрипт.
Alexsey
У бота nadeko для этого есть вариант при каждом рестарте выкачивать из своего git репозитория последнюю версию исходников. Владельцу бота остается только выполнить команду .exit когда он хочет обновить бота.