Sending Notifications to Telegram Messenger with Laravel.

43,018

Telegram is a non-profit cloud-based instant messaging service. It is similar to WhatsApp and Facebook messenger in features but offers great security. Telegram apps are available for Android, iOS, Windows Phone, Windows NT, macOS, and Linux.

Telegram officially released bot platform on June 24, 2015. We can use Telegram Bot API to send messages to a channel or a group through our bot. We can use this for app notification, errors or monthly application reports. It is completely free to use their bot API. You can checkout Bots API on the official documentation.

In this tutorial, we will create a simple application that will send messages to a channel. Let’s start working on the application.

Creating a laravel application

Let’s create a new Laravel application named Telegram. I am using laravel 5.6.3 for this tutorial. To create a new project, run the following command:

laravel new Telegram

Installing Telegram Bot API packages

In this tutorial, we will use Telegram Bot API PHP SDK package. This package is created and maintained by Syed Irfaq R. It supports laravel out of the box. It is unofficial Telegram Bot SDK. Let’s install this package through composer by running the following command:

composer require irazasyed/telegram-bot-sdk

It will install the package. If you are using laravel 5.4 or previous laravel 5 versions, you need to add Service Provider and facade for this package. If you are using the latest version of laravel, skip this step. To add Service Provider, add the following entry in providers array in config/app.php file.

Telegram\Bot\Laravel\TelegramServiceProvider::class,

Also, add the following entry in aliases array to setup facade present in config/app.php file.

 'Telegram' => Telegram\Bot\Laravel\Facades\Telegram::class,

Now that we have set up Service Provider and Facade, let’s move on to the next step.

The last step is to publish configuration file. Open the terminal window and run the following command to publish the configuration:

php artisan vendor:publish --provider="Telegram\Bot\Laravel\TelegramServiceProvider"

Above command will publish a telegram.php configuration file in config directory. Here we will be setting up our configuration for the bot. Let’s create our bot first.

Creating a Telegram Bot

Let’s start by creating a Telegram Bot. First, you need to install Telegram app. You need to talk to BotFather to create a telegram bot. To do this, send a message to @BotFather. Visit the link through your mobile and click Send Message to start messaging BotFather.

Now click START at the bottom. It will start your communication with botfather by sending /start. To create a new bot, send /newbot to botfather. It will ask for a new name. I will call mine tutsforweb. Then, botfather will ask for a username. Username must end with the word bot. I will name mine tutsforwebbot. You can call it whatever you want but remember to follow the tutorial with your choosen username.

Successfully our bot is created. BotFather will send a message with a token to access HTTP API.

Telegram bot api

Copy the bot token and insert in .env file under the key TELEGRAM_BOT_TOKEN. So, you need to add a line like this in your .env file. Replace the token with your bot token in the line below. This token is for tutsforwebbot.

TELEGRAM_BOT_TOKEN=525012101:AAEwy9R1SCpq0V_Bpkgqm9Z4nbrWZaNt_Kg

You can also change other options such as name, description, profile pic and other options by sending commands to the botfather but we will not be doing that here. You can find all of these options here in the documentation.

Creating channel for notifications

Now let’s create a new channel to send notifications. You can also choose to create a group instead but we will go with a channel. I will name my channel tutsforweb and make it public channel as well as set link to tutsforweb. Link will be t.me/tutsforweb.

Telegram creating channel

Let’s add the bot as the admin for the channel. To do this, open the channel and click on its profile picture. Now click the settings icon and select Administrators.

Telegram bot as administrator

Now click Add administrator and add tutsforwebbot as the admin by searching for it by bot username.

Telegram bot search

Now, click the tick icon at the top right corner with default access selected. It will add our bot as the admin that will enable it to send messages to the channel.

Go to config/telegram.php and in your telegram bots section which is the first section, set username to your bots username. In my case, it is tutsforwebbot. Also, set the values for token, certificate_path and webhook_url in env function second parameter to empty string. This is how my bots key, value looks like:

