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.3.6 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.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)
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.