Skip to main content

Writing a plugin

A plugin is a .chatt file with a name and at least one thing it reacts to.

The smallest plugin that does anything​

plugin "Hello"

on message do
alert("Someone said something")
end

Save it as hello.chatt, reload, switch it on, and your screen fills with alerts. Which teaches the first real lesson: say when.

plugin "Hello"

on message do
if event.text contains "hello" then
alert(event.user + " said hello")
end
end

The header​

Four lines can go at the top, all optional except the name.

plugin "Repeat offender"
description "Speaks up when the same person keeps getting timed out."
author "Your name"
setting actions = 3 "Mod actions before alerting"
  • plugin is the name shown in Settings. Required.
  • description is the line under it. Write it for the person deciding whether to switch this on.
  • author is you.
  • setting adds a box in Settings that changes the value without editing the file. See Settings below.

Events​

Everything a plugin does hangs off an on ... do ... end block:

on timeout do
alert(event.user + " was timed out by " + event.by)
end

Inside the block, event holds the details. What is on it depends on the event: event.user, event.text, event.channel and so on. The full list is on the events page.

A plugin can have as many blocks as it likes, including several for the same event.

Settings​

A setting line gives a value a name, a default, and a label:

setting actions = 3 "Mod actions before alerting"
setting window = 15 minutes "How far back to look"
setting words = ["free", "gift"] "Words to watch for"
setting chime_too = true "Play a chime as well"

The default decides what the box in Settings looks like:

DefaultBox
3a number
15 minutesa number, labelled in minutes
30 secondsa number, labelled in seconds
true / falsea switch
"text"a text box
["a", "b"]a text box, comma separated

Use the name anywhere in the script, like any other value:

if count(event.user, window) >= actions then

Counting things​

Most useful alerts are about something happening more than once. Two builtins do the work:

bump("key") # note that it happened, now
count("key", 5 minutes) # how many times in the last five minutes

The key is any text you make up. Use it to keep counts apart:

on timeout do
let key = event.channel + "/" + event.user
bump(key)
if count(key, 10 minutes) >= 3 then
alert(event.user + " keeps getting timed out")
end
end

Not repeating yourself​

That example alerts on the third timeout, then the fourth, then the fifth. cooldown fixes it - it returns true the first time and false until the wait is over:

if count(key, 10 minutes) >= 3 and cooldown(key, 10 minutes) then
alert(event.user + " keeps getting timed out")
end

Chattler also puts a hard cap on top: six alerts per plugin per ten seconds. Beyond that they are dropped and noted in the plugin's log.

Remembering things​

remember and recall keep a value between events:

on message do
remember("last/" + event.channel, event.user)
end

on timeout do
if recall("last/" + event.channel) = event.user then
alert("The last person to talk just got timed out")
end
end

Counters and notes live in memory, so they start empty when Chattler opens.

Sharing code between handlers​

define makes a function. Handy when two events should do the same thing:

define watch(who, where) do
let key = where + "/" + who
bump(key)
if count(key, window) >= actions and cooldown(key, window) then
alert(who + " has had " + count(key, window) + " actions in " + where, "warn")
end
end

on timeout do
watch(event.user, event.channel)
end

on ban do
watch(event.user, event.channel)
end

How loud to be​

alert takes an optional level that changes the colour of the strip on the alert:

alert("someone is talking", "info") # default
alert("this needs a look", "warn") # amber
alert("this needs you now", "urgent") # red

Sound and desktop notifications are separate, and both are your choice:

chime() # the highlight chime
chime("automod") # the AutoMod chime
notify("Raid", "500 people just arrived")
Streamer mode

When streamer mode is on, chimes and desktop notifications from plugins are silenced along with everything else. Alerts still appear in the app.

Testing it​

There is no test harness. The fastest loop is:

  1. Save the file.
  2. Settings → Reload.
  3. Make the thing happen, or wait for it.
  4. Check Recent alerts under the plugin in Settings - log("...") writes there without raising an alert.

log is your print statement:

on message do
log("saw " + event.user + ": " + event.text)
end

Switch that on in a busy chat and you will have sixty lines in a second, so keep it for when you need it.

A complete example​

plugin "Link watch"
description "Flags links from people who just arrived in chat."
author "Chattler"

setting quiet_for = 2 minutes "Only alert once per person in this time"

define looks_like_a_link(what) do
if what contains "http" or what contains "www." or what contains ".com" then
return true
end
return false
end

on message do
if not event.is_first then
stop
end
if looks_like_a_link(event.text) and cooldown(event.user, quiet_for) then
alert("First message from " + event.user + " has a link: " + event.text, "warn")
chime()
end
end

More in Examples.