'bots' => [
    'mybot' => [
        'username' => 'tutsforwebbot',
        'token' => env('TELEGRAM_BOT_TOKEN', ''),
        'certificate_path' => env('TELEGRAM_CERTIFICATE_PATH', ''),
        'webhook_url' => env('TELEGRAM_WEBHOOK_URL', ''),
        'commands' => [
        ],
    ],
],

We will not be using webhooks. Also, run the following command to configure cache:

php artisan config:cache

Obtaining channel CHAT_ID

To send messages or notifications to any channel, group or anyone requires chat_id. CHAT_ID is an integer which uniquely identifies a thread to which we can send the message in Telegram.

It is difficult to find chat_id for a thread. What we can do is send a message to our thread. I will send a message with text Hi to the tutsforweb channel. Of course, you can set the text to whatever you want because it does not matter.

Telegram message

Now, let’s create a method that will print tutsforwebbot updates. When we call this method, Telegram returns all of the related activity for our bot. We can use dd method to die and dump the response. The output response contains the channel and related chat_id number this bot belongs to.

To do this, create a new controller named TelegramBotController by running the following command in your terminal:

php artisan make:controller TelegramBotController

Now, add a new method named updatedActivity to the controller. Here’s how the file looks:

<?php

namespace App\Http\Controllers;

use Telegram\Bot\Laravel\Facades\Telegram;

class TelegramBotController extends Controller
{
    public function updatedActivity()
    {
        $activity = Telegram::getUpdates();
        dd($activity);
    }
}

Here we are using the getUpdates method on Telegram Facade and dumping the response. Now add a new route for this controller method by adding the following line to routes/web.php file:

Route::get('/updated-activity', 'TelegramBotController@updatedActivity');

Hit the /updated-activity endpoint through the browser. You might get an empty response like [ ]. Go to your channel and broadcast another message like "Hi". Hit the updated-activity endpoint again and you will find the response like this:

Telegram bot with laravel

Now copy the id present in channel_post/chat/id which in my case is -1001292494327. Go to .env file and paste your chat id on TELEGRAM_CHANNEL_ID key. Here’s how this line looks in my case:

TELEGRAM_CHANNEL_ID=-1001292494327

If you have sent multiple messages to the channel or bot, you will find them in the array. Make sure you use the chat_id of the message for your channel. Run the following command again to configure cache:

php artisan config:cache

Creating views

In this application, we will be creating two forms, one for submitting our form and the other one for sending pictures. Contact us form will send email address and message to the channel. Let’s start by creating views for our two forms.

Create a new view file named layout.blade.php in resources/views directory. Now, copy the contents below to your layout file:

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Telegram Bot Contact Form</title>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light" style="margin-bottom: 50px;">
        <a class="navbar-brand" href="#">Telegram</a>
        <div class="collapse navbar-collapse">
            <ul class="navbar-nav mr-auto">
                <li class="nav-item">
                    <a class="nav-link" href="{{ url('/') }}">Contact Us</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="{{ url('/updated-activity') }}">Check Activity</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="{{ url('/send-photo') }}">Send Photo</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="{{ url('/') }}">GitHub Code</a>
                </li>
            </ul>
        </div>
    </nav>
    <div class="container">
        <div class="row">
            <div class="col-sm-10 offset-sm-1">
                @yield('content')
            </div>
        </div>
    </div>
</body>
</html>

Here, we are using bootstrap 4 for styling. We will extend this file to create our forms. In this file, a simple navbar is created and then a place to yield contents is created.

Create another file named message.blade.php in resources/views directory. This blade file will be used as our contact form. Copy the contents below to the message file:

@extends('layout')

@section('content')
    <form action="{{ url('/send-message') }}" method="post">
        {{ csrf_field() }}
        <div class="form-group">
            <label for="email">Email address</label>
            <input type="email" class="form-control" id="email" name="email" placeholder="Enter your email">
        </div>
        <div class="form-group">
            <label for="message">Message</label>
            <textarea name="message" id="message" class="form-control" placeholder="Enter your query" rows="10"></textarea>
        </div>
        <div class="form-group">
            <button type="submit" class="btn btn-primary">Submit</button>
        </div>
    </form>
@endsection

In this file we are extending the layout file and creating a form. This form will be submitted to send-message endpoint.

