Introduction

Telegram is a cloud based mobile and desktop messaging app with a focus on speed and security.

Bots in telegram are used to provide services which makes our life easy and more comfortable. Today, we are going to build one in Elixir using Phoenix framework.

Requirement

— Telegram Bot API Token We need a token of request which is generated by the botfather to make authorized requests to server. Once if you are up with token, we are ready to make uphill battle.

Web-Frameworks

You are suppose to be knowledgeable in one of the Elixir web frameworks available. Some of them are, as follows:

1
2
3
Placid
Sugar
Phoenix

Choose your best. Here I go with Phoenix which is highly recommended by the most of developers because of its channel and plug implementations for socket programming. Phoenix Project Creation

1
mix phoenix.new telegrambot --no-ecto --no-brunch

The above command will create a phoenix application with out ecto and brunch which has no use in our application. Hope you know how to work with phoenix. So that, I am not going to explain about phoenix here.

Webhooks

Next step we need to have a web hook for matching telegram request to server. Check the Telegram Bot API for more information on Telegram webhooks.

1
If you’d like to make sure that the Webhook request comes from Telegram, we recommend using a secret path in the URL, e.g. https://www.example.com/<token>.

Since nobody knows your bot’s token, you can be pretty sure of that request is from the Telegram.

On phoenix router, in botkey it can be any parameter, just so that It needs to be identified that its is send by telegram.

1
2
3
4
5
6
  defmodule Application.Router do
    use Application.Web, :router
      scope "/", Application do
        post "/#{botkey}",PageController, :index
      end
  end

Once route in Phoenix is prepared,

1
https://api.telegram.org/bot#{botkey}/setWebhook?url="https://example.com/#{botkey}"

A GET request will set the web hook in the telegram server.

Till know we configured that, a bot can communicate to your server, now we will configure so that server can talk back to boot.

Nadia — Telegram API framework GitHub — zhyu/nadia: Telegram Bot API Wrapper written in Elixir

In config/config.ex add your Telegram Bot token like following.

1
2
3
def application do
  [applications: [:nadia]]
end
1
2
config :nadia,
  token: bot token

In phoenix controller,

1
2
3
4
5
6
7
8
9
defmodule Application.PageController do
  use Application.Web, :controller
  def index(conn, params) do
    %{from=> from,id=> id,offset=>_,query=>query}= params[inline_query]
    application.search(from[id],id,query)
    conn
    |> json %{ status: true }
  end
end

We have to extract the data from the query, if you are using inline_query, this is the format. For different responses refer to telegram API.

Once query and request id is extracted, its upto to the logic of our application.

Nadia, is a good application that can be used to send responses, well Nadia has full features, you can send any responses. Currently this example is limited to text reply.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
defmodule Qwantclient do

  def search(userid, requestId, query) do
    request(query)
    |>Poison.decode!
    |>parser
    |>send_toUser(requestId)
  end

  def request(query) do
    url = "https://api.qwant.com/api/search/web?q=#{query}"
    case HTTPoison.get(url) do
      {:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
        body
      {:error, %HTTPoison.Error{reason: reason}} ->
        IO.puts "reason #{inspect reason}"
        reason
    end
  end
  def parser(data) do
    data["data"]["result"]["items"]                                          
    |> Enum.map(fn (item)->
          article = %Nadia.Model.InlineQueryResult.Article{}                        
          %{article | title: item["title"],                                                       
              thumb_url: "http:"<>item["favicon"],                                                 
              description: item["desc"],                                                  
              url: item["url"],                                                           
              id: item["_id"],                                  
              input_message_content: %Nadia.Model.InputMessageContent.Text{ %Nadia.Model.InputMessageContent.Text{} | message_text: item["title"]<>item["desc"], parse_mode: "HTML" }
            } end)
  end
    def send_toUser(response,requestId) do
      res = Nadia.answer_inline_query(requestId, response)
      IO.inspect res
      IO.puts "nadi"
    end
end

Bot Response

img

If every thing goes well after pushing your code to heroku and running, you’ll see a response like above image.