Quick start — Python
Layout
Section titled “Layout”hello/├── manifest.json└── main.pymanifest.json
Section titled “manifest.json”{ "schema": 1, "id": "com.example.hello", "name": "Hello", "version": "1.0.0", "description": "Greets, counts messages and shows a settings page.", "author": { "name": "Example Dev" }, "license": "MIT", "compat": { "freshgram": ">=7.0.0 <8.0.0", "api": 6 }, "runtime": { "kind": "python", "entry": "main.py" }, "permissions": { "required": [ { "id": "messages.read", "reason": "Counts the messages it sees." }, { "id": "messages.send", "reason": "Answers the /hello command." }, { "id": "storage.private", "reason": "Remembers the count." }, { "id": "ui.command", "reason": "Adds the /hello command." }, { "id": "ui.toast", "reason": "Shows short notices." } ] }, "contributes": { "events": ["message.new"], "commands": [{ "name": "hello", "description": "Says hello" }] }}main.py
Section titled “main.py”import freshgram
@freshgram.on("message.new")def counted(event): count = freshgram.storage.get("count", 0) + 1 freshgram.storage.set("count", count) print("message", count, "in chat", event["chat"])
@freshgram.on_command("hello")def hello(event): count = freshgram.storage.get("count", 0) chat = event.get("chat") # missing when the chat is outside the scope you were granted if chat is None: freshgram.ui.toast("Open a chat in an allowed scope first") return freshgram.messages.send(chat, "Hello! I have seen %d messages." % count) freshgram.ui.toast("Said hello")
freshgram.run()Key points:
@freshgram.on("message.new")subscribes a function to an event. The event must also be declared incontributes.events, and receiving it needs themessages.readpermission.@freshgram.on_command("hello")handles the/hellocommand; it is declared incontributes.commandsand needs theui.commandpermission.- A
commandevent carrieschatonly while the chat is inside the scope the user granted, so the handler reads it withevent.get("chat").message.newalways haschat. freshgram.run()at the end is required: it starts the event loop.- Every call is checked against permissions. Without the permission you get a
freshgram.Deniedexception.
Running without the client
Section titled “Running without the client”The host sources include a development mode (fgpl::dev::Run, dev_runner.h): it runs a directory with manifest.json or a .fgpl package against a small fake app. Actions can be typed line by line (REPL) or read from a script file; permissions can be granted and denied (grant/deny) and state kept between runs (state). This lets you debug a plugin without installing it in the client.
- fgpl_tool: package, verify, sign and run plugins
- Manifest
- Permissions
- Lifecycle and events
