API reference
Each handler call may run 2,000,000 Lua instructions, post 20 messages or reactions and make 10 HTTP requests; each script may use 16 MB of memory. Scripts have Lua 5.4’s string, table, math, utf8 and coroutine libraries, the base functions and require for libraries, but no file or process access; the network is reachable only through sideporch.http. Messages are GitHub-flavored Markdown. print(...) writes to the automation’s run log.
Functions
sideporch.on(event, filter_or_handler, handler?): Callshandler(event)wheneventhappens:"message"(new messages in public channels),"message_changed"(edited; the table has the new text),"message_deleted"(the table has what it said),"reaction_added","reaction_removed","reaction"(both),"member_joined","channel_created"or"button"(someone clicked a button under one of this automation’s messages; only the automation that posted it hears about it, andpatternmatches the button’s value). An optional filter table between them narrows it down:channel(name),pattern(a Lua pattern the message text must match),emoji,user(username) andthread(truefor replies in threads,falsefor the rest). Posts and reactions from automations never trigger handlers. The event table’seventfield names the event.sideporch.cron(expression, options_or_handler, handler?): Callshandler()on a cron schedule:minute hour day-of-month month day-of-week, with ranges, lists, steps (*/15), names (mon-fri,jan) and shortcuts such as@hourlyand@daily. Times are in the instance’s automation time zone, or pass{ timezone = "Europe/Berlin" }before the handler.sideporch.command(name, options_or_handler, handler?): Registers the slash command/name, which people type in any channel.handler(cmd)getscmd.text(everything after the name),cmd.args(its words),cmd.user,cmd.username,cmd.channelandcmd.channel_id. Answer privately withsideporch.respond, or publicly withsideporch.postorsideporch.reply(cmd, …). Options:descriptionandusagefor/helpand the composer’s suggestions. Each command name belongs to one automation.sideporch.respond(cmd, text): Answers a slash command with Markdown that only the person who typed it sees.sideporch.on_message(handler): Callshandler(msg)for every new message in a public channel. Messages from automations never trigger it.sideporch.on_reaction(handler): Callshandler(event)when someone adds or removes a reaction on a message in a public channel.sideporch.on_webhook(handler): Callshandler(request)for each HTTP request to this automation’s webhook URL, shown in the editor. What the handler returns becomes the response. A script can register one webhook handler.sideporch.every(seconds, handler): Callshandler()everysecondsseconds, at least 10. The first call comes one interval after the script loads.sideporch.post(channel, text, options?): Poststextto the public channel namedchannel(with or without#), under the automation’s name.options.threadis a message id to answer in that thread;options.buttonsadds up to five buttons, each{ label = "Approve", value = "approve", style = "primary" }(style isprimary,dangeror left out), which people click to triggersideporch.on("button", …). Text is GitHub-flavored Markdown, such as**bold**,[a link](https://example.com), tables, and```mermaiddiagrams.sideporch.reply(message, text, options?): Answersmessagein its thread.messageis a message table fromon_messageor a reaction event’smessage.options.buttonsworks as forsideporch.post.sideporch.update(message, text?, options?): Changes a message this automation posted, such asclick.messagein a button handler: new text (ornilto keep it), andoptions.buttonsto replace its buttons ({}removes them).sideporch.react(message, emoji): Adds the reactionemoji(a name such as"white_check_mark"or a custom emoji) tomessage. Reacting twice with the same emoji has no further effect.sideporch.get(key): Returns the string saved underkeyfor this automation, ornil. Saved data survives restarts and edits.sideporch.set(key, value?): Savesvalueunderkeyas a string (numbers and booleans are converted; usesideporch.json.encodefor tables).nildeletes the key. Keys take up to 200 bytes and values up to 64 kB.sideporch.now(): Returns the current Unix time in seconds.sideporch.http.get(url, options?): Sends a GET request and returns the response:status,ok(true for 2xx),headers(lower-case names),body, andjsonwhen the body is JSON. Options:headersandtimeout(seconds, default 10, at most 30). Network errors raise an error; usepcallto handle them. Redirects are not followed. Private and loopback addresses are refused unless an admin allows them.sideporch.http.post(url, body?, options?): Sends a POST request. A table body is sent as JSON; a string as is. Returns the same response table assideporch.http.get.sideporch.http.request(options): Sends any request:method,url,headers, andbody(a string) orjson(a table), plustimeout. A call may make 10 requests.sideporch.secret(name): Returns the secretname, such as an API token, ornil. Admins store secrets under Automations → Secrets, or setSIDEPORCH_SECRET_<NAME>in the environment. Secret values are replaced in run logs.sideporch.setting(name): Returns the value an admin set for the settingnameunder this automation’s settings, or its declared default: a string, a number or a boolean as declared (a channel’s value is its name). Returnsnilwhen neither is set. Settings come with imported automations and change on the automation’s page, without editing the script; the automation reads new values as soon as they are saved.require(name): Loads the library automationnameonce and returns what it returns, usually a table of functions. Libraries use the samesideporchAPI, acting for the automation that loaded them.sideporch.json.encode(value): Returnsvalueas a JSON string. Empty tables become[]only when made withsideporch.json.array(); otherwise{}.sideporch.json.decode(text): Parses a JSON string into Lua values. JSONnullbecomessideporch.json.null. Fails on invalid JSON; usepcallto handle that.sideporch.json.array(items?): Marks a table as a JSON array, so an empty one encodes as[].
Tables
msg (on_message, reply, react)
id: message idchannel: channel name, without#channel_id: channel idtext: the message text as writtenauthor: display name of the authorusername: the author’s username;nilfor bots and webhooksis_bot:truefor webhook poststhread_id: id of the thread’s first message, orniloutside threads
event (member_joined)
user: display name of the new memberusername: their username
event (channel_created)
channel: the new channel’s namechannel_id: its iduser: display name of who created itusername: their username
cmd (command)
name: the command, without/text: everything typed after the nameargs: the words oftext, as a listuser: display name of who typed itusername: their usernamechannel: the channel’s name, or""in direct messageschannel_id: the channel’s idthread_id: the thread it was typed in, ornil
click (button)
value: the button’s valuelabel: the button’s labeluser: display name of who clicked itusername: their usernamemessage: the message with the button, as amsgtable
response (sideporch.http)
status: HTTP status codeok:truefor 2xx statusesheaders: table of headers, names in lower casebody: the body as a stringjson: the body parsed, when it is JSON
event (on_reaction)
emoji: emoji name, such as"thumbsup"added:truewhen added,falsewhen removeduser: display name of the person reactingusername: their usernamemessage: the message, as amsgtable
request (on_webhook)
method: HTTP method, such as"POST"path: the part of the URL after the webhook token, such as"/deploy", or""query: table of query parametersheaders: table of headers, names in lower casebody: the raw body as a stringjson: the body parsed as JSON, ornil
webhook response (return value of the on_webhook handler)
nil: answers 204 No Contenta string: answers 200 with that text{ status = 200, body = "text" }: status code (default 200) and a text body{ json = value }: a JSON body