Plugin Class
Understand the Plugin class structure.
Metadata
Metadata should be defined as plain strings. No concatenation or formatting, since it's parsed using AST
.
Required fields: __id__
, __name__
, __description__
, __author__
, __min_version__
.
__author__
: Supports plain text names or Telegram usernames/channel links (e.g., @yourUsername
or @yourPluginChannel
). These may be displayed as clickable links in the UI.
__description__
: Supports basic markdown for formatting.
__version__
: If not defined, your plugin will have version 1.0
by default.
__icon__
: To fill this field, you can use a link to your sticker pack (e.g., https://t.me/addstickers/MyPackName
), then specify the index of the sticker, separated by /. The index starts from 0
(e.g., for the second sticker, use MyPackName/1
).
Settings
You may create an activity for plugin settings using create_settings
method. This method should return a list of setting control objects.
To access settings from the code, use self.get_setting("KEY", DEFAULT_VALUE)
method:
To save or update a setting's value programmatically, use self.set_setting("KEY", NEW_VALUE)
method:
The set_setting
method will persist the new value, and it will be reflected in the settings UI if the control is bound to that key.
Supported controls:
(Note: The type
field is usually set automatically by the system and corresponds to PluginsConstants.Settings.TYPE_...
. Icon names are examples and depend on available resources.)
Plugin events
Load and unload
on_plugin_load
occurs when user enables the plugin or on application startup.on_plugin_unload
occurs when user disables the plugin or on application shutdown.
Application events
The AppEvent
enum provides the following events:
START
- Application is startingSTOP
- Application is stoppingPAUSE
- Application is paused (e.g., backgrounded)RESUME
- Application is resumed (e.g., brought to foreground)
Menu Items
You can add custom actions to various menus within the application, such as the context menu for messages or the action menu in a user's profile. This is done by adding a MenuItemData
object.
MenuItemData
To add a menu item, you call self.add_menu_item()
with a MenuItemData
object, which has the following properties:
menu_type: MenuItemType
: Required. Specifies which menu to add the item to. The available types are:MenuItemType.MESSAGE_CONTEXT_MENU
: Long-press menu on a message.MenuItemType.DRAWER_MENU
: The main navigation drawer (hamburger menu).MenuItemType.CHAT_ACTION_MENU
: The three-dot menu inside a chat screen.MenuItemType.PROFILE_ACTION_MENU
: The three-dot menu on a user, bot, or channel profile screen.
text: str
: Required. The text displayed for the menu item.on_click: Callable[[Dict[str, Any]], None]
: Required. A function that will be called when the user taps the item. It receives a dictionary containing context-specific data.item_id: str
: Optional. A unique ID for this item. Useful if you need to remove it later withremove_menu_item()
. If not provided, a unique ID is generated.icon: str
: Optional. The name of a drawable resource to use as an icon for the item (e.g.,"msg_info"
,"msg_delete"
).subtext: str
: Optional. Additional text displayed below the main text.condition: str
: Optional. A MVEL expression to conditionally show the item. (e.g.,"message.isOut()"
).priority: int
: Optional. A number to influence the item's position in the menu. Higher numbers appear first.
The on_click
Context
The on_click
callback receives a dictionary with data relevant to the context where the menu was opened. The available keys depend on the MenuItemType
and the specific situation. For example, a message context menu will provide a message
object, while a profile menu will provide a user
object.
It's best practice to check for the existence of a key before using it. You can log the dictionary's keys to discover what's available: self.log(f"Context keys: {list(context.keys())}")
.
Here are some of the possible keys you might find in the context dictionary:
account: int
: The current user account instance number.context: android.content.Context
: The Android application context.fragment: org.telegram.ui.ActionBar.BaseFragment
: The current UI fragment.dialog_id: long
: The dialog ID for the current chat.user: TLRPC.User
: TheUser
object (e.g., in a profile menu).userId: long
: The ID of theuser
.userFull: TLRPC.UserFull
: TheUserFull
object with more details.chat: TLRPC.Chat
: TheChat
object for a basic group or channel.chatId: long
: The ID of thechat
.chatFull: TLRPC.ChatFull
: TheChatFull
object with more details.encryptedChat: TLRPC.EncryptedChat
: The object for a secret chat.message: org.telegram.messenger.MessageObject
: TheMessageObject
that was clicked on.groupedMessages: org.telegram.messenger.MessageObject.GroupedMessages
: Information about grouped media (albums).botInfo: TL_bots.BotInfo
: Information about a bot.
Removing Menu Items
If you provided a custom item_id
when adding a menu item, you can remove it programmatically using self.remove_menu_item(item_id)
. However, in most cases, this is not necessary, as all of a plugin's menu items are automatically removed when the plugin is unloaded.
Hooks
To intercept network requests, responses, or client-side events, you first need to register a hook.
You can register hooks for specific Telegram API requests using their TL-schema name:
self.add_hook("TL_messages_readHistory", match_substring: bool = False, priority: int = 0)
name
: The name of the event or request (e.g., "TL_messages_readHistory").match_substring
: IfTrue
, the hook will trigger ifname
is a substring of the actual event/request name. Defaults toFalse
.priority
: Hooks with higher priority are executed first. Defaults to0
.
Examples:
self.add_hook("TL_messages_readHistory")
self.add_hook("requestCall")
self.add_hook("TL_channels_readHistory")
The list of names for requests could be found here.
For the common case of hooking message sending, you can use a helper:
self.add_on_send_message_hook(priority: int = 0)
API Request Hooks
These hooks allow you to inspect or modify outgoing requests and incoming responses.
Hook results determine the action to take:
HookStrategy.DEFAULT
: No changes to the flow; proceed as normal.HookStrategy.CANCEL
: Cancel the request (forpre_request_hook
andon_send_message_hook
) or suppress further processing of the response/update.HookStrategy.MODIFY
: Modify therequest
(inpre_request_hook
),response
(inpost_request_hook
),update
(inon_update_hook
),updates
(inon_updates_hook
), orparams
(inon_send_message_hook
). The modified object must be assigned to the corresponding field in theHookResult
(e.g.,result.request = modified_request
).HookStrategy.MODIFY_FINAL
: Same asMODIFY
, but no other plugins hooks for this event will be called after this one.
Update Hooks
These hooks are called when the application processes updates received from Telegram.
Message Sending Hook
This hook is specifically for intercepting messages being sent by the user.