Skip to content
This repository was archived by the owner on Oct 30, 2024. It is now read-only.

Tutorials

Daniel Daudysh edited this page Mar 7, 2023 · 9 revisions

Handling the updates

Referring to vtelegram 0.6 version

Update handling flow can be defined as follows:

Getting update -> Filters -> Middleware -> Filters -> Your Handling Function

Handler Function is last that will be executed in an update handling chain. 'Handler function' (or handler method) should look like this:

[handler type]
fn (mut app App) your_method_name(result vtelegram.Result) {
    // your handlings
}
  1. To get module to know which methods will be processed you need to set your function as method, in this example it is a method of App struct, which contains bot token and will be passed to vtelegram.start_polling

  2. Your bot methods must accept Result type argument to not get compile time errors.

    • Result type in method argument at this moment contains:
    update Update // update which are passed to function
    data map[string]string // data which can be added on middlewares
  3. To specify handler types in method attributes, use the attributes below.

Update Handler Types

message
edited_message
channel_post
edited_channel_post
inline_query
chosen_inline_result
callback_query
shipping_query
pre_checkout_query
poll
poll_answer
my_chat_member
chat_member
chat_join_request

Handler type refer to update type in Telegram Bot API.
Which handler type is set above the handler function, that update will apply to this function.

You can set context types on handlers as well as on top of middlewares, to know more about what is context filters you can look into this tutorial, as well as middleware tutorial

Simple example with context filters

This method means that on users enters the /greetings command, bot will reply with greetings text, and this will only be in group chat (also bot should be admin of the group to get such updates or command should look like /greetings@your_bot_username_bot)

[message: '/greetings'] // or [message: '/greetings@your_bot_username_bot']
[context: 'group']
fn (mut app App) greetings(result vt.Result) ! {
	result.update.message.reply(mut app, text: 'Hello, I\'m the Bot!')!
}

More use cases you can find in examples directory.

Context Filters

Referring to vtelegram 0.6 version

Update handling flow can be defined as follows:

Getting update -> Filters -> Middleware -> Filters -> Your Handling Function

Context Filters defines which updates will be handled with your middleware and with your handling methods.

To specify a context filter you need to use a context keyword, set the attribute on top of the relevant method. Like so:

// on top of handler
[message: '/start'] // will pe processed when user enter /start message
[context: 'private'] // specifies that method will be processed only in private chats
fn (mut app App) on_start_command(result vtelegram.Result) ! {
    // your start command handling
}

// on top of middleware
[message] // speciefies middleware type, will apply only to messages (all chats - private, groups)
[context: 'group'] // filter specifies that will be handled only group messages
fn (mut mw MyMiddleware) my_message_middleware(mut update Update) bool {
    // your message middleware handling
}

You can set a few context filters on one method:

['context: photo']
['context: video']
['context: voice']
[message]
fn (mut app App) on_all_messages(result vtelegram.Result) ! {}

Note For now, if you use a few attributes with the same name, you must put attributes into quotes, to not get compile time error. Should be [context: 'photo, video, voice'] in the future.

Example above specifies handler, which will be executed on all messages which contains photo, video or voice

Be aware that some of filter + handler type combination no makes sense, cause method not be executed ever. This combination will not pass ever:

[message]  // set handling type 'message' is not related to channels
[context: 'channel'] // set context 'channel' is not make sense with message type

in this case to handle channel you may use channel_post handler type. context 'channel' is needed for other use cases.

[channel_post]

Context Filter Types

Available contexts at the moment are:

// text filter relative to messages updates with text or caption
text
// forward filter relative to messages updates which are forwarded, apply to messages and channel_post
forward
// reply filter relative to messages updates which are replies to other messages
reply
// private filter relative to chat type, which is private
private
// group filter relative to chat type, which is group or supergroup
group
// channel filter relative to chat type, which is channel
channel
// if update.message.from.is_bot
sender_bot
// if update.message.from.is_bot == false
sender_user
// if update.message.sender_chat.@type == 'group' or 'supergroup'
sender_group
// if update.message.sender_chat.@type == 'channel'
sender_channel
// filters below relative to the relevant meaning in the Telegram Bot API
entities
animation
audio
document
photo
sticker
video
video_note
voice
contact
dice
game
poll
venue
location
new_chat_members
left_chat_member
new_chat_title
new_chat_photo
delete_chat_photo
group_chat_created
supergroup_chat_created
channel_chat_created
message_auto_delete_timer_changed
is_topic_message
pinned_message
invoice
successful_payment
user_shared
chat_shared
connected_website
write_access_allowed
passport_data
proximity_alert_triggered
video_chat_scheduled
video_chat_started
video_chat_ended
video_chat_participants_invited
web_app_data

