Бот для работы с телеграм (можно управлять шаблоном зенки)

artsmm

Client
Регистрация
03.10.2018
Сообщения
1 136
Благодарностей
196
Баллы
63
Доброго дня всем)
Выкладываю на суд общественности свой шаблон для работы с телеграм ботом.
При нажатии кнопки, шаблон отправляет команду в базу данных. Туда пишется два поля: название кнопки и статус - Yes
Я не нашел как напрямую связать зенку и бота с телеги.
Может вы что-то подскажете.

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

!!Единственно, у меня постоянно сыпятся сообщения, которые должен обрабатывать бот при нажатии кнопок. Пока не поборол данный момент, подумаю как его исправить.

Выложил готовый проект + исходники.
 

Вложения

  • Спасибо
Реакции: dizaynmaks и andropovleva

Zedx

Client
Регистрация
12.06.2018
Сообщения
1 346
Благодарностей
910
Баллы
113
По связыванию с зеннопостером была тема
Но там проблема с вылетанием шаблона при отправке ему команды.

Я вырезал оттуда всё лишнее и оставил только основу как шаблон с парой команд и авторизация по юзерам. Проблемы с лишними сообщениями нет, глянь может поможет
C#:
namespace tg_bot
{
    public class TgBot
    {
        public TelegramBotClient client;

        private string screenshotPath = @"D:\temp";

        string apiKey = "";
        string users = "";         // Comma separated authorized users

        /// <summary>
        /// Начинаем работу бота
        /// </summary>
        /// <param name="project"></param>
        /// <returns></returns>
        public async Task<bool> Start()
        {
            client = new TelegramBotClient(apiKey);
            var me = await client.GetMeAsync();

            Console.WriteLine($@"Бот ""{me.Username}"" запущен", true);

            client.OnMessage += BotOnMessageReceived;
            client.OnCallbackQuery += BotOnCallbackQueryReceived;
            client.StartReceiving(Array.Empty<UpdateType>());
            return true;
        }

        /// <summary>
        /// Обработка входящих сообщений
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="messageEventArgs"></param>
        async void BotOnMessageReceived(object sender, MessageEventArgs messageEventArgs)
        {
            var message = messageEventArgs.Message;

            if (message == null || message.Type != MessageType.Text)
                return;

            if (!CheckAutorized(message.Chat.Username))
            {
                try
                {
                    await client.SendTextMessageAsync(
                        chatId: message.Chat.Id,
                        text: "Недостаточно прав."
                    );

                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Ошибка BotOnCallbackQueryReceived: {ex.Message}", true);
                    return;
                }
                Console.WriteLine($"Неавторизованный пользователь: {message.Chat.Username} написал: {message.Text}", true);
                return;
            }

            Console.WriteLine($"{message.Chat.Username} написал {message.Text}", true);

            string command = message.Text.Split(' ').First();

            switch (command)
            {
                // Любая команда
                default:
                    await MainMenu(message.Chat.Id);
                    break;
            }
        }

        /// <summary>
        /// Основное меню
        /// </summary>
        /// <param name="message"></param>
        /// <param name="onlyWork"></param>
        /// <returns></returns>
        async Task MainMenu(long userId)
        {
            // Создаем массив кнопок
            List<IEnumerable<InlineKeyboardButton>> rowArr = new List<IEnumerable<InlineKeyboardButton>>();

            rowArr.Add(new[]
                    {
                        InlineKeyboardButton.WithCallbackData("CPU", "/cpu"),
                        InlineKeyboardButton.WithCallbackData("Скриншот", "/screen"),
                    });
            rowArr.Add(new[]
                    {
                        InlineKeyboardButton.WithCallbackData("Команда 1", "/test1"),
                        InlineKeyboardButton.WithCallbackData("Команда 2", "/test2"),
                    });
            InlineKeyboardMarkup inlineKeyboard = new InlineKeyboardMarkup(rowArr);

            try
            {
                await client.SendTextMessageAsync(
                    chatId: userId,
                    text: "Список команд:",
                    replyMarkup: inlineKeyboard
                );
            }

            catch (Exception ex)
            {
                Console.WriteLine($"Ошибка SendInlineKeyboard: {ex.Message}", true);
                return;
            }
        }

