У моего заказчика случился один инцидент. Ну, как инцидент, обычная житейская история. У него в компании есть девушка (или женщина, все относительно), которая следит за днями рождений сотрудников, собирает деньги на подарок и т.д., короче, Шура – профсоюзная активистка из «Служебного романа» (помните?: «… если сегодня кто-нибудь еще родится или умрет, я останусь без обеда…»), только помоложе и без профсоюза.
И вот однажды подходит эта «Шура» к одному из сотрудников и просит его помочь ей поднять на этаж пиццу.
Тут, конечно, началось… в спешке, пока «Шура» и «Шурик» исчезли в направлении пиццы, торопливые сборы ассигнаций, в ближайший цветочный ларёк направлялся гонец,
и воздухе витала мысль: «Просрали полимеры день рождения девушки, которая о каждом из нас не забывала»…
Дабы не попадать в следующий раз впросак, заказчик попросил меня написать для их корпоративного Telegram чата некую программку, которая бы утром поздравляла тех, у кого день рождения (в компании около 200 человек), а за три дня до дня рождения персонально направляла каждому сотруднику группы/отдела, в котором работает будущий именинник, telegram-сообщение о грядущем событии.
«Деньги в руки – будут звуки». Что в результате получилось? Есть чат, в котором сотрудники обсуждают разные вопросы, в нем каждое утро в 9-00 появляется средних размеров сообщение на тему «10 знаменитых людей, родившихся в этот день». Если в «этот день» родился кто-то из компании заказчика, то этот кто-то оказывается в компании знаменитостей. Такой вот каламбур. Также индивидуально некоторые сотрудники получают сообщение от бота «Шура – профсоюзная активистка» о ДР за три дня до «грустного праздника».
Вот, такая преамбула.
Для реализации поставленной задачи я использовал API Telegram, c# и серверную инфраструктуру заказчика на платформе Microsoft.
После создания заказной разработки на c# и .Net мне пришла в голову мысль: а можно ли запилить Telegram бот на VBA? На странице «Bot Code Examples» VBA среди множества языков нет, но ведь это не означает, что на нем нельзя написать бот для «телеги».
Попробую в этом посте заполнить брешь. Сначала нужно сделать то, что делается для любого языка программирования – создать и прописать бота.
Общая часть закончена. Теперь специфика Visual Basic for Application.
Попробуем отправить сообщение на VBA:
Sub SendAMessage2TheTelegram() Dim xmlhttp As New MSXML2.XMLHTTP60, url As String, response As String Dim msg As String Dim BotToken As String, ChatID As String ChatID = "0987654321" BotToken = "1234567890:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" msg = "Hello from VBA Excel" url = "https://api.telegram.org/bot" & BotToken & "/sendMessage?chat_id=" & ChatID & "&text=" & msg xmlhttp.Open "POST", url, False xmlhttp.Send ' В ответ придет JSON с информацией об успехе выполнения команды response = xmlhttp.ResponseText Debug.Print response End Sub
Конкретно этот код работает. Проблема возникнет, если вы попытаетесь отправить сообщение на русском языке. В этом случае от Telegram вы получите ответ: «Bad Request: strings must be encoded in UTF-8».
У VBA, к сожалению, нет встроенной функции перевода в требуемый формат. Что же делать? Что же делать? Надо выпить.
Можно придумать свой собственный велосипед на тему: «URL Encoding», - в соответствии с RFC-3986, можно найти на просторах интернета множество
чужих велосипедов разной степени глючности и «доработать напильником», но я бы предложил велосипед не изобретать, а воспользоваться функцией
JavaScript encodeURIComponent(), она заменяет «неправильные» символы процентными (escape-) последовательностями, представляющими кодировку символа UTF-8.
Public Function EncodeUTF8(str As String) Dim ScriptEngine As Object Set ScriptEngine = CreateObject("ScriptControl") ScriptEngine.Language = "JScript" EncodeUTF8 = ScriptEngine.Run("encodeURIComponent", str) End Function
Это окошко в возможности JavaScript меня уже неоднократно выручало.
Соответственно, функция SendAMessage2TheTelegram будет выглядеть так:
Sub SendAMessage2TheTelegram() Dim xmlhttp As New MSXML2.XMLHTTP60, url As String, response As String Dim msg As String Dim BotToken As String, ChatID As String ChatID = "0987654321" BotToken = "1234567890:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" msg = "Привет из VBA Excel - Послать сообщение в Telegram - это просто!" msg = EncodeUTF8(msg) url = "https://api.telegram.org/bot" + BotToken + "/sendMessage?chat_id=" & ChatID & "&text=" & msg xmlhttp.Open "POST", url, False xmlhttp.Send ' В ответ придет JSON с информацией об успехе выполнения команды response = xmlhttp.ResponseText Debug.Print response End Sub
Теперь сообщения с русскими буквами прекрасно перевариваются Telegram API. Отдельный вопрос: как узнать id чата, если речь идет о группе или даже конкретной персоне, а не о канале?
Для этого нужно отправить какое-либо сообщение боту из чата, в который вы планируете отправлять сообщения бота.
Например, такое: «/myid @UserNameOfMybot».
После чего посмотреть на историю сообщений бота с помощью команды, которую можно отправить из, например, Google Chrome:
https://api.telegram.org/bot1234567890:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/getUpdates
Посмотреть на последние строчки истории и найти собственное сообщение в структуре JSON. Там должен быть и такой фрагмент: "chat":{"id": 123456789. 123456789- на месте этих цифр должен быть ID чата для переменной ChatID.
Изначально я думал создать на c# com компонент для VBA, с большим набором функций по работе с Telegram. Но нужен ли такой com-компонент? – я пока не решил. Так что этот вопрос тоже можно обсудить.