gotify - push notifications to a Gotify server
Import with import "gotify.j" as gotify;. A tiny module on top of the http client that pushes a notification to a Gotify server. Hold a value-semantic Config (server URL
- application token) and call
push. Because it builds onhttp(which uses
net), this module needs the default jennifer binary.
On
jennifer-tiny: "needs the defaultjenniferbinary" refers to the stock tiny build, which ships without a network driver - not a TinyGo limitation. Ajennifer-tinyrebuilt with a network stack runs this module too; see the note onnetand TinyGo.
import "gotify.j" as gotify;
import "http.j" as http;
def g as gotify.Config init gotify.Config{url: "https://push.example.com",
token: "AqB3cD..."};
def r as http.Response init gotify.push($g, "Deploy", "build 1234 is live", 5);
io.printf("pushed -> %d\n", $r.status); # 200 on successRunnable: examples/modules/gotify_demo.j.
Surface
| Call / type | Notes |
|---|---|
gotify.Config | url (server, no trailing slash) and token (application key). |
gotify.Extras | markdown (bool) and clickUrl (string) - optional message extras. |
gotify.push(cfg, title, message, priority) | POST the message form; returns the http.Response. |
gotify.pushMarkdown(cfg, title, message, priority) | Render the body as markdown; returns the http.Response. |
gotify.pushWith(cfg, title, message, priority, url) | Open url when the notification is tapped; returns the http.Response. |
gotify.pushExtras(cfg, title, message, priority, ex) | Attach an arbitrary Extras (markdown and/or click URL). |
push POSTs title / message / priority as application/x-www-form-urlencoded to cfg.url + "/message" with an X-Gotify-Key: cfg.token header - Gotify's push-message contract, where priority is a plain int (0 lowest, higher is more urgent). It returns the raw http.Response, so the caller checks .status: a 200 on success, and a bad token comes back as a 4xx value, not a crash.
Message extras (markdown, click action)
Gotify's extras let a message carry client hints. Because extras are a nested object, the extras-carrying variants POST a JSON body (application/json) instead of the form - the plain push stays form-encoded and unchanged. Two extras are supported:
- markdown -
pushMarkdown(orExtras{markdown: true}) setsextras["client::display"]["contentType"] = "text/markdown", so the body renders as markdown. - click action -
pushWith(..., clickUrl)(orExtras{clickUrl: url}) setsextras["client::notification"]["click"]["url"] = clickUrl, so tapping the notification opens that URL.
Combine both with pushExtras and an Extras holding both fields. A zero Extras (markdown false, empty clickUrl) adds no extras object, so pushExtras with it matches a plain push (over JSON).
import "gotify.j" as gotify;
def g as gotify.Config init gotify.Config{url: "https://push.example.com", token: "tok"};
# markdown body
def a as http.Response init gotify.pushMarkdown($g, "Report", "# Done\n- built\n- shipped", 5);
# tap-to-open URL
def b as http.Response init gotify.pushWith($g, "Deploy", "build 1234 is live", 5,
"https://ci.example.com/builds/1234");
# both at once
def ex as gotify.Extras init gotify.Extras{markdown: true, clickUrl: "https://ci.example.com/builds/1234"};
def c as http.Response init gotify.pushExtras($g, "Deploy", "**build 1234** is live", 5, $ex);The JSON body pushExtras builds for the combined case is:
{"title":"Deploy","message":"done","priority":8,"extras":{"client::display":{"contentType":"text/markdown"},"client::notification":{"click":{"url":"https://x.example/go"}}}}Stateless by design
There is no init() that stashes the URL and token - a module has no mutable state. The caller holds the value-semantic Config and passes it to each push, the same shape as the time / hash structs. The URL and token are yours to supply and never commit: read them from the environment or a config file. The demo reads GOTIFY_URL / GOTIFY_TOKEN from the environment; the docs use placeholders.
See also
- http.md - the client
gotifyposts through. - modules/index.md - the module catalog and import rules.