ExGram

ExGram

Hex.pmDocumentationHex.pmHex.pmBuild Status

ExGram is a powerful Elixir library for building Telegram Bots. Use the low-level API for fine-grained control, or leverage the opinionated framework for rapid bot development.

Features

Quick Start

Installation

Add to your mix.exs:

def deps do
[
{:ex_gram, "~> 0.65"},
{:jason, "~> 1.4"},
{:req, "~> 0.5"} # HTTP adapter
]
end

Configure the adapter:

# config/config.exs
config :ex_gram, adapter: ExGram.Adapter.Req

Configure the formatter (Optional):

# .formatter.exs
[
# ....
import_deps: [:ex_gram] # Add :ex_gram here
]

Your First Bot

Generate a bot module:

mix bot.new

Add to your supervision tree:

# lib/my_app/application.ex
def start(_type, _args) do
children = [
ExGram,
{MyApp.Bot, [method: :polling, token: "YOUR_BOT_TOKEN"]}
]
Supervisor.start_link(children, strategy: :one_for_one)
end

Implement handlers:

defmodule MyApp.Bot do
use ExGram.Bot, name: :my_bot, setup_commands: true
import ExGram.Dsl.Keyboard
command("start")
command("help", description: "Show help")
middleware(ExGram.Middleware.IgnoreUsername)
def handle({:command, :start, _}, context) do
answer(context, "Welcome! I'm your bot.")
end
def handle({:command, :help, _}, context) do
message = """
Available commands:
/start - Start the bot
/help - Show this help
"""
keyboard =
keyboard :inline do
row do
button "Test button", callback_data: "button"
end
end
answer(context, message, reply_markup: keyboard)
end
def handle({:callback_query, %{data: "button"}}, context) do
context
|> answer_callback("Button clicked!")
|> edit(:inline, "You clicked the button!")
end
end

Run your bot:

mix run --no-halt

DSL Functions

The ExGram DSL builds actions on the context that execute after your handler returns.

Sending Messages

context
|> answer("Hello!")
|> answer_document({:file, "/path/to/file.pdf"})

Inline Keyboards

import ExGram.Dsl.Keyboard
markup =
keyboard :inline do
row do
button "Button text", callback_data: "button"
end
end
answer(context, "Choose:", reply_markup: markup)
markup = create_inline_keyboard([
[%{text: "Button", callback_data: "button"}]
])
answer(context, "Choose:", reply_markup: markup)

Editing & Deleting

edit(context, "Updated message")
edit_markup(context, new_keyboard)
delete(context)

Callback Queries & Inline Queries

answer_callback(context, "Processing...")
answer_inline_query(context, results)

Use steps results

context
|> answer("Important message!")
|> on_result(fn
{:ok, message}, name ->
ExGram.pin_chat_message(message.chat.id, message.message_id, bot: name)
error, _name ->
error
end)

Extracting Information

extract_id(context) # Chat ID
extract_user(context) # User
extract_message_id(context) # Message ID
extract_update_type(context) # Update type
extract_message_type(context) # Message type

Low-Level API

Use ExGram as a library without the framework:

# Configure globally
config :ex_gram, token: "YOUR_TOKEN"
ExGram.send_photo(chat_id, {:file, "photo.jpg"})
ExGram.get_me()
# Or you can pass the token directly
ExGram.send_message(chat_id, "Hello!", token: "YOUR_TOKEN")

All methods return {:ok, result} | {:error, ExGram.Error.t()} and have bang variants:

{:ok, message} = ExGram.send_message(chat_id, "Hello")
message = ExGram.send_message!(chat_id, "Hello") # Raises on error

See the Sending Messages guide for a complete reference or the Cheatsheet for a quick overview.

Documentation

Getting Started

Building Bots

Intermediate

Advanced

Deployment

Reference

Ecosystem

Companion libraries that extend ExGram. If you have a library that extends ExGram feel free to open a discussion to add it here:

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

Beer-Ware License. See LICENSE for details.