Standard library · Web and services

telegram/bot

Building a bot with the Bot API: messages, buttons, webhooks and a polling loop.

import telegram.bot

To build a bot, get a token from BotFather and make one with NewBot. A bot has two ways of taking messages: Poll, which asks Telegram itself and suits testing and simple servers, or a webhook, where Telegram POSTs the messages to your server.

With a webhook you can send the answer straight in the body of the HTTP response; the Reply... functions build that JSON text. Set a secret with SetWebhookSecret and check its header on every request.

Types

User

struct User
One Telegram user.
NameTypeDescription
idi64 = 0The id.
is_botbool = falseIt is a bot.
first_namestr = ""The first name.
last_namestr = ""The last name.
usernamestr = ""The user name.
language_codestr = ""The language of the user, such as fa.
telegram-bot-Parse.salam
import telegram.bot

func main:
    text := `{"update_id":10,"message":{"message_id":5,"date":1700000000,"text":"/start hello","chat":{"id":42,"type":"private","first_name":"Maryam","username":"maryam"},"from":{"id":42,"is_bot":false,"first_name":"Maryam","language_code":"en"},"reply_to_message":{"message_id":4,"from":{"id":7,"first_name":"Ali"}}}}`
    update := bot.ParseUpdate(text)
    println update.update_id, update.has_message, update.has_callback_query
    m := update.message
    println m.message_id, m.date, m.text, m.chat.id, m.chat.chat_type, m.chat.first_name, m.chat.username
    println m.from_user.id, m.from_user.is_bot, m.from_user.language_code, m.reply_to.message_id, m.reply_to.user_id, m.reply_to.user_name
    println bot.IsCommand(m.text), bot.CommandName(m.text), bot.CommandArgs(m.text)
    println bot.IsCommand("hello"), bot.CommandName("/help@my_bot")

    all := bot.ParseUpdates(`{"ok":true,"result":[{"update_id":11,"callback_query":{"id":"cq1","data":"yes","from":{"id":42,"first_name":"Maryam"},"message":{"message_id":9,"chat":{"id":42,"type":"private"}}}},{"update_id":12,"inline_query":{"id":"iq1","query":"book","offset":"","from":{"id":42,"first_name":"Maryam"}}}]}`)
    println all.len()
    q := all[0].callback_query
    println all[0].has_callback_query, q.id, q.data, q.from_user.first_name, q.has_message, q.message.message_id
    typed := all[1].inline_query
    println all[1].has_inline_query, typed.id, typed.query, typed.offset.len()
    println bot.ParseUser(`{"id":1,"first_name":"x","last_name":"y","is_bot":true}`).last_name
    println bot.ParseChat(`{"id":-100,"type":"supergroup","title":"the group"}`).title
    println bot.ParseMessage(`{"message_id":1,"caption":"a photo","chat":{"id":1}}`).caption
    println bot.ParseCallbackQuery(`{"id":"q","data":"d"}`).data, bot.ParseInlineQuery(`{"id":"i","query":"q"}`).query
    println bot.ParseUpdate(`{"update_id":13,"channel_post":{"message_id":1,"text":"news","chat":{"id":-5}}}`).channel_post.text

    mut row1 := Vector {} as Vector<str>
    row1.push(bot.InlineButton("yes", "yes"))
    row1.push(bot.InlineButton("no", "no"))
    mut row2 := Vector {} as Vector<str>
    row2.push(bot.InlineButtonURL("the site", "https://salamlang.ir"))
    mut rows := Vector {} as Vector<str>
    rows.push(bot.Row(row1))
    rows.push(bot.Row(row2))
    println bot.InlineKeyboardMarkup(rows)
    mut plain := Vector {} as Vector<str>
    plain.push(bot.KeyboardButton("menu"))
    mut plain_rows := Vector {} as Vector<str>
    plain_rows.push(bot.Row(plain))
    println bot.ReplyKeyboardMarkup(plain_rows)
    println bot.RemoveKeyboard(), bot.ForceReply()
    println bot.BotCommand("start", "start it")

    robot := bot.NewBot("123:ABC")
    println bot.FileURL(robot, "photos/file_1.jpg")
    println bot.ReplyMessage(42, "hello")
    mut options := bot.SendOptions {}
    options.parse_mode = "HTML"
    options.reply_to_message_id = 5
    options.disable_notification = true
    println bot.ReplyMessageOptions(42, "<b>hello</b>", options)
    println bot.ReplyAnswerCallbackQuery("cq1", "noted", false)
    println bot.ReplyChatAction(42, "typing")
    println bot.ReplyEditMessageText(42, 9, "updated", bot.RemoveKeyboard())
    println bot.SECRET_HEADER
