Plugin Class
Understand plugin metadata, lifecycle hooks, menu items, and request or update interception.
Metadata
Plugin metadata must be defined as plain top-level values. Do not build them dynamically, because the loader parses them from the source file with AST.
Supported metadata keys:
__id____name____description____author____version____icon____app_version____sdk_version____requirements__
Legacy compatibility:
__min_version__is still accepted, but it is treated as__app_version__ = ">=...".
Important details:
__id__and__name__are the only truly required fields.__id__must be 2-32 characters long, start with a letter, and contain only latin letters, digits,_, or-.__requirements__is a list of packages to install through PIP.__description__supports basic markdown rendering in the UI.__author__may be plain text or a Telegram-style handle such as@yourUsername.__version__defaults to1.0if omitted.__icon__uses the formatStickerPackShortName/index, for exampleexteraPlugins/1.__app_version__supports operators such as>=,<=,==,>, and<.__sdk_version__lets you require a minimum plugin SDK version when your plugin depends on newer APIs.
Practical baseline
The SDK in this repository targets the current 1.4.4.3 API surface and expects exteraGram 12.5.1+ for normal initialization.
Basic Structure
Every plugin file should define one class inheriting from BasePlugin.
Settings
To expose a settings screen, implement create_settings(self) -> List[Any].
For the full settings UI system, see Plugin Settings.
Plugin Events
Load and unload
on_plugin_loadruns when the plugin is enabled or restored during app startup.on_plugin_unloadruns when the plugin is disabled or the app is shutting down.
Application events
AppEvent values:
STARTSTOPPAUSERESUME
Settings Storage Helpers
BasePlugin already includes small helpers for persistent plugin settings:
self.get_setting(key, default=None)self.set_setting(key, value, reload_settings=False)self.export_settings()self.import_settings(settings, reload_settings=True)
Menu Items
You can add menu entries to several app menus through MenuItemData.
MenuItemData
MenuItemData fields:
menu_type: MenuItemType- required target menutext: str- required visible titleon_click: Callable[[Dict[str, Any]], None]- required click handleritem_id: Optional[str]- optional stable id if you want to remove the item latericon: Optional[str]- drawable name, such as"msg_info"subtext: Optional[str]- secondary line below the titlecondition: Optional[str]- MVEL expression which controls visibilitypriority: int- larger values usually appear earlier
MenuItemType
Current menu types exposed by the SDK:
MenuItemType.MESSAGE_CONTEXT_MENUMenuItemType.DRAWER_MENUMenuItemType.MAIN_MENUMenuItemType.CHAT_ACTION_MENUMenuItemType.PROFILE_ACTION_MENU
The on_click Context
The callback receives a dictionary with context-dependent values.
Common keys include:
accountcontextfragmentdialog_iduseruserIduserFullchatchatIdchatFullencryptedChatmessagegroupedMessagesbotInfo
Because the exact set depends on the menu type and screen, it is best to inspect the available keys during development:
Removing Menu Items
Menu items are removed automatically when the plugin unloads, but you can also remove one manually:
Event Hooks
Event hooks let your plugin intercept Telegram requests, responses, updates, or outgoing message parameters.
You register them with:
self.add_hook(name, match_substring=False, priority=0)self.add_on_send_message_hook(priority=0)
Every hook receives the account it fired for, and it is often not the account selected in the
UI — background accounts stay connected and keep firing hooks. Modifying the hooked object, as the
examples below do, needs no special care. But the moment you send, request, or read something in
response, use self.client(account) or an explicit account=, or you will act on whichever account
happens to be on screen. See Multi-account.
Hook results are returned as HookResult with a HookStrategy.
Hook strategies
HookStrategy.DEFAULT: do nothing specialHookStrategy.CANCEL: stop the operationHookStrategy.MODIFY: return a modified objectHookStrategy.MODIFY_FINAL: return a modified object and stop further plugin processing for that event
Depending on the hook type, the modified object should be assigned to:
HookResult.requestHookResult.responseHookResult.updateHookResult.updatesHookResult.params
Update hooks
Outgoing message hook
Xposed Method Hooking
For low-level Java method hooking through LSPosed/Xposed-style APIs, see the dedicated Xposed Method Hooking page.