Create another view file named photo.blade.php to send photos to the Telegram channel. Copy the contents below to the photo file:

@extends('layout')

@section('content')
    <form action="{{ url('/store-photo') }}" method="post" enctype="multipart/form-data">
        {{ csrf_field() }}
        <div class="form-group">
            <div class="custom-file">
                <input type="file" id="file" name="file" class="custom-file-input">
                <label class="custom-file-label" for="file">Choose file</label>
            </div>
        </div>
        <div class="form-group">
            <button type="submit" class="btn btn-primary">Submit</button>
        </div>
    </form>
@endsection

In the above file, we are creating a simple form to submit a file to the store-photo endpoint. Our views are now created successfully.

Setting up our routes

Now let’s setup our routes endpoints. Go to your routes/web.php and replace the contents of that file with the contents below:

<?php

Route::get('/', 'TelegramBotController@sendMessage');
Route::post('/send-message', 'TelegramBotController@storeMessage');
Route::get('/send-photo', 'TelegramBotController@sendPhoto');
Route::post('/store-photo', 'TelegramBotController@storePhoto');
Route::get('/updated-activity', 'TelegramBotController@updatedActivity');

Our routes are now set up successfully.

Setting Up the logic

Let’s set up our logic to handle upload and submit it to the Telegram. Open TelegramBotController.php we created in the previous step and replace the contents of the file with contents present below:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Telegram\Bot\FileUpload\InputFile;
use Telegram\Bot\Laravel\Facades\Telegram;

class TelegramBotController extends Controller
{
    public function updatedActivity()
    {
        $activity = Telegram::getUpdates();
        dd($activity);
    }

    public function sendMessage()
    {
        return view('message');
    }

    public function storeMessage(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'message' => 'required'
        ]);

        $text = "A new contact us query\n"
            . "<b>Email Address: </b>\n"
            . "$request->email\n"
            . "<b>Message: </b>\n"
            . $request->message;

        Telegram::sendMessage([
            'chat_id' => env('TELEGRAM_CHANNEL_ID', ''),
            'parse_mode' => 'HTML',
            'text' => $text
        ]);

        return redirect()->back();
    }

    public function sendPhoto()
    {
        return view('photo');
    }

    public function storePhoto(Request $request)
    {
        $request->validate([
            'file' => 'file|mimes:jpeg,png,gif'
        ]);

        $photo = $request->file('file');

        Telegram::sendPhoto([
            'chat_id' => env('TELEGRAM_CHANNEL_ID', ''),
            'photo' => InputFile::createFromContents(file_get_contents($photo->getRealPath()), str_random(10) . '.' . $photo->getClientOriginalExtension())
        ]);

        return redirect()->back();
    }
}

Let me explain everything in the controller above. First, we have the updatedActivity method that we created previously. Next, we have the sendMessage method where we are simply returning message view.

In storeMessage method, we are simply validating email and message fields. We can send HTML to the Telegram but the only tags that are allowed are bold, strong, italic, emphasis, anchor, code and preformatted tag. So, we are building our message text in $text variable. \n is used to add a new line. If we want to send HTML, we have to add a new entry to the array with key parse_mode and value HTML. Then we are sending chat_id, parse_mode, and text to the sendMessage method on Telegram facade.

In sendPhoto method, we are returning photo view. Along with messages, we can also send photo, audio, document, video, voice, location, venue, contact and much more. In store photo method, we are validating the file. Then, we are sending chat_id and photo to the sendPhoto method. We are using InputFile::createFromContents as a value for photo key which allows us to send photo contents which we are getting by using file_get_contents method. We are also sending a random name with the original extension as the name for the file. Finally, we redirect back the user.

Here’s how our channel looks like after sending message and photo.

Telegram channel view

Well, your Telegram bot is created and working successfully. You can also join this channel at t.me/tutsforweb. Also, you can send messages through the bot and view them on the channel.

Find the source code for this article on GitHub:

I’ve uploaded the code to Heroku. You can find it live here.

I will also be writing part 2 for Telegram to create bots where we will be using webhook method. Our bot will talk to the user for specific commands like we talked to the botfather.

You might also like
Comments