Pull to refresh

Как сохранить и обработать ответ пользователя в telegram боте. (C#)

Пролог

Часто на просторах интернета вижу, как люди сталкиваются с проблемой сохранения последующего ответа пользователя на сообщения бота, когда пишут бота на c#. Например, в библиотеке telebot для python есть отдельный метод register_next_step_handler, который регистрирует следующее сообщение пользователя. Сегодня я подробно разберу реализацию этого на c#.

P.S. Кто и так знает, как работать с базами данных и создавать элементарных ботов, сразу переходите к основной части.

Создание базы данных и элементарного бота

Заходим в Visual Studio, создаём консольное приложение и подключаем нужные пакеты через nuget:

  • Telegram.Bot

  • System.Data.SqlClient

Прописываем нужные директивы в код.

using System.Data;
using System.Data.SqlClient;
using Telegram.Bot;

Далее в обозревателе решений создаём базу данных.

Далее открываем обозреватель серверов (Вид => Обозреватель серверов) , открываем нашу базу данных. В ней нам нужно лишь создать таблицу.

Создаём 2 колонки с типом данных int, называем таблицу и нажимаем "Обновить". Когда таблица создана перейдём к написанию элементарного бота.

В классе Program создаём 2 экземпляра класса:

static TelegramBotClient client = new TelegramBotClient(token);
static SqlConnection sql = new SqlConnection(connectionString);

connectionString находится в свойстве базы данных. (пкм по database1.mdf в обозревателе серверов => свойства => строка подключения/connection string)

в main методе пропишем обработчики на сообщения и запустим приём обновлений (по возможности использовать webhook). В обработчике сообщений создадим экземпляр этого же сообщения.

static void Main(string[] args)
        {
            client.OnMessage += BotOnMessage; //Создаём обработчик событий на сообщение
            client.StartReceiving(); //Начинаем получать апдейты с сервера телеграмма
            Console.ReadKey();
            client.StopReceiving();
        }
async static void BotOnMessage(object sender, MessageEventArgs e)
        {
            Message msg = e.Message; //создаём переменную, которая содержит все свойства сообщения
        }

Шаблон бота готов, можем перейти к основной теме статьи.

Основная часть. Обработка сообщений.

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

Начнём с того, что при вводе /start мы запишем в таблицу идентификатор пользователя и начальное значение второй колонки, пускай будет 0.

if (msg.Text == /start)
{
  if(sql.State == ConnectionState.Closed) // Проверяем, закрыто ли sql подключение
  {
    sql.Open(); //Открываем sql подключение
    SqlCommand command = new SqlCommand($"insert into %Название_таблицы% (%Колонка_1%, %Колонка_2%) values ('{msg.Chat.Id}', '0')", sql); //Прописываем добавление данных в таблицу
    await command.ExecuteNonQueryAsync(); //Выполняем команду
    sql.Close();
  }
}

Потом обработчики на кнопки клавиатуры.

if (msg.Text == "Сумма двух чисел")
{
  if(sql.State == ConnectionState.Closed) //Проверяем состояние подключения
    {
    //Отправляем сообщение, что-бы ввели 2 числа
    sql.Open();
    SqlCommand command = new SqlCommand($"Update %Название_таблицы% Set %Колонка_2% = '1' where %Колонка_1% = '{msg.Chat.Id}'", sql);
    //Так, тут мы установили второй колонке значение 1 (это может быть любое число)
    await command.ExecuteNonQueryAsync();
    sql.Close();
    }
}
if(msg.Text == "Произведение двух чисел")
{
 if(sql.State == ConnectionState.Closed)
 {
   sql.Open();
   SqlCommand command = new SqlCommand($"Update %Название_таблицы% Set %Колонка_2% = '2' where %Колонка_1% = '{msg.Chat.Id}'", sql);
   await command.ExecuteNonQueryAsync();
   //Здесь мы уже присваиваем значение '2'
   sql.Close();
 } 
}

Далее, при поступлении каждого сообщения, нам нужно проверять значение второй колонки у написавшего пользователя. Тогда мы сможем отловить момент, когда у него во второй колонке 1 или 2 и обработать это сообщение. После обработки нужно обратно установить '0' во вторую колонку, что-бы его сообщения дальше не триггерили. В обработчике сообщений напишем вот такой код (этот блок кода должен идти после if(msg.Text == "/start") а также перед остальным кодом).

if (sql.State == ConnectionState.Closed)
            {
                sql.Open();
                SqlCommand command = new SqlCommand($"Select %Колонка_2% From %Таблица% Where %Колонка_1% = '{msg.Chat.Id}'", sql); 
                SqlDataReader reader = command.ExecuteReader();
                await reader.ReadAsync(); 
                count = Convert.ToInt64(reader[0]); //count - обычная int переменная. Мы считали данные с таблицы и присвоили значение второй колонки этой переменной.
                reader.Close();
                sql.Close();
            }

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

if(count == 1)
{
  //Здесь вы прописываете, что хотите. Напрмер, отправляете сумму чисел
  await client.SendTextMessageAsync(msg.Chat.Id, $"Сумма чисел - {Convert.ToInt32(msg.Text.Split(' ')[0]) * Convert.ToInt32(msg.Text.Split(' ')[1])}");
  sql.Open();
  SqlCommand command = new SqlCommand($"Update %Таблица% Set %Колонка_2% = '0' where %Колонка_1% = '{msg.Chat.Id}'", sql);
  command.ExecuteNonQuery();
  //Анулируем вторую колонку.
}

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

Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.