end

Chat

struct Chat
One chat: private, a group or a channel.
NameTypeDescription
idi64 = 0The id; negative for groups.
chat_typestr = ""The type: private, group, supergroup or channel.
titlestr = ""The title of the group or channel.
usernamestr = ""The user name.
first_namestr = ""The first name.
last_namestr = ""The last name.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

ReplyTo

struct ReplyTo
The message this one is a reply to.
NameTypeDescription
message_idi64 = 0The id of that message.
user_idi64 = 0The id of its sender.
user_namestr = ""The name of its sender.
telegram-bot-Bot.salam
import telegram.bot
import env

func handle(update: bot.Update):
    if not update.has_message:
        ret
    end
    println update.message.from_user.first_name, update.message.text
end

func main:
    robot := bot.NewBot(env.Get("TELEGRAM_TOKEN"))
    me := bot.GetMe(robot)
    if not bot.Ok(me):
        println me.error_code, me.description, me.http_status, me.http_err
        ret
    end
    println me.ok, me.result
    chat := 42 as i64
    _ := bot.SendMessage(robot, chat, "hello")
    _ := bot.SendMessage(robot, "@my_channel", "fresh news")
    mut options := bot.SendOptions {}
    options.parse_mode = "Markdown"
    options.reply_markup = bot.RemoveKeyboard()
    _ := bot.SendMessageOptions(robot, chat, "*important*", options)
    _ := bot.SendPhoto(robot, chat, "https://example.com/a.jpg", "a photo")
    _ := bot.SendDocument(robot, chat, "BQACAgQAAx", "")
    _ := bot.SendVideo(robot, chat, "https://example.com/v.mp4", "")
    _ := bot.SendAudio(robot, chat, "https://example.com/a.mp3", "")
    _ := bot.SendVoice(robot, chat, "AwACAgQ", "")
    _ := bot.SendSticker(robot, chat, "CAACAgI")
    _ := bot.SendLocation(robot, chat, 35.6997, 51.338)
    _ := bot.SendContact(robot, chat, "+989120000000", "Ali")
    _ := bot.SendChatAction(robot, chat, "typing")
    _ := bot.EditMessageText(robot, chat, 10, "edited")
    _ := bot.ForwardMessage(robot, chat, 43, 11)
    _ := bot.PinChatMessage(robot, chat, 10)
    _ := bot.UnpinChatMessage(robot, chat, 10)
    _ := bot.DeleteMessage(robot, chat, 10)
    _ := bot.AnswerCallbackQuery(robot, "cq1", "noted")
    _ := bot.AnswerInlineQuery(robot, "iq1", "[]")
    file := bot.GetFile(robot, "AgACAgQ")
    println file.result.len() > 0
    _ := bot.GetChat(robot, chat)
    _ := bot.GetChatMemberCount(robot, chat)
    _ := bot.GetChatMember(robot, chat, 7)
    _ := bot.BanChatMember(robot, chat, 7)
    _ := bot.UnbanChatMember(robot, chat, 7)
    _ := bot.LeaveChat(robot, -100)
    mut commands := Vector {} as Vector<str>
    commands.push(bot.BotCommand("start", "start it"))
    _ := bot.SetMyCommands(robot, commands)
    _ := bot.SetWebhook(robot, "https://example.com/hook")
    _ := bot.SetWebhookSecret(robot, "https://example.com/hook", "my-secret")
    _ := bot.GetWebhookInfo(robot)
    _ := bot.DeleteWebhook(robot)
    mut params := HashMap {} as HashMap<str, str>
    params.insert("chat_id", "42")
    _ := bot.Call(robot, "getChatAdministrators", params)
    updates := bot.GetUpdates(robot, 0, 10, 30)
    println bot.ParseUpdates(updates.result).len(), robot.token.len() > 0
    bot.Poll(robot, 30, (update: bot.Update):
        handle(update)
    end)
