How to build a Telegram Bot using PHP? — Absolute beginner guide
You are reading this, so you very well know chatbots are playing a major role in today’s businesses in the field of customer relationships. However, when it comes to Telegram, bots are used for fun(Gif, Memes sharing, etc), knowledge sharing(News, Live updates, YouTube videos, etc), and for performing easy quick tasks(File storage in the cloud, Wikipedia search, Polls, etc).
What if I tell you, creating bots in Telegram is super easy? Yeah! If you’ve read several blogs and still not yet clear on how to start building or if this is the first blog that you’re reading on building Telegram bots, then you’re at the right place!
Requirements:
* Basic understanding in PHP programming will be helpful.
One with no knowledge in PHP can also read this blog and try building bots, if the working of code in this blog is understood
Tell Me a Joke!
Let us create a simple bot named, “Tell Me a Joke!”. This bot throws us random jokes every time we ask for it, so when you feel the conversation with your friends’ gonna end, tell them a joke instantly and keep the conversation going with fun!
Try using this bot, so you get a clear idea on what we are gonna build!
How do telegram bots work?
It is a must to know how the background process works. To keep it more simple, Assume a user sends a message, let’s say “Tell me a joke” to your bot. Your bot then sends this information to the Telegram API(or Bot API). This Telegram API is responsible to send this information to where your PHP code is. Your PHP code will be hosted somewhere, so this Telegram API sends information to your PHP file using your domain name(www.xyz.com/myphpcode.php). Your PHP file has that piece of code to generate a random joke. After your code generates a random joke, this joke is sent back to Telegram API. And finally, the Telegram API sends the joke back to the user as a message.
Telegram allows sending information via Telegram API(Bot API) just to make sure if the bot is an authorized one.
It checks this with a unique token you get while you create a new bot.
Now that you understand how bots in Telegram work, we’ll get started in building a bot in just 3 steps!
Step 1
⦿ Open the Telegram app, and search for “@BotFather “. You’ll get a verified bot result. Open it.
⦿ Type “/newbot “. Give any name to your bot. I’ll name it “Tell Me a Joke!”. Next, you should choose a unique name for your bot. I’ll give “tell_me_a_joke_bot”. Your bot is now created. You can find your bot from anywhere using:
Step 2
Now that you have created a new bot, it’s time for creating Webhooks. As mentioned earlier, whenever users send a message to the bot, the bot sends this info to Telegram API. But, what does Telegram API do next? Well, it gives you two choices:
1) You can configure Telegram API to send this info immediately to your PHP file, or 2) It keeps the info with it, and whenever your PHP file asks the Telegram API for info, it gives info to PHP file.
For real-time communication, we need immediate responses from the bot, don’t we? So, we go for the first option and it’s called “Webhook”. This sends info to our PHP file automatically when users send messages to the bot.
To set Webhook, all you need to do is, have a hosted PHP file with SSL certified domain name(Try Glitch).
Just open any browser and type the below URL:
If everything works fine, your browser shows this JSON response:
The Webhook is now set!
Step 3
It's time to code! What do we need in our code?
- Get user details (User name, ID, the message that the user has sent).
- Generate a random joke if the message is “Joke” or “Tell me a joke”.
- Send the joke to the user via Telegram API.
When a user sends a message, the Telegram API sends the info to the PHP file in JSON format as shown below:
From this JSON object, you need to get Chat id, First Name and Text message. You can simply do that in PHP by:
If the message contains the word “joke”, we are gonna fetch a random joke from any joke providing website via API call. I’m using icanhazdadjoke.com to fetch a random joke.
For those who don’t know curl functions used in the above code, refer below:
Our code issues a GET request to the server of icanhazdadjoke.com and receives the document it asked for(A random joke). icanhazdadjoke.com needs user-agent to be added in HTTP header to know who’s requesting for jokes. So, the CURLOPT_USERAGENT parameter is used to show my website name to icanhazdadjoke.com. The joke should be sent by icanhazdadjoke.com in JSON format. So, we used the CURLOPT_HTTPHEADER parameter and set “application/json”.
For those who don’t know the json_decode function used in the above code, refer below:
The json_decode() function is an inbuilt function in PHP that is used to decode a JSON string response. It converts a JSON encoded string into a PHP variable. Now $json variable will be having the below JSON with it:
To fetch joke alone, we used $joke = $json[“joke”].
And finally, to send the joke to the requested user, we can use the URL provided by Telegram, which is:
The overall PHP code:
And here’s the work!
The Working
Start building your Telegram bot now! Also, there are many other features like inline mode, commands, adding your bot to groups, and much more.
Hope you liked it! Give it a and share it with who are really interested in building bots!
Бот для телеграм на php. Подробная инструкция
На данный момент telegram развивается очень активно и является одним из популярных мессенджеров, охватывающих огромную аудиторию. Одной из особенностей данного приложения является наличие ботов, выполняющих различные функции. К таким функциям относятся онлайн-чаты, информирование пользователя (например, о новой записи в блоге), различные игры или помощь пользователю в различных аспектах.
В этой статье будет рассказано о том, как создать самого простого бота на языке php.
А теперь перейдем подробнее к пошаговой инструкции, рассказывающей как создать бот для телеграм на php.
0. Подготовка
Самым первым делом необходимо отметить, что Телеграм позволяет размещать ботов только на доменах, защищенных сертификатом SSL. Если у вас еще нет такого сертификата, вам необходимо его приобрести. Возможно, вам также понадобится хостинг для размещения файлов бота. Для этих целей прекрасно подойдет хостинг от компании Бегет, предоставляющий бесплатные сертификаты. О его преимуществах подробно я расписал в этой статье .
Build a Telegram bot in PHP
Telegram is one of the two cool kids on the messaging app market right now. Especially since the recent upset with WhatsApps new data sharing policy the user numbers have positively skyrocketed. There’s now over 500 million people using the app.
Personally I’ve been using it since 2015. Since 2018, I’ve used it for 95% of my daily communication. During that time I also found out that Telegram has a really cool Chat Bot API! So I’ve built a few.
- One keeps track of my appointments and sends reminders
- One tracks shipping goals for a chat group of my friends
- One that checked who in the group got made fun of the most
- One that tracks some metrics of my company (audience growth, . )
Today, I’d like to teach you how to do the same. Because a future where we all have a personal army of automated chat robots is definitely one I want to live in!
Prerequisites
To follow along with this article you’ll need only two things.
- A working installation of PHP 7.2+ and Composer
- The Telegram app and an account
To create our bot, we need a special token from Telegram itself. We can get this from an automated bot, too! It’s called @BotFather and it will guide you through the setup process. So let’s do that now!
BotFather is quite the wordy chap.
Congratulations! You have set up your first Telegram bot. Be sure to note down that token from the last message. We’ll need it in a few minutes. You can also further customize your bot with a profile image and such. I’ll leave that up to you.
Setting up your PHP project
Now it’s time to get down to the actual core of this project: Implementing the chat bot. We’ll start as with any good PHP project in $CURRENT_YEAR : By setting up a Composer project.
While we could directly deal with the HTTP API of Telegram, there is a very nice library already built for us by Irfaq Sayed. So let’s grab that too!
For any Laravel fans: This library also provides a facade. Super neat!
Then it’s time to define our directory structure. When I build Telegram bots, I generally follow a structure that looks like this:
First we have our regular files as generated by Composer.
src/ is the folder where we place all of our commands and other application-specific code.
public/ will contain the code we expose to the scary, scary reality of the internet.
bootstrap.php will set up some things such as including our autoloader and loading variables from our .env file. We’ll include that one a lot.
helpers.php usually contains small utility functions that don’t fit anywhere else.
Last but not least, setup.php is a small file that helps us set up our connection with Telegram.
Now would be a good time to copy that token we got from BotFather earlier and put it in our .env file.
You can name it whatever you like. My chosen name is just the default of the library.
To wrap up this setup sequence all that’s left to is to set up our autoloader. To do this we modify our composer.json and add this:
Again, the namespace can be whatever you prefer. Doesn’t have to be self-centered.
The change essentially summarizes to this: Load everything from src/ into the Pretzel namespace, and please also load the helpers.php file specifically.
Now we finally have our PHP project ready to go!
Setting up the connection with Telegram
Telegram works with an event-based system to let you know when new updates arrive. For this purpose we need to set up a webhook handler. In real world terms this just a PHP file that Telegram sends a request to every time somebody messages our bot. Fancy!
First, we’ll need our bot’s token. That is how we identify to Telegram who we are. As you may remember we put that into a .env file. So let’s set up loading variables from that.
Then we add the following to our bootstrap.php
Thanks to that short and sweet snippet we can now easily grab values from our .env file by using the env() function. This is not a native PHP function, but the Telegram Bot SDK brings it along as a dependency.
Next, I want to set up a small helper function in our helpers.php
This is purely for convenience. It allows us to grab an instance of the Telegram API wrapper without constantly having to query the .env file again. Now we can combine those two things in our setup.php file.
Stuff like this is why the telegram() helper is useful
Hold your horses. Readers with sharp eyes will have noticed, that I’m getting a TELEGRAM_WEBHOOK from the .env file. We don’t have that yet, right? Right.
We need to pass Telegram some kind of URL it can send its updates to. How do we do this on localhost? I’m glad you asked. Being a PHP developer in 2021 is a wonderful experience, so we have the perfect tool for this. It’s called expose and it’s made by BeyondCode.
Note: There are other options out there too. Something like ngrok would work just as well. I like expose because it’s easy to set up and provides custom subdomains for free.
Setting up your local webhook
To get started with getting an URL for our local environment, first we install expose .
This installs the expose utility globally and gives us access to it. If you’ve been using Composer for a while you’ve probably already done that, but make sure that composer global config bin-dir —absolute is in your $PATH .
Next we need to run our PHP somehow. For a project such as this the integrated PHP web server is fine. So we can use the following in the root directory of your project to get it running:
Then, open another terminal tab and run the following:
The subdomain option can be any of your choice. You can even name it «hunky-dory»
In the resulting output towards the end you should find a URL ending in sharedwithexpose.com . In my case it is pbbot.sharedwithexpose.com and that is the URL we need. Remember it!
Making it more ergonomic (optional)
Running two different terminal tabs at once is cumbersome. So let’s make use of ✨magical Composer scripts✨ so we only have to run one command to get our bot up to speed. We can make use of the & functionality of the shell to run both things at the same time. So you can add this to your composer.json
Adjust the subdomain and port to your liking.
The &>/dev/null stuff just ensures that the output of the original PHP web server does not mess with expose . Since expose gives us a nice request overview, we don’t need it anyways. Now you can run a single command, and your bot comes alive!
Now we can add our webhook URL to our .env file
Note that the URL *must* be HTTPS. Security and all that.
webhook.php will be the file we use to handle any incoming requests from Telegram. We’ll create it in the next step. First, we want to run our little setup.php script.
Setting up your webhook handler
So we just told Telegram to please send us any information to webhook.php , but we don’t have that file yet. We’ll just create it in our public/ folder. The webhook handler is essentially responsible for grabbing any unprocessed updates, forwarding them to our bot, and returning a result to Telegram. It looks like this:
I think by now you can see why the Telegram Bot SDK is useful. The fact that we have to call only one function to set up an entire command system is super useful and keeps productivity high!
Writing your first command
Now that we have all the annoying setup stuff out of the way, we can write our first command. Let’s start with the most bare-bones command imaginable: When we say /hello to our bot, we want it to say Hello World back to us.
First, we have to create a new class for our command. I’ll put it in src/Commands/HelloCommand.php , so we can access it through the class Pretzel\Commands\HelloCommand . Every command we create needs to inherit from the Bot SDKs base class. It also needs to have a name. So the basic structure looks like this.
Now inside the handle() function, we have access to a whole bunch of replyWith* type functions that we can use to respond to the message we just received. The easiest way is to use replyWithMessage .
These functions all take a bunch of arguments in the form of an array. I can’t even tell you all of them by heart. Thankfully, there’s good documentation! To find out what you need to send to the function, you can just look it up in the API Methods documentation. I also highly recommend the official Telegram documentation for more detailed information.
Each send* function corresponds to one of our replyWith* functions.
The important thing that these replyWith* functions do is adding the chat_id parameter to our arguments. So we can safely ignore that one. The other parameter we need is text . It should contain, as the name implies, the text of our message.
So now our class should look something like this
This would be an amazing use case for named arguments from PHP 8!
Registering it with the bot
Now we need to register this command with the bot, so it actually knows what commands are available. To do this, we go back to our bootstrap.php file and add the following
The namespace of your command is of course different
And now that we have done this, we can interact with our bot! Open up the chat with your bot in Telegram and try sending it a /hello command. It should respond to you right away!
Look at the little sunshine!
Working with arguments
Of course, commands are much more interesting when you’re able to send arguments to them. Say we want to greet a friend! How do we pass in their name?
For this, the Command class we inherit from offers a $pattern property. Here we can either use named arguments in braces like
So let’s say we want our bot to greet a person by their name if it receives one. Else we just greet the world, because everyone should be greeted once in a while. For this we set our $pattern to
Then, in our handle() function we can just grab the pre-supplied $arguments property:
As you can see, I used a the collect function when getting the arguments. This is another beautiful thing from the Laravel world and brought along by the Bot SDK. Collections are basically super-powered PHP arrays with a much cleaner way of working with them.
Of course you can also just handle the $arguments array yourself, but I vastly prefer this approach.
To learn more about Laravel collections, you can read the excellent documentation. They’re available as a standalone package and are a massive quality-of-life improvement.
Now we can grab the name key from our arguments, or return a default value if it’s not there. Then we insert this argument into a string and send it back to the user. That looks like this
After saving our command we can try it immediately! Go over to your bot and send it /hello <YOUR_NAME> and watch as it greets you with it’s mechanically engineered happiness!
Machines are so cute
Sending unprompted messages
Of course bots only have limited use if they only reply to you when you ask for them. Luckily, we can also send messages without any prior command. Just because we feel like it. For this, we need the chat_id of the person we want to send the messages to, or the @username of the group we want to send messages to.
To find out your personal chat_id you can just contact @RawDataBot, who will tell you in the first message.
You want the ID field I so helpfully redacted
If you have a private group without a @username , you can also just add @RawDataBot to the group to find the chat_id of the group. It will be a negative number.
Same field, different contents
And then you can use the sendMessage function of the Telegram API object. As demonstration, let’s add an unprompted message to our setup.php that we successfully set up our webhook.
That was pretty easy, wasn’t it?
Processing raw messages without commands
For some bots, we may want to process messages that are sent without command, just using the raw information that Telegram provides us. This is once again, relatively easy. After passing through the commands system, the SDK gives us an update object in the webhook handler. We can then use that to do whatever!
All properties on this update are directly accessible. So you can use $update->message->text to grab the relevant messages text etc.
This is the process I used in another bot to parse date and event information directly from a users message. Aside from the fact that parsing natural language dates is painful, it works great!
Deployment
Deployment for this setup should be straightforward for anyone who has ever dealt with other PHP deployments before. Doing so is left as an exercise for the reader, but it boils down to three points
- Push your files onto your server
- Point your webserver to serve files from public/
- Update webhook URL to yourdomain.com/webhook.php using setup.php
After that you’re good to go!
Closing thoughts
This article should have given you enough of an overview to get started with writing your own Telegram bots for whatever purposes. From here on out, the possibilities are mostly limited to what you can imagine.
My main bot currently tracks newsletter growth, Twitter growth, and during Notebag’s lifecycle it tracked the daily amount of money earned. It’s like a little daily dashboard informing me how my side-project life is going. The second bot makes sure I show up to any appointments I have on time.
Как написать телеграмм бота на php
Telegram-бот на PHP
Несколько лет назад я сделал на своем сайте отправку сообщений в Telegram средствами серверного PHP. В конце статьи я упомянул, что кроме отправки данных можно организовать взаимодействие с сайтом через Telegram. Настало время это реализовать, то есть написать полноценного Telegram-бота на PHP.
Основная часть, касающаяся регистрации бота, получения токена и идентификатора, подробно расписана по ссылке из первого абзаца, дублировать не буду. В дальнейшем предполагается, что бот создан и все необходимые данные получены.
Для того, чтобы серверный бот мог получать все сообщения и уведомления, первым делом надо зарегистрировать так называемый webhook, то есть указать ссылку на скрипт, куда Telegram будет отправлять все данные. Формируем ссылку вида:
https://api.telegram.org/bot [token] /setWebhook?url= https://вашсайт.ру/telebot.php
где [token] — это токен, полученный при регистрации бота. Например, для описанного ранее тестового бота ссылка будет вот такой:
https://api.telegram.org/bot 629705209:AAFhFqFbhR3VHHrOgOM7R4OnQT-usqJwTBk /setWebhook?url= https://вашсайт.ру/telebot.php
Если все сделано правильно, то в браузере будет получен ответ:
{»ok»:true,»result»:true,»description»:»Webhook was set»}
Telegram отправляет данные на указанный скрипт при помощи POST-запроса, формат передаваемых данных всегда JSON. Для удобства разбора полетов, особенно на первых этапах, лучше логировать все полученные данные куда-нибудь в файл. Каркас скрипта-приемника будет иметь следующий вид:
- $data = file_get_contents ( ‘php://input’ );
- if ( $json = json_decode ( $data , true )) <
- if (isset( $json [ ‘update_id’ ])) <
- // $json — отправленные данные
- >
- else <
- // Это точно не данные от Telegram
- exit;
- >
- >
- else <
- // Получены некорректные данные
- exit;
- >
Тут сразу же выполняется быстрая проверка на корректность полученных данных, после чего разобранный запрос помещается в массив $json. Обычно бот может получать текстовые данные, файлы или управляющие команды. Начнем с самого простого. Когда пользователь пишет в чат сообщение, то бот получит примерно такие данные:
Array (
[update_id] => 434540657
[message] => Array (
[message_id] => 1702
[from] => Array (
[id] => 698237240
[is_bot] =>
[first_name] => Dmitry
[language_code] => ru
)
[chat] => Array (
[id] => 698237240
[first_name] => Dmitry
[type] => private
)
[date] => 1679039931
[text] => Привет
)
)
В зависимости от функционала и назначения, бот самостоятельно анализирует входящее сообщение, на его основании выполняет какие-то действия и, если надо, отправляет пользователю ответ. Отправлять данные мы уже умеем. По такой схеме работают, например, боты-переводчики.
Бот может принимать управляющие команды, они начинаются с косой черты «/». Если Telegram распознает такую команду, то в этом случае в уведомлении будет присутствовать дополнительный блок, хотя в остальном оно ничем не отличается от обычного текстового сообщения.
Array (
[update_id] => 434540657
[message] => Array (
[message_id] => 1702
[from] => Array (
[id] => 698237240
[is_bot] =>
[first_name] => Dmitry
[language_code] => ru
)
[chat] => Array (
[id] => 698237240
[first_name] => Dmitry
[type] => private
)
[date] => 1679039931
[text] => /dosomething
[ entities ] => Array (
[0] => Array (
[offset] => 0
[length] => 12
[type] => bot_command
)
)
)
)
Тут указывается, с какой позиции сообщения начинается управляющая команда и какой она длины. Реакция на ту или иную команду, естественно, остается на совести разработчика бота. Пользователь может передавать несколько команд в одном сообщении, даже перемежая их текстом. Telegram поможет их определить и для каждой команды передаст ее позицию в отправленном сообщении и длину.
Array (
[update_id] => 434540657
[message] => Array (
[message_id] => 1702
[from] => Array (
[id] => 698237240
[is_bot] =>
[first_name] => Dmitry
[language_code] => ru
)
[chat] => Array (
[id] => 698237240
[first_name] => Dmitry
[type] => private
)
[date] => 1679039931
[text] => Yo, bota! /krush /kill and /destroy
[entities] => Array (
[0] => Array (
[offset] => 10
[length] => 6
[type] => bot_command
)
[1] => Array (
[offset] => 17
[length] => 5
[type] => bot_command
)
[2] => Array (
[offset] => 27
[length] => 8
[type] => bot_command
)
)
)
)
Когда пользователь отправляет боту картинку со своего устройства, то фактически боту никаких файлов не передается. Файл загружается на сервер Telegram, а боту приходит информация об этом файле.
Array (
[update_id] => 434540657
[message] => Array (
[message_id] => 1702
[from] => Array (
[id] => 698237240
[is_bot] =>
[first_name] => Dmitry
[language_code] => ru
)
[chat] => Array (
[id] => 698237240
[first_name] => Dmitry
[type] => private
)
[date] => 1679039931
[ photo ] => Array (
[0] => Array (
[file_id] => AgAAAAAA1111111222222444zF-06666667777DDDDD
[file_unique_id] => AQ111111111111h4
[file_size] => 1575
[width] => 55
[height] => 90
)
[1] => Array (
[file_id] => AgAAAAAA1111111222222444zF-06666667777CCCCC
[file_unique_id] => AQ111111111111hy
[file_size] => 23882
[width] => 197
[height] => 320
)
[2] => Array (
[file_id] => AgAAAAAA1111111222222444zF-06666667777BBBBB
[file_unique_id] => AQ111111111111h9
[file_size] => 99568
[width] => 493
[height] => 800
)
[3] => Array (
[file_id] => AgAAAAAA1111111222222444zF-06666667777AAAAA
[file_unique_id] => AQ111111111111h-
[file_size] => 175335
[width] => 789
[height] => 1280
)
)
)
)
Как видите, Telegram и тут позаботился о web-мастере, передавая не только оригинальное изображение, но и подготовив аж три превьюшки разного размера. Сам файл получается в два этапа. Сперва надо определить, какой из четырех файлов нам нужен, они отличаются по полю file_id. Допустим, превьюшки нас не интересуют, поэтому просто берем последний элемент массива и получаем информацию о загруженном файле, используя его идентификатор.
- // Токен бота
- $token = ‘629705209:AAFhFqFbhR3VHHrOgOM7R4OnQT-usqJwTBk’ ;
- $photo = array_pop ( $json [ ‘message’ ][ ‘photo’ ]);
- $ch = curl_init ();
- curl_setopt ( $ch , CURLOPT_URL , ‘https://api.telegram.org/bot’ . $token . ‘/getFile’ );
- curl_setopt ( $ch , CURLOPT_POST , TRUE );
- curl_setopt ( $ch , CURLOPT_POSTFIELDS , ‘file_id=’ . $photo [ ‘file_id’ ]);
- curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , TRUE );
- curl_setopt ( $ch , CURLOPT_HEADER , FALSE );
- curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , FALSE );
- $result = curl_exec ( $ch );
- curl_close ( $ch );
- $json = json_decode ( $result , true );
Если все сделано правильно, то будет получен ответ примерно такого содержания:
Array (
[ok] => 1
[result] => Array (
[file_id] => AgAAAAAA1111111222222444zF-06666667777AAAAA
[file_unique_id] => AQ111111111111h-
[file_size] => 175335
[file_path] => photos/file_0.jpg
)
)
Только теперь, получив имя файла, можно загрузить его содержимое с сервера Telegram. Код будет примерно таким:
- $ch = curl_init ();
- curl_setopt ( $ch , CURLOPT_URL ,
- ‘https://api.telegram.org/file/bot’ . $token . ‘/’ . $json [ ‘result’ ][ ‘file_path’ ]);
- curl_setopt ( $ch , CURLOPT_POST , FALSE );
- curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , TRUE );
- curl_setopt ( $ch , CURLOPT_HEADER , FALSE );
- curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , FALSE );
- $source = curl_exec ( $ch );
- curl_close ( $ch );
- // $source — содержимое файла
Есть большой соблазн вообще пропустить предыдущий шаг, так как массив изображений формируется только для файлов в формате JPEG, а оригинальная картинка всегда хранится по пути photos/file_0.jpg. Но стопроцентной гарантии у меня нет, поэтому оставлю это на ваше усмотрение.
Все прочие файлы, в том числе и изображения в форматах PNG, WebP и других, пересылаются как документы. По возможности, если удалось распознать файл как изображение, для него генерится превьюшка.
Array (
[update_id] => 434540657
[message] => Array (
[message_id] => 1702
[from] => Array (
[id] => 698237240
[is_bot] =>
[first_name] => Dmitry
[language_code] => ru
)
[chat] => Array (
[id] => 698237240
[first_name] => Dmitry
[type] => private
)
[date] => 1679039931
[ document ] => Array (
[file_name] => my_image.png
[mime_type] => image/png
[thumbnail] => Array (
[file_id] => AgAAAAAA1111111222222444zF-06666667777CCCCC
[file_unique_id] => AQ111111111111hA
[file_size] => 25093
[width] => 320
[height] => 282
)
[thumb] => Array (
[file_id] => AgAAAAAA1111111222222444zF-06666667777BBBBB
[file_unique_id] => AQ111111111111hB
[file_size] => 25093
[width] => 320
[height] => 282
)
[file_id] => AgAAAAAA1111111222222444zF-06666667777AAAAA
[file_unique_id] => AQ111111111111hC
[file_size] => 33560
)
)
)
Остальные документы считаются бинарными файлами и передаются как есть.
Array (
[update_id] => 434540657
[message] => Array (
[message_id] => 1702
[from] => Array (
[id] => 698237240
[is_bot] =>
[first_name] => Dmitry
[language_code] => ru
)
[chat] => Array (
[id] => 698237240
[first_name] => Dmitry
[type] => private
)
[date] => 1679039931
[ document ] => Array (
[file_name] => my_book.fb2
[mime_type] => application/octet-stream
[file_id] => AgAAAAAA1111111222222444zF-06666667777AAAAA
[file_unique_id] => AQ111111111111hC
[file_size] => 1236900
)
)
)
Содержимое файла получается точно так же в два захода. И вот тут от получения информации о файле уже не отвертеться.
- // Токен бота
- $token = ‘629705209:AAFhFqFbhR3VHHrOgOM7R4OnQT-usqJwTBk’ ;
- $ch = curl_init ();
- curl_setopt ( $ch , CURLOPT_URL , ‘https://api.telegram.org/bot’ . $token . ‘/getFile’ );
- curl_setopt ( $ch , CURLOPT_POST , TRUE );
- curl_setopt ( $ch , CURLOPT_POSTFIELDS ,
- ‘file_id=’ . $json [ ‘message’ ][ ‘document’ ][ ‘file_id’ ]);
- curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , TRUE );
- curl_setopt ( $ch , CURLOPT_HEADER , FALSE );
- curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , FALSE );
- $result = curl_exec ( $ch );
- $json = json_decode ( $result , true );
- curl_setopt ( $ch , CURLOPT_URL ,
- ‘https://api.telegram.org/file/bot’ . $token . ‘/’ . $json [ ‘result’ ][ ‘file_path’ ]);
- curl_setopt ( $ch , CURLOPT_POST , FALSE );
- $source = curl_exec ( $ch );
- curl_close ( $ch );
- // $source — содержимое файла
Дальше содержимое файла записывается на диск или используется по иному назначению. Хорошим тоном будет уведомить пользователя о факте успешного получения файла и о действии, которое с этим файлом было выполнено.
В дополнение к предыдущей статье об отправке обычных текстовых сообщений расскажу, как можно отправлять пользователю изображения и документы. Делается это достаточно просто.
Отправка изображения
- // Подготовить локальный файл для отправки
- $file = __DIR__ . ‘/original.jpg’ ;
- if ( function_exists ( ‘curl_file_create’ )) <
- $attachment = curl_file_create ( $file );
- >
- else <
- $info = pathinfo ( $file );
- $attachment = ‘@’ . realpath ( $file ). ‘;filename=’ . $info [ ‘basename’ ].
- ‘;type=’ . mime_content_type ( $file );
- >
- $query =array(
- ‘chat_id’ => $chat_id ,
- ‘photo’ => $attachment ,
- ‘caption’ => ‘Тестовая картинка’ ,
- );
- $ch = curl_init ();
- curl_setopt ( $ch , CURLOPT_URL ,
- ‘https://api.telegram.org/bot’ . $token . ‘/sendPhoto’ );
- curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
- curl_setopt ( $ch , CURLOPT_HEADER , false );
- curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , false );
- curl_setopt ( $ch , CURLOPT_POST , true );
- curl_setopt ( $ch , CURLOPT_POSTFIELDS , $query );
- $result = curl_exec ( $ch );
- curl_close ( $ch );
Для формирования объекта файла проверяется доступность функции cURL, так как функция curl_file_create отсутствует в старых версиях PHP. Для таких случаев создание объекта отправляемого файла выполняется в «ручном» режиме.
Отправка документа выполняется почти так же, только меняется название ключа массива и ссылка API.
Отправка документа
Отправка документа
- // Подготовить локальный файл для отправки
- $file = __DIR__ . ‘/example.xls’ ;
- if ( function_exists ( ‘curl_file_create’ )) <
- $attachment = curl_file_create ( $file );
- >
- else <
- $info = pathinfo ( $file );
- $attachment = ‘@’ . realpath ( $file ). ‘;filename=’ . $info [ ‘basename’ ].
- ‘;type=’ . mime_content_type ( $file );
- >
- $query =array(
- ‘chat_id’ => $chat_id ,
- ‘document’ => $attachment ,
- ‘caption’ => ‘Тестовый документ’ ,
- );
- $ch = curl_init ();
- curl_setopt ( $ch , CURLOPT_URL ,
- ‘https://api.telegram.org/bot’ . $token . ‘/sendDocument’ );
- curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
- curl_setopt ( $ch , CURLOPT_HEADER , false );
- curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , false );
- curl_setopt ( $ch , CURLOPT_POST , true );
- curl_setopt ( $ch , CURLOPT_POSTFIELDS , $query );
- $result = curl_exec ( $ch );
- curl_close ( $ch );
По аналогии отправляются аудиофайлы, вынесенные от документов в отдельную категорию.
Отправка аудио
- // Подготовить локальный файл для отправки
- $file = __DIR__ . ‘/example.mp3’ ;
- if ( function_exists ( ‘curl_file_create’ )) <
- $attachment = curl_file_create ( $file );
- >
- else <
- $info = pathinfo ( $file );
- $attachment = ‘@’ . realpath ( $file ). ‘;filename=’ . $info [ ‘basename’ ].
- ‘;type=’ . mime_content_type ( $file );
- >
- $query =array(
- ‘chat_id’ => $chat_id ,
- ‘audio’ => $attachment ,
- ‘caption’ => ‘Тестовая песенка’ ,
- );
- $ch = curl_init ();
- curl_setopt ( $ch , CURLOPT_URL ,
- ‘https://api.telegram.org/bot’ . $token . ‘/sendAudio’ );
- curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
- curl_setopt ( $ch , CURLOPT_HEADER , false );
- curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , false );
- curl_setopt ( $ch , CURLOPT_POST , true );
- curl_setopt ( $ch , CURLOPT_POSTFIELDS , $query );
- $result = curl_exec ( $ch );
- curl_close ( $ch );
Отправку всяких стикеров, контактов и прочего смотрите в официальной документации, там ничего сложного.
Отдельно хочется остановиться на взаимодействии пользователя с ботом. Конечно, можно сколько угодно набирать вручную текстовые сообщения и команды управления, но это быстро надоедает, к тому же повышается риск ошибки. Гораздо удобнее сразу же предоставлять пользователю список возможных действий в привычном ему формате, например, в виде кнопок.
Первый тип клавиатуры — inline-клавиатура, которая прикрепляется к конкретному сообщению. Как правило в ней содержится список действий, которые связаны с этим сообщением, например, переход по ссылке или открытие конкретной карточки товара. Для отправки такой клавиатуры надо сперва сформировать массив с кнопками, которые будут прикреплены к сообщению, а затем передать его в параметре reply_markup.
Пример inline-клавиатуры
- $keyboard =array(
- «resize_keyboard» => true ,
- «inline_keyboard» =>array(
- // Первая строка кнопок
- array(
- array(
- ‘text’ => ‘Перейти на сайт www.manhunter.ru’ ,
- ‘url’ => ‘https://www.manhunter.ru’ ,
- ),
- ),
- // Вторая строка кнопок
- array(
- array(
- ‘text’ => ‘Привет!’ ,
- ‘callback_data’ => ‘Нажата внопка 1’
- ),
- array(
- ‘text’ => ‘До свидания!’ ,
- ‘callback_data’ => ‘Нажата внопка 2’
- ),
- ),
- ),
- );
- $text = ‘Вот такие кнопки. Попробуй их все!’ ;
- $ch = curl_init ();
- curl_setopt ( $ch , CURLOPT_URL ,
- ‘https://api.telegram.org/bot’ . $token . ‘/sendMessage’ );
- curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
- curl_setopt ( $ch , CURLOPT_HEADER , false );
- curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , false );
- curl_setopt ( $ch , CURLOPT_POST , true );
- curl_setopt ( $ch , CURLOPT_POSTFIELDS ,
- ‘chat_id=’ . $chat_id . ‘&text=’ . rawurlencode ( $text ).
- ‘&reply_markup=’ . json_encode ( $keyboard ));
- curl_setopt ( $ch , CURLOPT_CONNECTTIMEOUT , 10 );
- $result = curl_exec ( $ch );
Кнопки могут быть расположены в несколько строчек, а в качестве параметров указывается ссылка или строка с описанием действия, которое будет передано на ваш обработчик. При нажатии на кнопку-ссылку Telegram спросит подтверждение на переход, а при нажатии на кнопку-действие ваш обработчик получит примерно такие уведомление:
Array (
[update_id] => 434540657
[callback_query] => Array (
[ id ] => 1111222223333344444
[from] => Array (
[id] => 698237240
[is_bot] =>
[first_name] => Dmitry
[language_code] => ru
)
[message] => Array (
[message_id] => 74
[from] => Array (
[id] => 1112223445
[is_bot] => 1
[first_name] => MySupaTestBot
[username] => MySupaTestBot_bot
)
[chat] => Array (
[id] => 698237240
[first_name] => Dmitry
[type] => private
)
[date] => 1679227556
[text] => Вот такие кнопки. Попробуй их все!
[reply_markup] => Array (
[inline_keyboard] => Array (
[0] => Array (
[0] => Array (
[text] => Перейти на сайт
[url] => https://www.manhunter.ru/
)
)
[1] => Array (
[0] => Array (
[text] => Привет
[callback_data] => Нажата внопка 1
)
[1] => Array (
[text] => До свидания
[callback_data] => Нажата внопка 2
)
)
)
)
)
[chat_instance] => -123456789081123230
[ data ] => Нажата внопка 1
)
)
После отправки callback-сообщения клиент Telegram переходит в режим ожидания ответа, при этом на нажатой кнопке появляется значок часиков. Если в течение определенного времени ответ от серверного обработчика не получен, то значок часиков пропадает. Но хорошей практикой будет отправлять из обработчика ответ на callback-сообщения с помощью метода answerCallbackQuery. В этом случае для идентификации получателя используется [‘callback_query’][‘id’].
- $callback_id = $json [ ‘callback_query’ ][ ‘id’ ];
- $text = » ;
- $ch = curl_init ();
- curl_setopt ( $ch , CURLOPT_URL ,
- ‘https://api.telegram.org/bot’ . $token . ‘/answerCallbackQuery’ );
- curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
- curl_setopt ( $ch , CURLOPT_HEADER , false );
- curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , false );
- curl_setopt ( $ch , CURLOPT_POST , true );
- curl_setopt ( $ch , CURLOPT_POSTFIELDS ,
- ‘callback_query_id=’ . $callback_id . ‘&text=’ . rawurlencode ( $text ));
- curl_setopt ( $ch , CURLOPT_CONNECTTIMEOUT , 10 );
- $result = curl_exec ( $ch );
Текст ответа появится в виде всплывающего сообщения, если текст пустой, то клиент просто вернется из режима ожидания ответа в обычный режим работы. Показ сообщения также регулируется параметром show_alert. В зависимости от задачи, вместо показа сообщения можно передать параметр url, в этом случае клиент выполнит команду «открыть сылку».
Второй тип клавиатуры — обычная, она предназначена для отправки пользователем в чат предустановленных сообщений и располагается под строкой ввода. В массиве описания клавиатуры меняется название ключа и передаются только названия кнопок, они же являются предустановленным текстом сообщений.
Пример обычной клавиатуры
- $keyboard =array(
- «resize_keyboard» => true ,
- «keyboard» =>array(
- array(
- array(
- ‘text’ => ‘Всем привет!’ ,
- ),
- array(
- ‘text’ => ‘До свидания!’ ,
- ),
- ),
- ),
- );
- $text = ‘Вот такие кнопки. Попробуй их все!’ ;
- $ch = curl_init ();
- curl_setopt ( $ch , CURLOPT_URL ,
- ‘https://api.telegram.org/bot’ . $token . ‘/sendMessage’ );
- curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
- curl_setopt ( $ch , CURLOPT_HEADER , false );
- curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , false );
- curl_setopt ( $ch , CURLOPT_POST , true );
- curl_setopt ( $ch , CURLOPT_POSTFIELDS ,
- ‘chat_id=’ . $chat_id . ‘&text=’ . rawurlencode ( $text ).
- ‘&reply_markup=’ . json_encode ( $keyboard ));
- curl_setopt ( $ch , CURLOPT_CONNECTTIMEOUT , 10 );
- $result = curl_exec ( $ch );
При нажатиии таких кнопок серверному обработчику, соответственно, приходят самые обычные уведомления, как будто пользователь набрал их на клавиатуре.
Через @BotFather можно задавать список команд бота. Он появится в меню команд при нажатии кнопки рядом с полем ввода. Но можно сделать это и программно, например, сразу после старта бота.
Меню команд бота
- $commands =array(
- array(
- ‘command’ => ‘start’ ,
- ‘description’ => ‘Запуск бота’
- ),
- array(
- ‘command’ => ‘monster’ ,
- ‘description’ => ‘Монстр дня’
- ),
- array(
- ‘command’ => ‘crossword’ ,
- ‘description’ => ‘Кроссворд’
- ),
- array(
- ‘command’ => ‘coupon’ ,
- ‘description’ => ‘Купон’
- ),
- );
- $query =array(
- ‘commands’ => json_encode ( $commands ),
- );
- $ch = curl_init ();
- curl_setopt ( $ch , CURLOPT_URL ,
- ‘https://api.telegram.org/bot’ . $token . ‘/setMyCommands’ );
- curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
- curl_setopt ( $ch , CURLOPT_HEADER , false );
- curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , false );
- curl_setopt ( $ch , CURLOPT_POST , true );
- curl_setopt ( $ch , CURLOPT_POSTFIELDS , $query );
- curl_setopt ( $ch , CURLOPT_CONNECTTIMEOUT , 10 );
- $result = curl_exec ( $ch );
- curl_close ( $ch );
Как и в предыдущем случае, на сервер отправится управляющая команда, как будто ее набрали с клавиатуры. Количество команд в списке не должно быть больше 100.
И напоследок буквально пару слов об оформлении сообщений, которые бот отправляет пользователю. Чтобы определенный фрагмент текста можно было скопировать одним нажатием, его надо оформить тегами <code> и дополнить список полей отправки параметром parse_mode=HTML.
- $text = ‘Длинный текст, <code>а этот фрагмент можно копировать</code>, и еще текст’ ;
- $ch = curl_init ();
- curl_setopt ( $ch , CURLOPT_URL ,
- ‘https://api.telegram.org/bot’ . $token . ‘/sendMessage’ );
- curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
- curl_setopt ( $ch , CURLOPT_HEADER , false );
- curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , false );
- curl_setopt ( $ch , CURLOPT_POST , true );
- curl_setopt ( $ch , CURLOPT_POSTFIELDS ,
- ‘chat_id=’ . $chat_id . ‘&text=’ . rawurlencode ( $text ). ‘&parse_mode=HTML’ );
- curl_setopt ( $ch , CURLOPT_CONNECTTIMEOUT , 10 );
- $result = curl_exec ( $ch );
- curl_close ( $ch );
По умолчанию Telegram не позволяет вставлять изображения в текст сообщений. Это частично можно обойти, сформировав сообщение особым образом, указав ссылку на картинку с пустым текстом ссылки и добавив еще один параметр disable_web_page_preview=false в отправляемые данные.
Изображение в сообщении
- $text = ‘Посмотрите, какая картинка есть у нас ‘ ;
- $text .= ‘<a href=»https://вашсайт.ру/image.jpg»>‍</a>’ ;
- $text .= ‘Вам нравится?’ ;
- $ch = curl_init ();
- curl_setopt ( $ch , CURLOPT_URL ,
- ‘https://api.telegram.org/bot’ . $token . ‘/sendMessage’ );
- curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
- curl_setopt ( $ch , CURLOPT_HEADER , false );
- curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , false );
- curl_setopt ( $ch , CURLOPT_POST , true );
- curl_setopt ( $ch , CURLOPT_POSTFIELDS ,
- ‘chat_id=’ . $chat_id . ‘&text=’ . rawurlencode ( $text ).
- ‘&disable_web_page_preview=false&parse_mode=HTML’ );
- curl_setopt ( $ch , CURLOPT_CONNECTTIMEOUT , 10 );
- $result = curl_exec ( $ch );
- curl_close ( $ch );
Еще один часто используемый вариант оформления постов — большой текст в качестве подписи к изображению. В этом случае картинка будет сверху, а под ней, например, рекламный текст. Длина подписи к картинке, а, следовательно, и текста поста, не должна превышать 1024 символа. Обычный текст сообщения к фото добавлять нельзя.
Текст в подписи и inline-клавиатура
- $keyboard =array(
- «resize_keyboard» => true ,
- «inline_keyboard» =>array(
- array(
- array(
- ‘text’ => ‘Перейти на сайт www.manhunter.ru’ ,
- ‘url’ => ‘https://www.manhunter.ru’ ,
- ),
- ),
- ),
- );
- // Подготовить локальный файл для отправки
- $file = __DIR__ . ‘/example.jpg’ ;
- if ( function_exists ( ‘curl_file_create’ )) <
- $attachment = curl_file_create ( $file );
- >
- else <
- $info = pathinfo ( $file );
- $attachment = ‘@’ . realpath ( $file ). ‘;filename=’ . $info [ ‘basename’ ].
- ‘;type=’ . mime_content_type ( $file );
- >
- $query =array(
- ‘chat_id’ => $chat_id ,
- ‘photo’ => $attachment ,
- ‘caption’ => ‘Новинка! Распродажа!’ . «\n» .
- ‘Только сейчас и только у нас!’ . «\n» .
- ‘Налетай, торопись, покупай живопись!’ ,
- ‘reply_markup’ => json_encode ( $keyboard ),
- );
- $ch = curl_init ();
- curl_setopt ( $ch , CURLOPT_URL ,
- ‘https://api.telegram.org/bot’ . $token . ‘/sendPhoto’ );
- curl_setopt ( $ch , CURLOPT_RETURNTRANSFER , true );
- curl_setopt ( $ch , CURLOPT_HEADER , false );
- curl_setopt ( $ch , CURLOPT_SSL_VERIFYPEER , false );
- curl_setopt ( $ch , CURLOPT_POST , true );
- curl_setopt ( $ch , CURLOPT_POSTFIELDS , $query );
- $result = curl_exec ( $ch );
- curl_close ( $ch );
Комбинируя описанные тут методы приема и отправки сообщений разного типа, вы можете написать собственного Telegram-бота с нужным функционалом. В очередной раз скажу, что перечисленными функциями возможности Telegram-ботов не ограничиваются. Изучайте документацию, смотрите примеры, пробуйте и у вас все получится.