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:
| Default | Box |
|---|---|
3 | a number |
15 minutes | a number, labelled in minutes |
30 seconds | a number, labelled in seconds |
true / false | a 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")
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:
- Save the file.
- Settings → Reload.
- Make the thing happen, or wait for it.
- 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.