Skip to content

Lifecycle and events

The host calls initialization once when the plugin starts:

  • Python — functions registered with @freshgram.on_init are called; they receive {account, plugin, version, api}.
  • Wasm — the fg_init export.

freshgram.info() returns the API version, the plugin id and the granted permissions.

Events arrive as a dictionary with a type key. Subscribing in Python:

@freshgram.on("message.new") # exact name
def a(event): ...
@freshgram.on("chat.*") # prefix with an asterisk
def b(event): ...

A handler may be async. It runs up to the first await while the event is being handled and the rest after the awaited calls are answered; other events are handled meanwhile.

There are ready-made decorators for common cases: on_command, on_menu, on_timer, on_setting, on_dialog, on_window, on_toast, on_chat_opened, on_typing, on_read, on_member, on_title_changed, on_pinned, on_story, on_call, on_user_status, on_app_focus, on_app_blur, on_plugin_message, on_translate, on_ai. See the Python API.

Call freshgram.run() at the end of the script. It reads host messages, calls handlers and sends the host a completion status (0 — success, -1 — exception). Unhandled exceptions are written to the log (freshgram.log).

Handling one event is limited by runtime.limits.eventTimeoutMs (500 ms by default). Do long operations with async calls.

freshgram.unload() stops the plugin after the current event to free memory. The host starts it again on the next event, command, menu click or settings change.

freshgram.timers.set("tick", 60, repeat=True)
@freshgram.on_timer("tick")
def tick(event):
...

Timers live while the app runs and wake a stopped plugin with a timer event. At most 32 timers, with a period from 1 second to 7 days.

freshgram.storage is the plugin’s private storage (permission storage.private), limited by the storageMb quota. get(key, default), set, delete, keys(prefix, limit), usage().