Вступление
Как я и обещал — пишу вторую статью по созданию ботов к известному мессенджеру telegram. В этот раз речь пойдет о языке C# и о создании полноценного бота на нем. И так, начнем, пожалуй.
Шаг первый. Создаем оформление бота через Botfather
В этот шаг я скопировал часть статьи из бота на php, так как тут все действия у нас будут полностью идентичны.
BotFather — это такой бот(официальный), через которого регистрируют все остальные боты. Без него нам никак не обойтись, поэтому давайте откроем telegram и перейдем по ссылке — BotFather
Там все крайне просто, вбиваем /help и смотрим на список доступных команд:
Собственно сейчас нас интересует команда /newbot, пишем ее и создаем бота указывая его название. В данном случае я назову своего бота — Рев.ком.стих и будет он у нас выдавать стихи о Маяковского и Есенина (когда я его доделаю, однако весь процесс в эту статью я включать не буду).
Нам выдадут токен, на скриншоте он замазан в целях…, ну вы сами понимаете. Этот токен нам и нужен, сохраните его куда-нибудь в текстовый файл, он нам еще пригодится.
Далее можно задать оформление для бота. Например картинку — логотип. Для этого используем команду /setuserpic после чего загружаем картинку. Так-же задаются описание бота и прочие вещи до которых вы допрете и без моего участия.
Ну и чтобы проверить установилась картинка или нет переходим на бота вбивая его имя через собачку в поиск
Теперь надо сделать боту доступ к сообщениям пользователей, то есть выключить нахер приватный режим. Если мы планируем добавлять бота в группы или конфы, назовите как хотите, в любом случае приватность нам нахер не нужна. Чтобы ее выключить вбиваем команду /setprivacy после чего выбираем пункт — disabled. Обязательно выполните этот шаг, если вы хотите сделать действительно интерактивного бота.
Теперь самое время заняться backend частью, а именно написанием кода для команд нашего бота, но сначала настроим среду разработки.
Шаг второй. Среда разрабтки
В случае с c# мы будем использовать кроссплатформенную и совершенно бесплатную ide — SharpDevelop в которую уже предустановлены все необходимые для нас плагины такие как nuget package manager. Это во первых экономит мне время, во вторых ресурсы. Тяжелая visual studio тащит за собой кучу уже давно неакутальных и ненужных вещей, да к тому-же платная. Выглядит она конечно приятнее, но для меня такие мелочи не самое главное, мне главное — результат (это нифига не мелочи, Visual Studio 2017 стоит 37 000 рублей).
Короче если у вас не стоит — установите, она весит не много. К тому-же проекты написанные в ней целиком совместимы с visual studio, то есть написанное можно будет потом перенести и туда тоже.
Создаем File->New->Solution
И выбираем тип, так как писать мы будем на C# то выбор очевиден:
И вот среда для разработки у нас готова:
Собственно время устанавливать нужные нам компоненты.
Шаг третий. Установка компонент
В качестве обертки для работы с API мы будем использовать пакет под названием telegram.bot, его мы и будем устанавливать в наш проект. Идем в Project->Manage Packages
Перед нами появится менджер пакетов, который сам найдет нужный нам пакет из интернета, скачает его и установит в ваше приложение для использования. Ищем там наш компонент и тыкаем «Add»:
И вот наш пакет добавился, его видно в solution explorer’е
Отлично, если вы проделали все эти действия то можно переходить уже и к кодингу.
Шаг третий. Написание кода
Собственно для начала сделаем простейший интерфейс. Переключаемся на вкладку MainForm -> Design, после чего кидаем на форму одну кнопку и одно текстовое поле.
Вообще я рассчитываю что у вас есть некий базовый опыт программирования на C#, потому что полностью описывать тут все действия у меня просто не хватит места. В любом случае после оформления стоит перейти к написанию кода.
Для начала стоит вспомнить о главном преимуществе C# — асинхронности. Я буду писать код в двух потоках и в качестве второго потока буду использовать класс BackgroundWorker. Просто создаем переменную этого класса и среда сама предложит нам установить необходимые зависимости.
Да, это еще одна вещ за которую я просто обожаю C#. Мне достаточно знать имя класса, а где он находится система знает и без меня.
Далее добавляем инициализацию нашей переменной в конструкторе класса, а так-же запилим запуск воркера по клику кнопочки.
BackgroundWorker bw;
public MainForm(){
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
//
// TODO: Add constructor code after the InitializeComponent() call.
//
this.bw = new BackgroundWorker();
this.bw.DoWork += this.bw_DoWork; // метод bw_DoWork будет работать асинхронно
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
var worker = sender as BackgroundWorker; // получаем ссылку на класс вызвавший событие
}
void BtnRunClick(object sender, EventArgs e) // обработка клика кнопки
{
if (this.bw.IsBusy != true) // если не запущен
{
this.bw.RunWorkerAsync(); // запускаем
}
}
вот примерно так и должно быть у вас в начале. Теперь нам надо передать токен из текстового поля формы в обработчик воркера и там использовать. Звучит конечно писец как сложно но делается очень просто:
void bw_DoWork(object sender, DoWorkEventArgs e)
{
var worker = sender as BackgroundWorker;
var key = e.Argument as String; // получаем ключ из аргументов
}
void BtnRunClick(object sender, EventArgs e)
{
var text = txtKey.Text; // получаем содержимое текстового поля txtKey в переменную text
if (text && this.bw.IsBusy != true)
{
this.bw.RunWorkerAsync(text); // передаем эту переменную в виде аргумента методу bw_DoWork
}
}
}
Вообще тот кто кодил на C# по больше моего конечно смог бы реализовать это все элегантнее, наверное, но я не из таких. К тому-же далеко не всем известны примочки многопоточности встроенные в этот язык. Там еще есть классы Thread и ThreadPool, а еще полу-асинхронные async и await.
Теперь настало время получения данных из бота. То есть время работы с API телеграма. Собственно инициализация API выглядит так:
var Bot = new Telegram.Bot.Api(key);
Так как мы не используем WebHook то … будем получать обновления бота «вручную», я не знаю как это можно более корректно назвать. Короче раз в секунду телеграм предоставляет ботам информацию о всех сообщениях, которые за это время поступили в бота. Эту информацию можно получать автоматически на https домен, так мы делали на php, а можно получать в бесконечном цикле внутри потока, что мы сейчас и собираемся сделать. Поток у нас есть, осталось сделать цикл и получать обновления. Собственно последнее выполняется вызовом Bot.GetUpdatesAsync(offset) который возврщает массив обновлений начиная с отступа «offset».
async void bw_DoWork(object sender, DoWorkEventArgs e)
{
var worker = sender as BackgroundWorker;
var key = e.Argument as String; // получаем ключ из аргументов
try
{
var Bot = new Telegram.Bot.TelegramBotClient(key); // инициализируем API
await Bot.SetWebhookAsync("");
//Bot.SetWebhook(""); // Обязательно! убираем старую привязку к вебхуку для бота
int offset = 0; // отступ по сообщениям
while (true)
{
var updates = await Bot.GetUpdatesAsync(offset); // получаем массив обновлений
foreach(var update in updates) // Перебираем все обновления
{
Console.WriteLine(update.Type);
offset = update.Id + 1;
}
}
}
catch (Telegram.Bot.Exceptions.ApiRequestException ex)
{
Console.WriteLine(ex.Message); // если ключ не подошел - пишем об этом в консоль отладки
}
}
И так, в цикле мы перебираем обновления, теперь надо взять обновления нужного нам типа, получить их содержимое и обработать. В данном случае давайте обработаем команду «/saysomething», для этого нам надо отловить обновление типа текстовое сообщение и если текст этого сообщения совпадает с «/saysomething» значит выдать в ответ в тот-же чат строчку «тест».
foreach(var update in updates) // Перебираем все обновления
{
var message = update.Message;
if (message.Type == Telegram.Bot.Types.Enums.MessageType.TextMessage)
{
if (message.Text == "/saysomething")
{
// в ответ на команду /saysomething выводим сообщение
await Bot.SendTextMessage(message.Chat.Id, "тест",
replyToMessageId: message.MessageId);
}
}
offset = update.Id + 1;
}
Запустим теперь наше приложение, вставим токен и нажмем кнопку «поехали».
Отлично, а теперь в телеграм-боте вобьем нашу команду и посмотрим придет ли ответ:
Наш бот работает. Без регистрации домена, указания SSL, подключения cloudflare и прочих муторных вещей.
Отправка картинок
Чтобы отправить картинку надо отправить ссылку на нее самому telegram’у, он сам все загрузит и сделает за нас. Заставим нашего бота по команде «/getimage» отсылать нам вот эту картинку.
if (message.Text == "/getimage")
{
// в ответ на команду /getimage выводим картинку
await Bot.SendPhotoAsync(message.Chat.Id, "http://aftamat4ik.ru/wp-content/uploads/2017/03/photo_2016-12-13_23-21-07.jpg","Revolution!");
}
Запускаем, тыкаем кнопочку и тестируем:
С отправкой документов я не буду мучиться потому что тут придется писать OpenFileDialog и прочие вещи описывать на которые тут просто не хватит места, статья и без того длинная.
Задаем список команд
Как это сделать я уже писал и не вижу ни малейшего смысла писать это снова. Просто прочитайте тут.
Ответы на сложные вопросы:
Решил запилить расширенную версию информации по ботам на C# прямо тут. Укажу в кратце сам код, без дополнительного комментирования.
Советую вам сначала скачать исходники внизу статьи и просматривать блоки кода, которые я привожу, прямо на месте!
Inline кнопки и их обработка:
Выводятся кнопки таким кодом:
// inline buttons
if (message.Text == "/ibuttons")
{
var keyboard = new Telegram.Bot.Types.ReplyMarkups.InlineKeyboardMarkup(
new Telegram.Bot.Types.InlineKeyboardButton[][]
{
// First row
new [] {
// First column
new Telegram.Bot.Types.InlineKeyboardButton("раз","callback1"),
// Second column
new Telegram.Bot.Types.InlineKeyboardButton("два","callback2"),
},
}
);
await Bot.SendTextMessageAsync(message.Chat.Id, "Давай накатим, товарищ, по одной!", false, false, 0, keyboard, Telegram.Bot.Types.Enums.ParseMode.Default);
}
Выглядят так:
Обрабатываются так:
// Callback'и от кнопок
Bot.OnCallbackQuery += async (object sc, Telegram.Bot.Args.CallbackQueryEventArgs ev) =>
{
var message = ev.CallbackQuery.Message;
if(ev.CallbackQuery.Data == "callback1") {
await Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id, "You hav choosen " + ev.CallbackQuery.Data, true);
} else
if (ev.CallbackQuery.Data == "callback2")
{
await Bot.SendTextMessageAsync(message.Chat.Id, "тест", replyToMessageId: message.MessageId);
await Bot.AnswerCallbackQueryAsync(ev.CallbackQuery.Id); // отсылаем пустое, чтобы убрать "частики" на кнопке
}
};
Reply-кнопки
Выводятся и обрабатываются таким кодом:
// reply buttons
if (message.Text == "/rbuttons")
{
var keyboard = new Telegram.Bot.Types.ReplyMarkups.ReplyKeyboardMarkup
{
Keyboard = new[] {
new[] // row 1
{
new Telegram.Bot.Types.KeyboardButton("Накатим!"),
new Telegram.Bot.Types.KeyboardButton("Рря!")
},
},
ResizeKeyboard = true
};
await Bot.SendTextMessageAsync(message.Chat.Id, "Давай накатим, товарищ, мой!", false, false, 0, keyboard, Telegram.Bot.Types.Enums.ParseMode.Default);
}
// обработка reply кнопок
if (message.Text.ToLower() == "накатим!")
{
await Bot.SendTextMessageAsync(message.Chat.Id, "Ну, за охоту!", replyToMessageId: message.MessageId);
}
if (message.Text.ToLower() == "рря!")
{
await Bot.SendTextMessageAsync(message.Chat.Id, "Ну, за демократию!", replyToMessageId: message.MessageId);
}
Работают так:
Inline Query — запросы
Обрабатываются так:
// Inlin'ы
Bot.OnInlineQuery += async (object si, Telegram.Bot.Args.InlineQueryEventArgs ei) =>
{
var query = ei.InlineQuery.Query;
var msg = new Telegram.Bot.Types.InputMessageContents.InputTextMessageContent
{
MessageText = @"Это супер крутой текст статьи
с переносами
и html тегами!",
ParseMode = Telegram.Bot.Types.Enums.ParseMode.Html,
};
Telegram.Bot.Types.InlineQueryResults.InlineQueryResult[] results = {
new Telegram.Bot.Types.InlineQueryResults.InlineQueryResultArticle
{
Id = "1",
Title = "Тестовый тайтл",
Description = "Описание статьи тут",
InputMessageContent = msg,
},
new Telegram.Bot.Types.InlineQueryResults.InlineQueryResultAudio
{
Url = "http://aftamat4ik.ru/wp-content/uploads/2017/05/mongol-shuudan_-_kozyr-nash-mandat.mp3",
Id = "2",
FileId = "123423433",
Title = "Монгол Шуудан - Козырь наш Мандат!",
},
new Telegram.Bot.Types.InlineQueryResults.InlineQueryResultPhoto
{
Id = "3",
Url = "http://aftamat4ik.ru/wp-content/uploads/2017/05/14277366494961.jpg",
ThumbUrl = "http://aftamat4ik.ru/wp-content/uploads/2017/05/14277366494961-150x150.jpg",
Caption = "Текст под фоткой",
Description = "Описание",
},
new Telegram.Bot.Types.InlineQueryResults.InlineQueryResultVideo
{
Id = "4",
Url = "http://aftamat4ik.ru/wp-content/uploads/2017/05/bb.mp4",
ThumbUrl = "http://aftamat4ik.ru/wp-content/uploads/2017/05/joker_5-150x150.jpg",
Title = "демо видеоролика",
MimeType = "video/mp4",
}
};
await Bot.AnswerInlineQueryAsync(ei.InlineQuery.Id, results);
};
Выглядят так:
Как я уже говорил, прежде чем разбирать эти примеры — скачайте исходники! Там все поймете сразу же.
Скачать исходники
Без исходников все мои слова были бы бесполезны. Как говорится можно десять раз прочитать и не понять, а можно один раз посмотреть код и все понять. Да, к стати, проект открывается в visual studio, я проверял.

