README.md

# AgalaTelegram
Full-featured framework for writing telegram bots in Elixir. 

# Example application
Link to [repository](https://github.com/CarefreeSlacker/sandbox) simple CLI application for receiving and sending messages to telegram bot

Just:
1. `git clone https://github.com/CarefreeSlacker/sandbox`
2. `cd sandbox`
3. Create your bot by @BotFather
4. Add its token to sandbox/config/config.custom.exs into sandbox.agala_telegram.token
5. `mix deps.get`
6. `iex -S mix`
7. ?????
8. PROFIT!

Now you can send and receive messages from created Telegram bot.
1. Incoming messages will be displayed in CLI like this:    
`<User first name> <user_telegram_id> : <Message>`     
`----> You have just received message <----`   
2. For sending message you can use module `Sandbox.MessageSender.answer(<recepient user_telegram_id>, <Your message>)` and then you will see feedback:    
`<bot_name> Bot <bot_id> : <Your message>`   
`----> You have just sent message <----`

## Installation
There will be described the process of creating a bot step by step. Also pay attention to comments in code snippets.

1. Add to your mix.exs
```elixir
def deps do
  [
    {:agala_telegram, "~> 0.1.2"}
  ]
end
```

2. Create request handler
```elixir
defmodule Sandbox.RequestHandler do
  @moduledoc false

  use Agala.Chain.Builder # Add it in handler. It will allow you to use `chain` macro
  use Agala.Provider.Telegram, :handler # Specify provider.
  alias Agala.Conn

  # Chain macro. Works just like `plug` macro.
  # You can pass there module. Like here.
  chain(Agala.Provider.Telegram.Chain.Parser) 
  # Module must
  # 1. Have one `init` method with specification `@spec init(opts :: Keyword.t) :: Keyword.t`. Options will be passed to `call` function.
  # 2. Have one `call` method with specification `@spec call(conn :: Agala.Conn.t, opts :: Keyword.t) :: Agala.Conn.t`. Attention! It must return `Agala.Conn.t` function for chaining.

  # Or you can pass there current module function name
  # Function must have specification `@spec call(conn :: Agala.Conn.t, opts :: Keyword.t) :: Agala.Conn.t`
  chain(:handle)
  chain(:second_handle)

  def handle(%Conn{request: %{message: %{text: text, from: %{first_name: first_name, id: user_telegram_id}}}} = conn, _opts) do
    IO.puts("#{first_name} #{user_telegram_id} : #{text}")
    conn
  end

  def second_handle(conn, _opts) do
    IO.puts("----> You have just received message <----")
    Conn.halt(conn)
  end
end
```

3. Create your bot
You can create it by @BotFather. Just find it, type `/newbot` and follow instructions. In the end copy the token of created bot and paste it into your config file.
```elixir
config :sandbox, :agala_telegram,
  name: "sandbox_telegram_bot", # It must not strict to you telegram bot name. It's using to call specific bot.
  token: "999999999:aaaaaaaaaaaaaaaaaaaaaaaaa-aaaaaaaaa" # Nuff said
```

4. Create bot configuration
```elixir
defmodule Sandbox.BotConfig do
  alias Agala.Provider.Telegram.Conn.ProviderParams

  def get do
    %Agala.BotParams{
      name: Application.get_env(:sandbox, :agala_telegram)[:name], # You can use any string. It's using for sending message from specific bot in paragraph #6
      provider: Agala.Provider.Telegram,
      handler: Sandbox.RequestHandler, # RequestHandler from paragraph #2
      provider_params: %ProviderParams{
        token: Application.get_env(:sandbox, :agala_telegram)[:token], # Token from paragraph #3
        poll_timeout: :infinity
      }
    }
  end
end
```

5. Add Bot to your supervision tree
```elixir
{Agala.Bot, Sandbox.BotConfig.get()}
```
**You can run any number of bots. Just specify different `name` and `token` in each bot configuration.**

6. Create request sender
```elixir
defmodule Sandbox.MessageSender do
  @moduledoc """
  Module for sending messages to telegram
  """

  alias Agala.Provider.Telegram.Helpers
  alias Agala.Conn

  @bot_name Application.get_env(:sandbox, :agala_telegram)[:name] # Bot name just like in bot configuration from paragraph #4

  def answer(telegram_user_id, message) do
    # Function for sending response to bot
    Agala.response_with(
      %Conn{}
      |> Conn.send_to(@bot_name) # You must explicitly specify bot name.
      |> Helpers.send_message(telegram_user_id, message, []) # Helper function for telegram prpovider.
      |> Conn.with_fallback(&message_fallback(&1)) # Fallback after successful request sending. Pass Agala.Conn.t of finished request.
      # It is not necessary to pass fallback. It's just mechanism to make feedback after sending message.
      # For example it is necessary to display that message has been delivered. Or there could become error or something else.
    )
  end

  defp message_fallback(%Conn{fallback: %{"result" => %{"from" => %{"first_name" => first_name, "id" => id, "is_bot" => is_bot}, "text" => text}}} = _conn) do
    bot_postfix = if is_bot, do: "Bot", else: ""
    IO.puts("\n#{first_name} #{bot_postfix} #{id} : #{text}")
    IO.puts("----> You have just sent message <----")
  end
end
```
7. Download dependencies
`mix deps.get`

That's it. Now you can receive and send messages from and to telegram bot.

### Conclusion
For further information you can visit [documentation](https://hexdocs.pm/agala_telegram/api-reference.html) page in hexdocs.pm