end

Message

struct Message
One message.
NameTypeDescription
message_idi64 = 0The id.
datei64 = 0The time in Unix seconds.
chatChatThe chat.
from_userUserThe sender.
textstr = ""The text.
captionstr = ""The caption of a photo or file.
reply_toReplyToThe message that was replied to.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

CallbackQuery

struct CallbackQuery
One press of an inline button.
NameTypeDescription
idstr = ""The id; answer with it.
from_userUserThe user.
messageMessageThe message the button was in.
has_messagebool = falseIt has a message.
datastr = ""The data of the button.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

InlineQuery

struct InlineQuery
An inline query, from when a user types @bot.
NameTypeDescription
idstr = ""The id.
from_userUserThe user.
querystr = ""The text.
offsetstr = ""The paging position.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

Update

struct Update
One event from Telegram; only one of its parts is filled in.
NameTypeDescription
update_idi64 = 0The id; pass one more than it to the next GetUpdates.
messageMessageThe message.
has_messagebool = falseIt has a message.
channel_postMessageA channel post.
has_channel_postbool = falseIt has a channel post.
callback_queryCallbackQueryA button press.
has_callback_querybool = falseIt has a button press.
inline_queryInlineQueryAn inline query.
has_inline_querybool = falseIt has an inline query.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

ApiResponse

struct ApiResponse
A Bot API response.
NameTypeDescription
okbool = falseIt succeeded.
resultstr = ""The result as JSON.
descriptionstr = ""The error description.
error_codei64 = 0The Telegram error code.
http_statusint = 0The HTTP status code.
http_errstr = ""The network error.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

SendOptions

struct SendOptions
The options for sending a message.
NameTypeDescription
parse_modestr = ""The text format: HTML or MarkdownV2.
disable_notificationbool = falseSend it silently.
reply_to_message_idi64 = 0Reply to this message.
reply_markupstr = ""The keyboard as JSON.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

Bot

struct Bot
One bot.
NameTypeDescription
tokenstr = ""The token from BotFather; keep it secret.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

Constants and variables

SECRET_HEADER

const SECRET_HEADER: str = "X-Telegram-Bot-Api-Secret-Token"
The name of the header the webhook secret arrives in.
telegram-bot-Webhook.salam
import telegram.bot
import net.http
import net.router

func webhook(ctx: i64):
    if http.Ctx_header(ctx, bot.SECRET_HEADER) != "my-secret":
        http.Ctx_status(ctx, 403)
        http.Ctx_text(ctx, "forbidden")
        ret
    end
    update := bot.ParseUpdate(http.Ctx_body(ctx))
    if update.has_message and bot.IsCommand(update.message.text):
        answer := "the command " + bot.CommandName(update.message.text) + " arrived"
        http.Ctx_json(ctx, bot.ReplyMessage(update.message.chat.id, answer))
    else update.has_callback_query:
        http.Ctx_json(ctx, bot.ReplyAnswerCallbackQuery(update.callback_query.id, "all right", true))
    else:
        http.Ctx_text(ctx, "ok")
    end
end

func main:
    mut r := router.NewRouter()
    router.Post(r, "/hook", webhook)
    mut s := http.NewServer(19632)
    http.Use(s, r)
    _ := http.RunBackground(s)

    mut headers := http.NewHeaders()
    headers.insert(bot.SECRET_HEADER, "my-secret")
    headers.insert("Content-Type", "application/json")
    a := http.PostWith("http://127.0.0.1:19632/hook", `{"update_id":1,"message":{"message_id":2,"text":"/start","chat":{"id":42,"type":"private"}}}`, headers)
    println http.Status(a), http.Body(a)
    b := http.PostWith("http://127.0.0.1:19632/hook", `{"update_id":2,"callback_query":{"id":"cq9","data":"x","from":{"id":42}}}`, headers)
    println http.Body(b)
    c := http.Post("http://127.0.0.1:19632/hook", "{}")
    println http.Status(c)