        /// <summary>
        /// Обработка нажатий Inline кнопок
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="callbackQueryEventArgs"></param>
        private async void BotOnCallbackQueryReceived(object sender, CallbackQueryEventArgs callbackQueryEventArgs)
        {
            var callbackQuery = callbackQueryEventArgs.CallbackQuery;
            if (!CheckAutorized(callbackQuery.Message.Chat.Username))
            {
                try
                {
                    await client.SendTextMessageAsync(
                        chatId: callbackQuery.Message.Chat.Id,
                        text: "Недостаточно прав."
                    );
                }

                catch (Exception ex)
                {
                    Console.WriteLine($"Ошибка BotOnCallbackQueryReceived: {ex.Message}", true);
                    return;
                }
                Console.WriteLine($"Неавторизованный пользователь: {callbackQuery.Message.Chat.Username} нажал: {callbackQuery.Data}", true);
                return;
            }

            Console.WriteLine($"{callbackQuery.Message.Chat.Username} выбрал {callbackQuery.Data}", true);
            string[] callbackArr = callbackQuery.Data.Split('|');
            string task = callbackArr[0];
            string message = "";
            InlineKeyboardMarkup inlineKeyboard = null;

            switch (task)
            {
                // Сделать скриншот
                case "/screen":
                    await GetScreen(callbackQuery.Message.Chat.Id);
                    return;

                case "/cpu": // Узнать загруженность системы
                    float cpu;
                    string freeMemery;

                    //Процессора
                    using (var pc = new System.Diagnostics.PerformanceCounter("Processor", "% Processor Time", "_Total"))
                    {
                        cpu = pc.NextValue();
                        Thread.Sleep(1000);
                        cpu = pc.NextValue();
                    }
                    // Свободно оперативы
                    using (var mem = new System.Diagnostics.PerformanceCounter("Memory", "Available MBytes"))
                    {
                        freeMemery = (mem.NextValue() / 1024.0).ToString("N2"); ;
                    }
                    message = $"Нагрузка на CPU : {(int)cpu}%. \nСвободно памяти: {freeMemery} GB";
                    break;

                default:
                    return;
            }

            // Создаем кнопки управления
            try
            {
                await client.SendTextMessageAsync(
                    chatId: callbackQuery.Message.Chat.Id,
                    text: message,
                    parseMode: ParseMode.Html,
                    replyMarkup: inlineKeyboard
                );

            }
            catch (Exception ex)
            {
                Console.WriteLine($"Ошибка BotOnCallbackQueryReceived: {ex.Message}", true);
                return;
            }

        }

        async Task GetScreen(long userId)
        {
            string fileName = DateTime.Now.ToString("yy.MM.dd_HH.mm.ss") + ".jpeg";
            string path = Path.Combine(screenshotPath);

            try
            {
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                Bitmap printscreen = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);

                Graphics graphics = Graphics.FromImage(printscreen as Image);
                graphics.CopyFromScreen(0, 0, 0, 0, printscreen.Size);
                printscreen.Save(path + fileName, System.Drawing.Imaging.ImageFormat.Jpeg);

                using (var fileStream = new FileStream(path + fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    await client.SendPhotoAsync(
                        chatId: userId,
                        photo: new InputOnlineFile(fileStream, fileName),
                        caption: $"Снимок экрана {fileName}");
                }
            }

            catch (Exception ex)
            {
                Console.WriteLine($"Ошибка GetScreen: {ex.Message}", true);
                return;
            }
        }

        bool CheckAutorized(string userName)
        {
            string[] authorizedUsers = users.Split(',');

            if (!authorizedUsers.Contains(userName))
            {
                return false;
            }
            return true;
        }
    }
}
 
Последнее редактирование:
  • Спасибо
Реакции: MaxMan, Koqpe и artsmm

artsmm