Продолжаете радовать-)
еще бы) заглядывайте
всё очень круто, но я не понял как убрать старую привязку к вебхуку, можешь пояснить??
в код посмотрите внимательно, там это есть
ну или ладно вот скопирую для вас
спасибо!
отличное начало для ботостроения на шарпе
нахера ты пишешь нахера? это так уёбищно выглядит. И это, ты даун или прикидываешься, писать что студия стоит 37 кусков?
Блять с 2015 студии есть community edition которая такая же как про, только бесплатная для простых ребят. И текст прогняй через word, потому что очень много ошибок, читать ужасно.
да, пишу коряво, извините.
а про visual studio я знаю, просто весит она порядка полутора гигов, так что гораздо проще использовать SharpDevelop
Добрый день!
Не могу никак понять, где собственно само тело программы, где весь код? в программ.цс лишь три строки… а сам код то где? как его найти?
Может глупый вопрос.. но все-же
Спасибо!
в исходниках проект для visual studio / sharp develop
там откройте
у меня тот же вопрос, но я не понял, что вы имели ввиду под «в исходниках для вижуал студио. там откройте»
Как сделать inline кнопки и обработчик для них ?????
точно так-же как и в случае с php http://aftamat4ik.ru/bot-dlya-telegram-na-php-knopki-posting-inline-queryes/ в этой статье. Попробуйте адаптировать код.
Я специально вчера открыл ide и переписал варианты решений с php на C#, вот, почитайте
http://aftamat4ik.ru/pishem-bota-telegram-na-c/#ansvers
тут есть и про inline query и про кнопки двух видов и про все остальное. Ничего сложного. Исходники я тоже обновил. Надеюсь эта информация вам поможет.
Ну здравствуй, алёша (специально с маленькой буквы написал). Ты чё мразь? С какого *** ты вообще пиз*** на VS задвигая свои обо***е ide, которые известны тебе одному, бл***ь, а? Есть **** мрази, которые задвигают ху*** на студию (от того, что они ни***я не понимают), есть двуличные мрази, которые пи***т про студию ложную инфу (просто потому что студия «мейнстримчик», а они «не такие как все»). Но одновременно тупорылую и двуличную мразь мне встречать еще не приходилось. Серьёзность ситуации усиливается еще тем, что ты не только тупорылая и двуличная мразь, но еще и упёртая тупорылая и двуличная мразь. Тебя в каментах ткнули рожей в кучу твоего пи****а, как обоссавшегося котёнка, но ты всё равно ра****ся, упорствуя в собственном невежестве. И снова на***л мимо лотка, пи****в, что студия весит «около полутора гигов». Сообщаю, тебе, пи***к, что вес студии разнится в зависимости от устанавливаемых компонентов. Ладно бы ты задвигал за VSC, но за какую=то лютую левую за****у — это уже переходит все границы.
это сообщение прекрасно во всем! Специально публикую его, чтобы показать всем уровень развития юзеров иде, которая все делает за тебя. Даже жопу подтирает. Вы же в нотепаде никогда ничего дельного не писали, у вас готовый вижуал-бейсик с дополнением синтаксиса, на котором даже макака без мозгов может программировать и с# который конечно хорош, но уж слишком прост. Низкий порог входа, и вот всякая школота вроде тебя, начинает срать тут о преимуществах вижуал студии.
Кодер должен писать код. А за вас код пишет IDE.
Так *** ты уёбак тогда бахаешь на C# и PHP? Что ж ты, ***, не на асме кодишь? Приложения получаются быстрые, порог входа высокий. ООП разрабатывалось для того, что бы сделать разработку быстрее. Дотнетфреймворк разрабатывался для того, что бы упростить разработку, там даже указатели инкапсулированы! Мир программирования обязан идти в сторону упрощения разработки, потому что этот путь надиктовывается здравым смыслом. Но всегда найдётся уёбок «не такой как все», который будет исключительно упорно противится этому самому здравому смыслу и просирать собственное время, просто за, понятную только им, идею.
«Разработчику должно быть сложно, он должен рвать букли от напряжения каждый день» — считают они. Почему и как они дошли до такой жизни? *** его знает. Они напоминают мне баб, которых пиздит собственный муж по пьяне каждый день, просто потому что «да ты ох***ла мразь». Они могут бросить нелюбимого мужа, съебать к маме в Липецк и найти нормального мужика, но они терпят, потому что считают это нормой. Я бы и слова не сказал, если бы ты в крысу ебошил на этой обоссаной ideшки в соляного, забившись в угол и потирал сосок удовлетворяя свои БДСМные наклонности. Но ты же, блять, эту хуйню советуешь другим людям и, наверное при этом, сидишь с каменным ебалом за столом и считаешь это нормой. Это нихуя не норма. Хочу сказать тебе огромное спасибо за то, что ты есть и за то, что ты плодишь подобных себе. Пока вы есть у меня всегда будет работа.
какое прекрасное оправдание своего нежелания учить что-то новое и в чем-то разбираться. «Для меня все должно быть просто». «Ваша матиматика слишком сложна для меня! весь мир богу молится, там все элементарно — по воле божьей!». «Ваш с++ слишком сложен! зачем он нужен, если можно открыть иде и понашлепать кнопок!». На поверхности все кажется таким простым. Но с таким подходом ты никогда не сможешь реализовать, например, драйвера. Не сможешь писать код под микроконтроллеры. А за этим будущее ибо грядет роботизация. Уже сегодня к этому надо готовиться, так что ты про асм верно заметил, его надо учить. В любом случае, пока есть такие недалекие недокодеры, сидящие на поверхности и боящиеся заглянуть в глубину, у меня всегда будет работа.
В комментариях к каждому посту на моем блоге вопросы по элементарным вещам, которые задающий, запросто, может и сам вычитать. Но нет. Потому что он сидит на поверхности и ни читать код, ни разбирать сложные проекты не научился. За него всегда все делали формочки. И на все его вопросы отвечали такие люди как я. Блоггеры, опытные кодеры. И нет бы спасибо сказать, свинья еще и гадит матом на чужой площадке! Олзо: что будешь делать там, где формочек нет? М?
Интересно очень, какой у тебя сейчас доход в $, только честно.
если честно я имею абсолютное право не отвечать на такие вопросы.
Читаю давно твой блог,но тут спорно.
Конечно идёт всё в роботизацию, но никто не отменит продукты написанные на том же шарпе, джавке и т.д и т.п.
И конечно никто не будет переписывать программы, ну не выгодно же.
И стоппп, кто сказал, что на том же шарпе нельзя закодить под «микроконтроллер»
Интересно, что же про питочик скажешь?
питон хорош, самому очень нравится. кодил на нем немного, напоминает чем-то… неуловимым джаву. Только хорошую, не тормозящую, удобную джаву, скажем так. Но пока … хм как бы это сказать, до серьезных проектов на питоне руки не дошли, короче.
На самом деле сейчас больше в бигдату все упирается, а не в робототехнику, мне кажется. Здоровые проекты с огромными данными. Но C# дает гораздо более простую поддержку подобных проектов за счет четкой объектной модели и кучи «сахара», делающего код понятным и читабельным. Например, даже в этом проекте все использованные методы абсолютно очевидны и понятны. Честно скажу, с другими языками работал мало, но если сравнивать с js, то небо и земля.
А еще неплохо бы рассказать о механизме работы этого апи, тогда бы половина вопросов о asp сразу же отвалилась. Потому что нугет, как я понимаю, это обертка над массой ajax’ов, причем сервер боту ничего не говорит, в описанном случае, только отвечает и типа никаких вебсерваков тут не надо, просто консолька зацикленая, которая крутится на компе с интернетом.
P.S. И сделай ты валидатор форм на клиенте, нафига гонять на сервер, чтобы потом возвращать ошибку, типа форма невалидна?)
Кто сюда пустил школоту, автор, почему не удаляете эти комментарии?
Мало того, что выбор IDE не предмет этой статьи, так этот мелкий дегенерат позволяет себе сквернословить среди приличных людей=)
Спасибо 🙂 , как на счет того чтобы создать конфу в телеграмме , где можно будет пообщатся с вами , да и друг друг можно будет помочь ????
я подумываю форум запилить, попожже может открою
реквизиты в студию !!!
есть только вебмани — R343924802694
https://botoboom.com/ — Мой скромный каталог для ботов 🙂
Здравствуйте, спасибо за очень полезный урок, я хотел написать своего бота для одного проекта, когда узнал что с помощью C# можно это реализовать обрадовался и пишу вам пару своих вопросов, было бы круто с вашей стороны если помогли бы мне с этим.
1. Каким методом можно получить телефон номер(контакт) пользователя и GPS координаты пользователя(для пользователей моб.клиента телеграма) средствами MVS C#?
2. Как отправить HTTP Post запрос по определенному URL с полученными данными о пользователя средствами MVS C# ?
3.Для того чтобы написанный нами телеграм бот работал и полностью функционировал обязательно ли запускать программу которую мы написали или можно как то это всё автоматизировать ?
Я давно не программировал и не профи в программировании,так что прощу строго не судить если мои вопросы покажутся для вас глупыми.
Если я что то пропустил или забыл ткните пальцем))
Благодарю за ваш ответ за ранее!
За вашу помощь готовь ответит взаимностью(мотанод).
1. про средства mvc php ничего не скажу, а ваще инфу о пользователе можно получить так — https://monosnap.com/file/DmxfFqT2cV2RVdhWLbrPTmPGiBi1Dm, это скрин, можете в исходниках этот участок найти и дописать сами.
касательно GPS — придется вам используя бота просить пользователя указать из какого он населенного пункта. пилить интерфейс, короче. Телега не отправляет longtitude и lattitude, то есть не отслеживает своих … пользователей.
2. гуглите, а ваще вот — https://stackoverflow.com/a/8091963/2574125
3. можно автоматизировать если у вас конкретно на ASP.net все написано, но перед этим, разумеется, придется написать само приложение сайта и установить его на сервер. Хз как это делается в ASP я с ним не связывался, а на C# пишу короткие скрипты для десктопа и работы с файлами в основном, то есть это для меня такой системный язык, в вебе я его не использую.
Привет. У меня вот такая ошибка вылазит, что делать?
https://image.prntscr.com/image/gbQt4yluSHGJE4Nbrqv5Gg.png
хм, у вас .net точно последней версии? Если есть проблемы, как тут и советуют, попробуйте в Visual Studio сделать.
Вижл у меня только 2010 года.
хм, то есть .net старый… не знаю запустится или нет…
Вроде на сколько я знаю, для апи телеги нужен нет 4.6.1
Плохая практика оборачивать в try catch всю программу.
с этим не поспоришь
Почему когда несколько раз вызываешь inlain и по кнопки инлайн выводишь сообщение, это сообщение дублируется столько раз сколько был вызван инлайн ???
как это исправить ?
после отправки сообщения — выходить из функции(return’ом, например)
Все равно не понимаю
Bot.OnCallbackQuery += async (object sc, CallbackQueryEventArgs ev) =>
{
message = ev.CallbackQuery.Message;
if (ev.CallbackQuery.Data == «кнопка1»)
{
await Bot.SendTextMessageAsync(message.Chat.Id, «нажата 1 «);
return;
}
else
if (ev.CallbackQuery.Data == «кнопка2»)
{
await Bot.SendTextMessageAsync(message.Chat.Id, «нажата кнопка 2»);
return;
}
};
Если я вызываю инлайн 1 раз нажимаю на кнопку 1 выводится — нажата 1
Если я опять вызываю инлайн и нажимаю на кнопку 1 то выводится — нажата 1 нажата 1 ; и так далее
создайте выше переменную bool is_mesage_sent
после отпрвки сообщения присвойте is_mesage_sent = true
в начале функции отправки сообщения добавьте if(is_mesage_sent == true) return;
Спасибо помогло, хороший пример и админ человек)
А у меня еще такой вопрос, я увидел бота у которого у которого сообщения бота заменяются на другие, как такое реализовать?
надо сохранить айди месседжа в базу, потом взять его оттуда и изменить… короче вот, это я на php делаю, но на c# так-же будет, примерно
///
/// Выполняет подключение к аккаунту ВК и одновременно информирует
/// пользователя об успехе данного процесса.
///
public static async Task WaitForConnection(TelegramBotClient Bot, Telegram.Bot.Types.Message msg)
{
var result = await Bot.SendTextMessageAsync(message.Chat.Id, «Выполняется процесс подключения аккаунта…», replyToMessageId: message.MessageId); //сохраняем отправленное сообщение в переменную result
var authorized = true; //await VK.VkAuth(«login», «password»); — какая-то функция
if (authorized)
{
await Bot.EditMessageTextAsync(message.Chat.Id, result.MessageId, «Подключение успешно завершено.»); //указываем в параметрах ID чата и ID сообщения, которое хотим изменить
}
}
ну вообщем id нужного сообщения по получаю так: Бот отправляет сообщение (команду) и потом ПОСТ , я на этой команде получаю id и прибавляю 1 и получаю id поста.
Но вот проблема с самой функцией edit на C# я примеров не нашел, искал на githab и гуглил ( один петон и пыха)
я использую функцию вот так (
mes_id = mes_id + 1;
ParseMode parseMode = ParseMode.Default;
System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken);
await Bot.EditMessageTextAsync(user_idi, mes_id, «Партнерская», parseMode, false, null, cancellationToken);
)
В итоге программа останавливается и выдает ошибку: необработанное пользователем исключение
Telegram.Bot.Exceptions.ApiRequestException: «Bad Request: object expected as reply markup»
Пожалуйста подскажите что не так как исправить ?
вообщем нашел пример осталось разобраться, если вдруг кому надо то вот
await Bot.EditMessageTextAsync(user_idi, mid,
«نام کاربر», ParseMode.Html, false,
new InlineKeyboardMarkup()
{
InlineKeyboard = new InlineKeyboardButton[][]
{
new InlineKeyboardButton[]
{
new InlineKeyboardButton
{
Text = «موافقم»,
CallbackData = «Accept»,
SwitchInlineQuery = string.Empty,
Url = string.Empty
},
new InlineKeyboardButton
{
Text = «مخالف»,
CallbackData = «Denid»,
SwitchInlineQuery = string.Empty,
Url = string.Empty
}
}
}
});
А как сделать проверку на администратора и создателя группы? Иначе говоря нужно написать что-то вроде if (пишет создатель или администратор группы) { то выполняем заданный тут код }. Если можно, напишите пример.
хз, копайтесь в объектие message.Chat и производных от него. Там должно быть чо-то типа информации о юзере, отправившем сообщение. Вот его и крутите.
Нашел похоже на правду тут: Telegram.Bot.Types.Enums.ChatMemberStatus.Administrator но как прописать условия не пойму. Может подскажете.
хм, копайтесь, студия сама иногда дает подсказки.
Да уже вроде бы все вариант перебрал. Сюда уже пишу как жест отчаяния. Видимо, придется ограничения ставить по юзернеймам(
Добрый день! Не понимаю как сделать отправку формы с telegram бота на почту?
И как обработать: 429 (Too Many Requests)
Написал:
catch (System.Net.Http.HttpRequestException ex)
{
if (ex.Message.Contains(«429 (Too Many Requests)»))
{
Thread.Sleep(100000);
}
Console.WriteLine(ex.Message);
}
Всё равно выдает ошибку.
я тут где-то же отвечал на такое. Создайте переменную в боте, например так var trigger = false;. После обработки отправки сообщения эту переменную сделайте trigger = true; и перед отправкой сообщения сделайте if(trigger == true) return;
как-то так.
Что-же до отправки почты, то вам надо SMTP, можете почитать тут — https://stackoverflow.com/questions/9201239/send-e-mail-via-smtp-using-c-sharp
Спасибо за совет!
Подскажите как отправлять смайлы?
у вас телеграм есть? выберите там смайл, вставьте его в поле отправки сообщения так: http://take.ms/GrYpc (скрин)
после чего выделите и скопируйте — http://take.ms/r3mFg и вставьте. ?
это будет работать только в браузере или в телеграме. в текстовом редактре вы получите квардатный значек с вопросом, но не парьтесь, все так и должно быть.
Спасибо!!!
Что делать если в Manage Packages не находит Telegrum.Bot?
попробовать поставить visual studio или скачать проект с моего сайта и юзать его.
Доброе утро! Как можно сформировать Inline-кнопки для перехода по страницам?
Допустим есть текст и снизу кнопки, при нажатий одной из кнопки(далее или же назад) он просто менял текст не отправляя новое сообщение.
Видел реализацию этого на python (https://kostya.co/bot-keyboards-inline/)
await Bot.EditMessageTextAsync(message.Chat.Id, ev.CallbackQuery.Message.MessageId, «Измененный текст»);
Доброго времени суток, скачал исходники, не понимаю что нужно ввести, чтобы получить вот это http://aftamat4ik.ru/wp-content/uploads/2017/03/inline-telegram-zapros.png
через @имя_вашего_бота + пробел, вот так, например — http://take.ms/iQJyN
Не работает. Наверное это связано с тем, что библиотеки не обновлены.
Нужно включить режим inline в ботфадере
Не пойму, как написать условие, когда фраза начинается с заданной фразы, а не является вхождением внутри текста.
Например, message.Text.ToLower().Contains(«кто это») сработает на любое вхождение «кто это» внутри текста. То есть это условие сработает, даже если я напишу «блаблаКТО ЭТОблабла». А как написать условие, чтобы оно сработало только в том случае, если наше сообщение в чат начинается с фразы «кто это»? Иначе говоря, чтобы на «блаблаКТО ЭТОблабла» не сработало, а на «кто это блаблабла» сработало.
А как сделать автоотправку сообщений из бота пользователям?
сохранить чат-id каждого пользователя в базу или в файл какой-нибудь, а потом просто проходиться по всем значениям и отпрвлять в эти чат-ид сообщения.
Это то понятно, но как сделать отдельно от всего этого по кнопке или таймеру? Есть ли простой пример?
Сделал с помощью web
WebRequest req = WebRequest.Create(«https://api.telegram.org/bot» + txtKey.Text + «/sendMessage?chat_id=» + «123123123» + «&text=» + text);
req.GetResponse();
req.Abort();
Новый вопрос)) как зная номер телефона отправлять сообщения в тот же чат?
номер телефона не нужен. нужен чат-ид, без чат ида нельзя отправить сообщение.
Ок) и можно последний вопрос, как работать с ботом через прокси?)))
Прокси? Через эту библиотеку врятли получится. Как вариант, можете установить прокси для всего пк и тогда они будут работать и для приложения тоже.
Кому может пригодится, у меня получилось с работой через прокси так:
Настройка прокси через «Свойства браузера»,
В программе в app.config дописать:
Подскажи пожалуйста как мне оправить сообщение с бота, юзеру по номеру телефона или по логину!
никак. вы можете писать только тем пользователям, которые общались с вашим ботом. Можете сохранть в базу chatid этих пользователей и потом уже по этому иду писать сообщения.
Привет, буду очень благодарен, если ответишь!
Как получать геопозицию пользователей в реальном времени ? это 100% возможно, но как я пока не знаю
https://stackoverflow.com/questions/37983272/telegram-geolocation
ну вот тут написано, что все не так то просто.
Я уже разобрался, все довольно просто, нужно шарнуть геолокацию в реал тайме в чат с ботом, поймать id этого обновления и потом просто проверять это обновление постоянно, и брать от туда 2 точки X и Y, нужен будет код стучите на почту [email protected]
Салют асушник, есть проблема. Сталкивался ли ты с подобной ошибкой и как ты считаешь где искать решение.
//
if (message.Text == «/getpic»)
{
string sunRick = «http://aftamat4ik.ru/wp-content/uploads/2017/03/photo_2016-12-13_23-21-07.jpg»;
await Bot.SendPhotoAsync(message.Chat.Id, sunRick ,»» );
}
//
Когда в поле для аргументов помещаю ссылку, происходит ошибка связанная с преобразованием переменных.
Ошибка заключена в том, что «string » в «Telegram.Bot.Types» нельзя переслать.
Я не силен в «.Net» библиотеках и работы с ними, может что-то не прописал в инклюдах.
Дословно ошибка выглядит так:
«(локальная переменная) string sunRick
Аргумент 2: не удается преобразовать из «string » в «Telegram.Bot.Types.FileToSend».
С уважением, error.
Все решил проблему, пока не полез внутрь.
if (message.Text == «/getpic»)
{
FileToSend fl;
Uri sunRick = new Uri(@»http://aftamat4ik.ru/wp-content/uploads/2017/03/photo_2016-12-13_23-21-07.jpg»);
fl.Url = sunRick;
await Bot.SendPhotoAsync(message.Chat.Id, fl, «» ); //(message.Chat.Id, «»)
}
хм, спасибо, что поделились решением) Нет я с подобной ошибкой когда писал не сталкивался.
Доброго времени суток. Действительно, сработало. Но, а если ссылок на картинки несколько?
в цикле перебор сделайте
Приветствую! Замечательная статья. Единственная, которую я смог освоить и что-то сделать, но почему не рассматривается простейшие команды работы с базой данных? Как ее правильно подвязать к экземплярам чата?
Спасибо) В будущем напишу статью по работе с базами данных на C#, когда наконец новый комп ко мне придет и я там все настрою.
Хорошая статья, спасибо!
Подскажите, вы не пробовали с в помощью нажатия callbacl кнопки обновлять клавиатуру? Например, сделать клавиатуру в виде календаря и иметь возможность менять год.
конкретно на C# не пробовал, на php делал такое. Вам нужен метод что-то типа updateMessageMarkup или как-то так, советую поискать его в автоподсказках
Как его остановить теперь?
this.bw.WorkerSupportsCancellation = true;
и
this.bw.CancelAsync();
не останавливают поток
чтобы остановить поток надо из него выйти через return; Или заюзать метод thread.Abort — https://stackoverflow.com/questions/14131608/how-to-terminate-a-thread-in-c
или вот — https://stackoverflow.com/a/14419540
А вообще статью под 14 версию бота есть возможность переписать?)))
А как получить картинки/видео что отправляют пользователи?
Привет. А как через FileToSend отправить картинку которая находится на компьютере?
хз, не знаю, вероятно вам придется загрузить файл куда-то к себе на внешний домен.
Подкорректируй под документ
await Bot.SendChatActionAsync(message.Chat.Id, ChatAction.UploadPhoto);
const string file = @»Files/tux.png»;
var fileName = file.Split(Path.DirectorySeparatorChar).Last();
using (var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read))
{
await Bot.SendPhotoAsync(
message.Chat.Id,
fileStream,
«Nice Picture»);
}
Был бы супер пост про то, как добавить реферальную систему в бот телеграма. В инете такая инфа сейчас отсутствует.
первый раз о таком слышу
Делаешь бд пользователей, уникальный идентификатор пользователя, приходящий может ввести этот идентификатор и в бд они станут привязанными)
год назад писал бота для диплома на основе этой статьи, а сейчас вижу что в 2018м все продолжают писать комментарии, круто
добрый день
выдаёт ошибку ‘Newtonsoft.Json’ already has a dependency defined for NETStandard.Library при подключении пакета Telegram.bot
что можно сделать. пробовал разные версии, всё то же
значит у вас система 64-х битная. Поставьте вижуал студию и соберите пример оттуда.
Спасибо.
Салют Автор, есть очень интересный и думаю важный момент для кто хочет стабильности в сие коде.
К примеру «Соединение прервано» и у нас вылетает ошибка на строчке в получении обновлений.
_
var updates = await Bot.GetUpdatesAsync(offset); // получаем массив обновлений
_
ошибка заключена в трех экзепшинах.
System.Net.Http.HttpRequestException: «Произошла ошибка при отправке запроса.»
WebException: Базовое соединение закрыто: Непредвиденная ошибка при приеме.
И как сделать так, хотя бы чтобы приложение в MessBox выкинуло это исключение и останоила работу до перезапуска, за ранее спасибо.
Поспешил, но реализовал пока изменив код, убрал ОшибкуАпи в кэтче., поменял на
ок, спасибо за правку)
Полез значит дальше, как думаеш достаточно ли просто таким образом остановить bw
catch (HttpRequestException ex)
{
MessageBox.Show(ex.Message.ToString());
bw.WorkerSupportsCancellation = true;
this.bw.CancelAsync();
}
отмена асинхронности вызовет поддтормаживания. Лучше просто return юзнуть в нужном месте, чтобы выйти из обработчика.
Попробую оба варианта, посмотрю как поведет система.
За оперативно лайк тебе.
Интересный момент ещё , в коде бота, идёт постоянный запрос на новые сообщения, в цикле.
while (true)
{
var updates = await Bot.GetUpdatesAsync(offset); // получаем массив обновлений
//…
}
Идёт постоянный запрос , без задержек, мен смущает что реализовано без задержки хотя бы в одну секунду
Вопрос:
стоит ли ее тормозить?
и если да, то были ли случаи в проектах, когда лучше постоянный запрос в контроль какой-то взять, а не в задержу в пару мс?
Чисто нужно мнение.
не стоит, он не начнет следующий цикл пока не закончит предыдущий, то есть пока все не обработает.
Просто всегда смущает «долбежка» с интервалом маленьким. Скорее моя придирчивость основывается в незнании поведения половины функций.
долбежка это не страшно ибо лимиты телеграма повзоляют обрабатывать до 30 запросов в секунду, что… достаточно дохуя.
Вопрос на счёт лимитов. 30 в секунду это на все запросы входящие + исходящие? И второй вопрос, сколько символов поддерживает одно исходящее сообщение? Кто ни будь знает?)
Да, и что будет при превышении кол-ва запросов? Ошибка программы или сервер будет постепенно их обрабатывать?
Круто что ты в курсе нюансов , складывается впечатление что помимо официального Bot API, от телеграмма, будто есть ещё источники или описание большого опыта в использовании на другом языке.
лимиты — https://core.telegram.org/bots/faq#my-bot-is-hitting-limits-how-do-i-avoid-this
+ в методах в самих написано, но да, написано не все. Например у sendMessage есть лимит по тексту в сколько-то там символов, хз даже в сколько, но тут не указан — https://core.telegram.org/bots/api#sendmessage
но зато указано, что файлы не могут быть больше 50 мегабайт и прочее.
Нашел) Ограничение в 700 символов
Доброго времени суток!
Написал своего бота по примеру из вашей статьи, но в виде обычного консольного приложения. Все отлично работает но есть вопрос.
Как залить бота на хостинг, чтоб он работал постоянно, не зависимо от моего компьютера? Пробовал залить на Azure и на somee.com, но ничего так и не заработало. В интернетах нормального мануала тоже не нашел. Что посоветуете?
вам нужен windows хостинг + войти на этот хостинг из-под «подключения к удаленному рабочему столу windows». Залить своего бота в папку юзая FTP, потом через рабочий стол открыть эту папку, включить бота, свернуть или добавить в автозагрузку. PROFIT.
проблема решилась генерацией нового токена авторизации. Спасибо
каким образом добавить туда свои изображения, аудио и видео? я так понимаю, у Вас все привязано к сайту
залить на любой бесплатный хостинг и получить ссылку
Исключение типа «System.Net.Http.HttpRequestException» возникло в mscorlib.dll, но не было обработано в коде пользователя. Ничего толком не меняла, всё работало нормально, попробовала свою ссылку вставить и тут такое, теперь постоянно. Как исправить?
видимо что-то со ссылкой не в порядке
Добрый день! Попробовал запустить Ваш проект со своим ботом. Возникла ошибка соединения. Видимо, блокировка работает. Что дописать в коде, чтобы обойти. Или невозможно, так как библиотека не своя?
да блокировка работает, этот бот врятли запустится в снгшных системах
Как получить доступ к боту в условиях блокировки провайдером Телеграма. IP адрес внутри библиотеки зашит.
хз даже, думаю вам к автору библиотеки надо обращаться в такой ситуации
При запуске ругается на //await Bot.SetWebhookAsync(«»);
Пишет ошибку System.Net.Http.HttpRequestException.
Проблема в РКН?
да там косяк. сделайте так
Так ошибка пропадает, но бот не откликается.
всего одно слово. роскомнадзор.
Здравствуйте, сделал в телеграм бот метод отправки картинки из интернет ресурсов. Проблема в том что с любого сайта картинка загружается без проблем, а вот именно с какого нужно мне сайта не грузит пишет ошибка 400 недопустимый запрос. В браузере эту картинку нормально грузит в постмане тоже и даже если просто скачать картинку через программу то тоже скачивает ее нормально а вот как доходит дело чтобы послать ее в бот то возникает ошибка
ну это уже вам с программой загрузки надо работать, это же к боту непосредственно не относится. Возможно не подходит формат картинки или ее размер.
У меня упорно не устанавливалось соединение с серверами Телеграма, получал ошибку The request was aborted: Could not create SSL/TLS secure channel.не удалось создать безопасный канал SSL / TLS. (System.Net.WebException: Запрос был прерван:
Не удалось создать защищенный канал SSL/TLS.)
Решилось:
В Program.cs добавить
using System.Net;
там же
В public static void Main(string[] args)
добавить в начале
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
спасибо, что поделились