end

Functions

ParseUser

func ParseUser(raw: str): User
Reads a user from JSON.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

ParseChat

func ParseChat(raw: str): Chat
Reads a chat from JSON.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

ParseMessage

func ParseMessage(raw: str): Message
Reads a message from JSON.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

ParseCallbackQuery

func ParseCallbackQuery(raw: str): CallbackQuery
Reads a button press from JSON.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

ParseInlineQuery

func ParseInlineQuery(raw: str): InlineQuery
Reads an inline query from JSON.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

ParseUpdate

func ParseUpdate(raw: str): Update
Reads one update from JSON.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

ParseUpdates

func ParseUpdates(raw: str): Vector<Update>
Turns the result of getUpdates into a list of updates.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

NewBot

func NewBot(token: str): Bot
A bot with a token.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

Ok

func Ok(resp: ApiResponse): bool
The response succeeded.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

Call

func Call(bot: Bot, method: str, params: HashMap<str, str>): ApiResponse
Calls any Bot API method with its parameters.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

GetMe

func GetMe(bot: Bot): ApiResponse
The details of the bot itself; for testing the token.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

GetUpdates

func GetUpdates(bot: Bot, offset: i64, limit: i64, timeout: i64): ApiResponse
Takes the updates from the given position, with long polling.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

SendMessage

func SendMessage(bot: Bot, chat_id: i64, text: str): ApiResponse
Sends a text message; the chat by numeric id or by channel name, such as @channel.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

SendMessage

func SendMessage(bot: Bot, chat_id: str, text: str): ApiResponse
Sends a text message; the chat by numeric id or by channel name, such as @channel.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

SendMessageOptions

func SendMessageOptions(bot: Bot, chat_id: i64, text: str, opts: SendOptions): ApiResponse
A message with options.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

SendPhoto

func SendPhoto(bot: Bot, chat_id: i64, photo: str, caption: str): ApiResponse
Sends a photo by address or file id, with a caption.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

SendDocument

func SendDocument(bot: Bot, chat_id: i64, document: str, caption: str): ApiResponse
Sends a file by address or file id, with a caption.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

SendVideo

func SendVideo(bot: Bot, chat_id: i64, video: str, caption: str): ApiResponse
Sends a video by address or file id, with a caption.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

SendAudio

func SendAudio(bot: Bot, chat_id: i64, audio: str, caption: str): ApiResponse
Sends a song by address or file id, with a caption.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

SendVoice

func SendVoice(bot: Bot, chat_id: i64, voice: str, caption: str): ApiResponse
Sends a voice message by address or file id, with a caption.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

SendSticker

func SendSticker(bot: Bot, chat_id: i64, sticker: str): ApiResponse
A sticker.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

SendLocation

func SendLocation(bot: Bot, chat_id: i64, latitude: f64, longitude: f64): ApiResponse
A geographic location.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

SendContact

func SendContact(bot: Bot, chat_id: i64, phone_number: str, first_name: str): ApiResponse
A contact.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

SendChatAction

func SendChatAction(bot: Bot, chat_id: i64, action: str): ApiResponse
Shows a status such as "typing".

The example for this item is shown with the ones above: telegram-bot-Bot.salam

EditMessageText

func EditMessageText(bot: Bot, chat_id: i64, message_id: i64, text: str): ApiResponse
Edits the text of a message that was sent.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

DeleteMessage

func DeleteMessage(bot: Bot, chat_id: i64, message_id: i64): ApiResponse
Deletes the message.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

ForwardMessage

func ForwardMessage(bot: Bot, chat_id: i64, from_chat_id: i64, message_id: i64): ApiResponse
Forwards a message from another chat.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

PinChatMessage

func PinChatMessage(bot: Bot, chat_id: i64, message_id: i64): ApiResponse
Pins the message.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

UnpinChatMessage

func UnpinChatMessage(bot: Bot, chat_id: i64, message_id: i64): ApiResponse
Unpins it.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

AnswerCallbackQuery

func AnswerCallbackQuery(bot: Bot, callback_query_id: str, text: str): ApiResponse
Answers a button press; until you answer, the button stays in its loading state.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

AnswerInlineQuery