Client
Регистрация
03.10.2018
Сообщения
1 136
Благодарностей
196
Баллы
63
разобрался в чем прикол был, нужно изменить один метод в коде:
C#:
internal void GetUpdates()
        {
            _client = new TelegramBotClient(_token);
            var me = _client.GetMeAsync().Result;
            if(me != null && !string.IsNullOrEmpty(me.Username))
            {
                int offset = 0;
                while (true)
                {
                    try
                    {
                        var updates = _client.GetUpdatesAsync(offset).Result;
                        if(updates != null && updates.Count() > 0)
                        {
                            foreach(var update in updates)
                            {
                                processUpdate(update);
                                offset = update.Id + 1;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }

                    Thread.Sleep(1000);
                }
            }
        }
добавить Offset те, тогда будет не бесконечный цикл, бот будет ждать нажатия кнопок
 
  • Спасибо
Реакции: Zedx

blamingas

Client
Регистрация
14.05.2021
Сообщения
114
Благодарностей
45
Баллы
28
Чтобы шаблон не реагировал на старые сообщения в боте, обрабатывал только свежие, я при отправке сообщений и прослушке ответа забираю из json-ответов параметр Time (он там вида Timestamp - "12345678"). И когда слушаю ответ, беру последнее сообщение (Offset=-1) и просто кубиком Javascript вычитаю - беру его timestamp и отнимаю от него timestamp сохраненный ранее (от предыдущего сообщения, идущего перед циклом прослушки). И через if делаю проверку - если разница >0, значит сообщение новое.
 
  • Спасибо
Реакции: adr1enette и artsmm

artsmm

Client
Регистрация
03.10.2018
Сообщения
1 136
Благодарностей
196
Баллы
63
Чтобы шаблон не реагировал на старые сообщения в боте, обрабатывал только свежие, я при отправке сообщений и прослушке ответа забираю из json-ответов параметр Time (он там вида Timestamp - "12345678"). И когда слушаю ответ, беру последнее сообщение (Offset=-1) и просто кубиком Javascript вычитаю - беру его timestamp и отнимаю от него timestamp сохраненный ранее (от предыдущего сообщения, идущего перед циклом прослушки). И через if делаю проверку - если разница >0, значит сообщение новое.
хороший совет) спасибо) надо внедрить
 

blamingas

Client
Регистрация
14.05.2021
Сообщения
114
Благодарностей
45
Баллы
28
Я не нашел как напрямую связать зенку и бота с телеги.
А ничего связывать и не нужно. Команды в бот можно посылать простыми http запросами в виде url с параметрами внутри него.
Вот, к примеру, пример урла гет-запроса в мой бот. Запрос 1) отправляет сообщение, 2) Рисует в боте панель с кнопками:
HTML:
https://api.telegram.org/bot{-Variable.Work_Bot_Token-}/sendMessage?chat_id={-Variable.default_chat_id-}&text={-Variable.text-}&parse_mode=Markdown&reply_markup={-Variable.Keyboard-}
Читать ответы так же, по урл:
HTML:
https://api.telegram.org/bot{-Variable.Work_Bot_Token-}/getUpdates?offset=-1
(плюс пару кубиков отфильтровки старых ответов)

В обоих случаях приходят json-ответы, которые легко распаршиваются на переменные.
 

artsmm

Client
Регистрация
03.10.2018
Сообщения
1 136
Благодарностей
196
Баллы
63
А ничего связывать и не нужно. Команды в бот можно посылать простыми http запросами в виде url с параметрами внутри него.
Вот, к примеру, пример урла гет-запроса в мой бот. Запрос 1) отправляет сообщение, 2) Рисует в боте панель с кнопками:
HTML:
https://api.telegram.org/bot{-Variable.Work_Bot_Token-}/sendMessage?chat_id={-Variable.default_chat_id-}&text={-Variable.text-}&parse_mode=Markdown&reply_markup={-Variable.Keyboard-}
Читать ответы так же, по урл:
HTML:
https://api.telegram.org/bot{-Variable.Work_Bot_Token-}/getUpdates?offset=-1
(плюс пару кубиков отфильтровки старых ответов)

В обоих случаях приходят json-ответы, которые легко распаршиваются на переменные.
Спасибо за совет. У вас были проблемы при работе бота на сервере? Я вынес на сервер и все, никакого отклика в телеге. Со своего компа когда делаю - все норм
 

blamingas