All filters logic is in filters.v

More use cases you can find in examples directory.

Middleware Tutorial

Referring to vtelegram 0.6 version

Update handling flow can be defined as follows:

Getting update -> Filters -> Middleware -> Filters -> Your Handling Function

Middleware is your defined functions, which will process before your handling functions.

For now middlewares can:

  • Prevent update for passing to handlers ( middleware methods must return bool, false for prevent update )
  • Transform update
  • Pass data in map[string]string type to handlers

To initialize middleware, you need to create one global struct and add methods to it. That will be all your middlewares, as much as you want. To get module to know what struct is your middleware, you need pass your struct name to vtelegram.start_polling

import vtelegram

// define main middleware struct
struct MyBaseMiddleware{}

// define your app struct, Bot module struct must be nested
struct App{
    vtelegram.Bot
}

// message middleware
[message]
fn (mut mw MyBaseMiddleware) my_message_middleware(mut update vtelegram.Update) bool {
    // do something
    return true // true means the middleware approves passing the update to handlers
}

// channel post middleware
[channel_post]
fn (mut mw MyBaseMiddleware) my_channel_middleware(mut update vtelegram.Update) bool {
    // add text to update, which will be passed to handlers. (Doesn't change message which recieved in channel post, just change update which will be passed to handlers)
    update.channel_post.text += '\nProcessed with middleware.' 
    return true
}

fn main(){
    // initialize your bot app, token adding
    mut app := App{
        token: 'YOUR_BOT_TOKEN'
    }

    // The main point to make your middleware work is to cast it to a generic type struct PollingConfig
    polling_config := vtelegram.PollingConfig[MyBaseMiddleware]{
        allowed_updates:['message', 'channel_post'] // parameter from getUpdate telegram method
        delay_time: 2000 // pause between getting updates (default 1000) in milliseconds
    }

    // starting your bot app with middleware in polling config
    vtelegram.start_polling(mut app, polling_config)
}

To define to which type of handlers middleware apply, set attribute on top of your middleware method.

Middleware can be extended with context filters, which will expand the context of handled updates.
To pass data to handlers from your middleware, you need set data field to your middleware struct, which have map[string]string type.

Note That you need to clear the data from middleware manually, otherwise data will be saved

import vtelegram

// define main middleware struct
struct MyBaseMiddleware {
mut:
	data map[string]string
}

// define your app struct, Bot module struct must be nested
struct App {
	vtelegram.Bot
mut:
// setting middleware instance to app for data manipulations
	middleware MyBaseMiddleware
}

// message middleware
[message]
fn (mut mw MyBaseMiddleware) my_message_middleware(mut update vtelegram.Update) bool {
	// do something
	// add some data, for example from db
	mw.data['data_from_db'] = 'some_data'
	return true // true means the middleware approves passing the update to handlers
}

// message handler
[message]
fn (mut app App) your_app_handler(result vtelegram.Result) ! {
	// do something
	// passed data is present
	data_from_db := result.data['data_from_db']
	println('Data from middleware is: ${data_from_db}')
}

fn main() {
	// initialize your bot app
	mut app := App{
		token: 'YOUR_BOT_TOKEN'
	}
	// set logging
	app.log.set_level(.debug)
	app.log.set_full_logpath('./bot.log')
	polling_config := vtelegram.PollingConfig[MyBaseMiddleware]{}

	// starting your bot app with middleware in polling config
	vtelegram.start_polling(mut app, polling_config)
}

More use cases you can find in examples directory.

Clone this wiki locally