func AnswerInlineQuery(bot: Bot, inline_query_id: str, results: str): ApiResponse
Sends the results of an inline query.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

GetFile

func GetFile(bot: Bot, file_id: str): ApiResponse
The file details, for downloading.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

FileURL

func FileURL(bot: Bot, file_path: str): str
The download address of a file.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

GetChat

func GetChat(bot: Bot, chat_id: i64): ApiResponse
The details of a chat.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

GetChatMemberCount

func GetChatMemberCount(bot: Bot, chat_id: i64): ApiResponse
The number of members.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

GetChatMember

func GetChatMember(bot: Bot, chat_id: i64, user_id: i64): ApiResponse
The status of one member.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

LeaveChat

func LeaveChat(bot: Bot, chat_id: i64): ApiResponse
The bot leaves the chat.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

BanChatMember

func BanChatMember(bot: Bot, chat_id: i64, user_id: i64): ApiResponse
Bans a member.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

UnbanChatMember

func UnbanChatMember(bot: Bot, chat_id: i64, user_id: i64): ApiResponse
Lifts the ban.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

SetWebhook

func SetWebhook(bot: Bot, url: str): ApiResponse
Sets the webhook address, so Telegram sends the updates to it.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

DeleteWebhook

func DeleteWebhook(bot: Bot): ApiResponse
Takes the webhook away.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

GetWebhookInfo

func GetWebhookInfo(bot: Bot): ApiResponse
The state of the webhook.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

BotCommand

func BotCommand(command: str, description: str): str
One command for the bot menu.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

SetMyCommands

func SetMyCommands(bot: Bot, commands: Vector<str>): ApiResponse
Sets the command menu of the bot.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

InlineButton

func InlineButton(text: str, callback_data: str): str
An inline button with data.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

InlineButtonURL

func InlineButtonURL(text: str, url: str): str
An inline button with a link.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

KeyboardButton

func KeyboardButton(text: str): str
A reply keyboard button.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

Row

func Row(buttons: Vector<str>): str
One row of buttons.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

InlineKeyboardMarkup

func InlineKeyboardMarkup(rows: Vector<str>): str
An inline keyboard from rows.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

ReplyKeyboardMarkup

func ReplyKeyboardMarkup(rows: Vector<str>): str
A reply keyboard from rows.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

RemoveKeyboard

func RemoveKeyboard(): str
Takes the reply keyboard away.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

ForceReply

func ForceReply(): str
Makes the user reply.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

IsCommand

func IsCommand(text: str): bool
The text starts with a /.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

CommandName

func CommandName(text: str): str
The command name, without the / and without @bot.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

CommandArgs

func CommandArgs(text: str): str
The rest of the text after the command.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

Poll

func Poll(bot: Bot, timeout: i64, handler: func(Update))
The polling loop: it takes the updates with long polling and calls the function for each one; it does not return.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

SetWebhookSecret

func SetWebhookSecret(bot: Bot, url: str, secret_token: str): ApiResponse
A webhook with a secret that Telegram sends in the SECRET_HEADER header; reject forged requests with it.

The example for this item is shown with the ones above: telegram-bot-Bot.salam

ReplyMessage

func ReplyMessage(chat_id: i64, text: str): str
A webhook reply that sends a message; make it the body of the HTTP response and no separate request is needed.

The example for this item is shown with the ones above: telegram-bot-Webhook.salam

ReplyMessageOptions

func ReplyMessageOptions(chat_id: i64, text: str, opts: SendOptions): str
The same, with options.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

ReplyEditMessageText

func ReplyEditMessageText(chat_id: i64, message_id: i64, text: str, reply_markup: str): str
A webhook reply that edits the text of a message.

The example for this item is shown with the ones above: telegram-bot-Parse.salam

ReplyAnswerCallbackQuery

func ReplyAnswerCallbackQuery(callback_query_id: str, text: str, show_alert: bool): str
A webhook reply to a button press.

The example for this item is shown with the ones above: telegram-bot-Webhook.salam

ReplyChatAction

func ReplyChatAction(chat_id: i64, action: str): str
A webhook reply with a chat action.

The example for this item is shown with the ones above: telegram-bot-Parse.salam