Client
Регистрация
14.05.2021
Сообщения
114
Благодарностей
45
Баллы
28
Спасибо за совет. У вас были проблемы при работе бота на сервере? Я вынес на сервер и все, никакого отклика в телеге. Со своего компа когда делаю - все норм
На сервер пока еще не переносил, только планирую, но по идее не должно быть никакой разницы.
Я бы начал с проверки на сервере сделать в браузере хттп запрос обычной ссылкой:
Код:
https://api.telegram.org/bot{-Variable.Bot_Token-}/sendMessage?chat_id={-Variable.Chat_id-}&text=BLABLABLA&parse_mode=html

Если ничего не придёт в телегу, значит что-то с ip. Если пришел - смотреть свой код.
 
  • Спасибо
Реакции: artsmm

Zedx

Client
Регистрация
12.06.2018
Сообщения
1 346
Благодарностей
910
Баллы
113
У меня крутится на сервере, никаких проблем нет
 

artsmm

Client
Регистрация
03.10.2018
Сообщения
1 136
Благодарностей
196
Баллы
63
У меня крутится на сервере, никаких проблем нет
по идее - да. Никаких ограничений на сервере не может быть? вроде не установленного asp net и тп ? блокировки какие-то?
 

Zedx

Client
Регистрация
12.06.2018
Сообщения
1 346
Благодарностей
910
Баллы
113
по идее - да. Никаких ограничений на сервере не может быть? вроде не установленного asp net и тп ? блокировки какие-то?
Только если айпишник блокируется со стороны телеграма
 
  • Спасибо
Реакции: artsmm

blamingas

Client
Регистрация
14.05.2021
Сообщения
114
Благодарностей
45
Баллы
28
  • Спасибо
Реакции: artsmm

artsmm

Client
Регистрация
03.10.2018
Сообщения
1 136
Благодарностей
196
Баллы
63
Будете смеяться, но я сам тупанул: оставил незакомментированной команду Console.ReadLine(), а она ждет нажатия Enter, блиииин)))
 

Fastics

Client
Регистрация
13.12.2015
Сообщения
6
Благодарностей
0
Баллы
1
Ребят, а кто-то делал шаблон с использованием С# библиотеки под Telegram?
 

artsmm

Client
Регистрация
03.10.2018
Сообщения
1 136
Благодарностей
196
Баллы
63

Nick

Client
Регистрация
22.07.2014
Сообщения
1 983
Благодарностей
817
Баллы
113

bizzon

Client
Регистрация
08.09.2015
Сообщения
1 103
Благодарностей
132
Баллы
63
А ничего связывать и не нужно. Команды в бот можно посылать простыми http запросами в виде url с параметрами внутри него.
Вот, к примеру, пример урла гет-запроса в мой бот. Запрос 1) отправляет сообщение, 2) Рисует в боте панель с кнопками:
HTML:
https://api.telegram.org/bot{-Variable.Work_Bot_Token-}/sendMessage?chat_id={-Variable.default_chat_id-}&text={-Variable.text-}&parse_mode=Markdown&reply_markup={-Variable.Keyboard-}
Читать ответы так же, по урл:
HTML:
https://api.telegram.org/bot{-Variable.Work_Bot_Token-}/getUpdates?offset=-1
(плюс пару кубиков отфильтровки старых ответов)

В обоих случаях приходят json-ответы, которые легко распаршиваются на переменные.
Ребят, а кто-то делал шаблон с использованием С# библиотеки под Telegram?
А чем лучше с использованием С# библиотеки?
 

blamingas

Client
Регистрация
14.05.2021
Сообщения
114
Благодарностей
45
Баллы
28
А чем лучше с использованием С# библиотеки?
С библиотекой компактнее. Я делал без библы, на post-get запросах в кубиках, когда c# еще не сильно рубил (но переделывать уже не буду, лень), и у меня каждый запрос-прослушка ответа это столбик из 10 кубиков. Бот на 100+ команд с таким подходом внешне выглядит очень тяжелым проектом.
 

bizzon

Client
Регистрация
08.09.2015
Сообщения
1 103
Благодарностей
132
Баллы
63

Кто просматривает тему: (Всего: 3, Пользователи: 0, Гости: 3)