# input
equal to IRC.command.input
# print(string{, options})
prints text using the colour parser from IRC.colors. options are;
log
- boolean settingfalse
will omit bot messages from the logtarget
- string channel / user to send to (only works if the command is included in thebroadcastCommands
config array)
# log(object{, options})
alias for print.log
# notice(string{, options})
same as print but for notices
# action(string{, options})
same as print but for actions
each of the above functions has additional properties;
# printer.log(object{, options})
renders and prints an object using IRC.inspect
options can be those of print and IRC.inspect
# printer.raw(string{, options})
prints text without parsing the colour DSL
# printer.error(error{, options})
prints errors with IRC.colors.error. also used to print thrown errors
# printer.info(string{, options})
prints text with IRC.colors.info
# printer.success(string{, options})
prints text with IRC.colors.success
# fetchSync(url{, options}) -> data
works the same as fetch but is synchronous. options are the same as fetch with the addition;
type
- string can betext
,json
ordom
form
- object send multipart/form-datafetchSync('https://example.com', { form: { key: 'value' } })
fetchSync blocks, but each command is run concurrently in a separate vm - so other features continue to be responsive
# fetchSync.json(url{, options}) -> object
same as fetchSync, except parses the response as JSON and returns an object
# fetchSync.dom(url{, options}) -> DOM
same as fetchSync, except parses the response as HTML and returns a window object
useful for scraping websites or RSS feeds
const { window, document } = fetchSync.dom('http://google.com');
# jsdom() -> { JSDOM, ... }
helper to set up the environment to run JSDOM and return the library
data is scoped by server and command. data will be stored in the server database
# store.set(key, value)
a simple key-value store. the value can be either string, or undefined|null to remove the value
# store.get(key) -> string|undefined
retrieve the stored value
# store.save(key, value)
a convenience function that JSON stringifies the value sent to the store
# store.load(key{, default value}) -> value
a convenience function that JSON parses the value retrieved from the store
# store.all() -> array
returns an array of objects have have the properties key and value corresponding to the data in the store
# store.clear()
removes all values from the store
# store.namespace
equal to IRC.command.root
different commands store data in different namespaces, only commands with the same root
share the same namespace
read more about command.root
in IRC.command
the SQLite store is scoped by command namespace only, so data is shared between servers
each command will have a seperate database file. various restrictions on execution time, filesize, and available features of the language have been made for safety reasons
statements have a prepare cache, so repeating the same query is as cheap as if you had prepared it
# SQL.run(query[, ...params]) -> array
run an SQLite statement
# SQL.one(query[, ...params]) -> result
retrieve a single result from a query
# SQL.many(query[, ...params]) -> info
retrieve all results of a query
# SQL.exec(query)
run multiple statements. worse performing, no caching
an example use of the API could be like this; SQL.one('SELECT ?', 1)
however, the SQLite API also allows you to use tagged template strings for safe and easy statement escaping;
SQL.run`INSERT INTO foo (bar) VALUES (${userInput})`
# require(packagename) -> object
download a package from npm and bundle it with esbuild. npm scripts are ignored for safety. subsequent accesses of the same package are cached
packagename can include the version and a path, like - require('react-dom/[email protected]').renderToString( ... )
the event system runs in a dedicated long running vm. each server connection has their own vm
by convention, events are stored in commands with the prefix event.
, but any command can be an event by setting the option in a command editor
only admins have access to changing events
the remote debugger is useful for event development
# IRC.listen(eventname, callback {, options})
run a callback each time an event happens
available events are
the tick
event happens every second
the message
event happens for each message
the webhook.name
events happen when a request is sent to a webhook
the callback will receive some eventData
object that always contains a target
property with the channel or username
available options are
showErrors
- boolean should errors in this event be printedfilter
- function provide a callback to dictate if an event should run or not
some additional APIs are only available in events;
# IRC.queryConfig(key{, default value}) -> value
query user-defined config values
will first check the channel config, then server, and then top level
# fetch(url{, options}) -> Promise
API to match browser fetch
async APIs are favoured in events as blocking would cause the event system to pause
# SQL.async.run(query[, ...params]) -> Promise
# SQL.async.one(query[, ...params]) -> Promise
# SQL.async.many(query[, ...params]) -> Promise
# SQL.async.exec(query) -> Promise
async versions of the SQLite API
# IRC.setNamespace(namespace)
change the namespace the key-value and SQLite stores use. this gives the events full access to all command data
multiple webhooks can be created on the fly to allow pushing data to the bot
the following route structure is used; https://host/api/webhook/somename
webhooks support any http method, and provide body data and query params as part of the eventData
object
for example, the following event;
IRC.listen('webhook.print', (event) => {
if (IRC.queryConfig('hasPrintWebhook')) {
print(event.query.message);
}
})
will cause the request http://host/api/webhook/print?message=foo
to print 'foo' to the channel
auth is left as an exercise for the user. it can be as complex or simple as you like
here's a simple tripcode example;
const tripcode = require('tripcode');
IRC.listen('webhook.test', event => {
const authed = tripcode(event.body.passcode) === IRC.queryConfig('testCode');
print(authed ? 'pass' : 'fail');
});
which can be used with;
curl -X POST --data-binary '{"passcode":"demo"}' -H "Content-Type: application/json" http://localhost:8888/api/webhook/test
the IRC object includes data and helper functions for IRC-related things, but also contains some general things that didnt quite make it into the big league global scope
# IRC.trigger
a config-defined string denoting the prefix to run commands with
can be revealed by running .bots
with no prefix if IBIP is enabled
# IRC.message
an object with information about the current message that triggered the command. has the folowing properties:
from
- string nickname of the message senderto
- string where the message was senttext
- string full text of the messagemessage
- object raw information about the messagetarget
- string where the response message is aimedisPM
- boolean if the original message was in PM
# IRC.nick
the current nickname of the bot
# IRC.server
the address the server has connected to
# IRC.channel
the current channel. undefined if message is a PM
# IRC.setNick(string)
change the bot's nick. only works if the user is an admin or the channel has the setNick
config option enabled
used in the nick
command
# IRC.command
a parsed representation of the current command. uses IRC.parseCommand
path
- string the actual command requested ( ~full.path )list
- array the path, split by the.
characterparams
- array list of strings from the command ( ~full.path(param, ...) )root
- string the command namespace ( ~full.path )input
- string the text after the command ( ~command some text )
# IRC.parseCommand(object) -> object
used internally to parse commands. object has the following properties;
trigger
- string|undefined the command prefix to use, if at alltext
- string the full message
# IRC.webAddress
config-defined URL pointing to the web frontend
# IRC.epoch
date object indicating when the node process was started
# IRC.version
bot version
# IRC.nodeVersion
node.js version
# IRC.secret
a config-defined value for a specific command root. useful for API keys
# IRC.wordList
an array of words from /usr/share/dict/words
# IRC.resetBuffer()
cancel all pending messages (to suppress spam). used in the reset
command
# IRC.whois(nick) -> object
provides whois information for a user. properties are: nick, user, host, realname, channels, server, serverinfo, account, accountinfo
# IRC.ping(host) -> promise
runs the CLI ping command at the specified host and provides the output
# IRC.inspect(value{, options}) -> string
object inspector designed for IRC specifically. takes the following options;
depth
- number what level of of the tree should be renderedtruncate
- number at which point to truncate the outputcolors
- bool should output be formatted with colours
values of zero will show the maximum instead
# IRC.colors(string) -> string
DSL parsing function. colours can be disabled entirely in the config
colours
{r}red
{dr}dark red
{w}white
{bl}black
{c}cyan
{dc}dark cyan
{b}blue
{db}dark blue
{g}green
{dg}dark green
{p}magenta
{dp}dark magenta
{o}orange
{y}yellow
{gr}grey
{dgr}dark grey
formatting
{bo}bold
{u}underline
{i}italic
misc
{rb}rainbow
{g,r}background
{rand}random colour
{bell}ascii beep
{/}cancel effects
for example
{r}red{/} and {bo}bold{/} and {rb}rainbow{/} and {r,g}red with green background
# IRC.colors.hash(string) -> string
produces a colour hashed from the input string
# IRC.colors.nick(string[, boolean]) -> string
uses hashing to render a nickname. additionally pass false to not render the angle brackets
# IRC.colors.link(string) -> string
a simple function to render a hyperlink
# IRC.colors.cmd(name[, args, params]) -> string
renders a command with usage information. args and params can be a string or an array of strings
# IRC.colors.error(error|string) -> string
renders an error's name (if different to 'Error') and message
# IRC.colors.info(string) -> string
renders a neutral message
# IRC.colors.success(string) -> string
renders a successful message
# IRC.colors.strip(string) -> string
removes (rendered) colour codes and formatting from a string
# IRC.parseTime(string) -> date
used in the memo
and remind
commands
parses a string into a date object. it accepts various formats
absolute times
YYYY-MM-DD
HH:MM
HH:MM:SS
3am
3pm
sunday
feb
3rd
march
2019
tomorrow
relative times
3 weeks
1y
4 mins
10 hours
7d
each format can be combined to create a time offset
see here for a full list of strings that are accepted
used in the log
command and subcommands, but also used to create sed like functionality for messages
# IRC.log.get(text[, limit[, offset]]) -> array
retrieve messages from the channel
# IRC.log.count(text) -> number
return the number of lines that match the provided string
# IRC.log.user(nick, text[, limit[, offset]]) -> array
retrieves messages from a specific user
# IRC.log.random([quantity]) -> array
pull random messages from the log
# IRC.log.regex(string[, limit[, offset]]) -> array
takes a regex as a string to search the database with
# IRC.paste(content, name)
host some content as HTML or text. HTML is sandboxed
used in the command
command and subcommands. commands can also be manipulated via the web frontend
# IRC.commandFns.get(name) -> object|undefined
returns information on a command. properties are;
name
- string name of the commandcommand
- string code snippet that is run when the command is triggeredlocked
- boolean if the command is locked from editingstarred
- boolean if the command is a star ★
commands that share the same root also share the same locked / starred state
# IRC.commandFns.list() -> array
returns an array of all command information
# IRC.commandFns.names() -> array
returns an array of all the command names
# IRC.commandFns.count() -> number
returns the number of commands
# IRC.commandFns.setSafe(name, code) -> boolean
sets the code for a particular command. returns true if successful
# IRC.commandFns.deleteSafe(name, code) -> boolean
deletes the command. returns true if successful
# sleep(milliseconds)
blocks the current thread for the specified time. other commands will continue to run
async timers may be added in future
# IRC.auth()
if the user is not authenticated with nickserv, throws an error. otherwise does nothing
# IRC.sudo() -> object
checks the user is authenticated to nickserv, and checks if the user is in the admins
config option for that server, otherwise throw an error
the returned object has the following properties
exit
- function kills the main processnode
- proxy a bridge out of the vm to the channel's internal node object in the main process
the node
proxy allows you to send raw commands and update config options on the fly. examples of its use can be seen in the following commands; reload
, reboot
, update
, join
, part
, mode
, topic
, kick
, nick
, redirect
, ignore
, debug
update
can be used to update the bot without rebooting
# IRC.require(name) -> object
loads a command as a module. the object is whatever was added to module.exports
some useful utilities are available as subcommands of the module
command. for example:
IRC.require('module.paste')('hello world') == 'https://paste.rs/PN2'
# module.exports
an object to place functions you would like to export on
# module.required
a boolean indicating if the current command has been required or not. allows commands to be used as commands or modules
all properties are optional. see the example config
if the configuration file is edited while the bot is running, these changes will be reflected in its behaviour, to the extent that if you change the server address it will leave the old one and rejoin the new one
servers
array list of IRC servers to connect toaddress
string for example:irc.libera.chat
password
string password to use for services authenticationchannels
array list of channels to join.name
string channel name to join. for example:##rust
the following properties are top level, but can also placed inside the server for a local override
trigger
string the prefix to use for running commands (default:~
)nickname
string nicknameuserName
string username shown in whois informationrealName
string real name shown in whois informationquitMessage
string message to provide when the bot leaves a serverfloodProtection
boolean should flood protection be enabled (default:true
)floodProtectionDelay
number set flood protection time delay in ms (default:250
)autoRejoin
boolean should the bot autorejoin channels when kicked (default:true
)ignoreHosts
array list of hostnames to ignore for events and messages entirelyadmins
array list of nicknames of users that have access to IRC.sudosecrets
object keys in this object correspond to commands that have an IRC.secret valuebroadcastCommands
array list of commands that are able to use the target property of print
the following properties are top level, but can also placed inside the server or channel for a local override
lineLimit
number maximum number of lines a command can display (default:10
)charLimit
number maximum number of characters a command can display (default:false
)colLimit
number maximum number of characters per line a command can display (default:400
)colors
boolean should colours and formatting be enabled (default:true
)setNick
boolean does anyone in this channel have access to IRC.setNick (default:false
)enableEvents
boolean should channel run events system (default:true
)enableCommands
boolean should commands be triggerable (default:true
)
the following properties are top level only
timezone
string timezone to use for dates (default:Europe/London
)web
object configuration for the web frontendurl
string web address for the frontend, available at IRC.webAddressport
number port to host the content atpassword
string logging in to the web interface allows you to modify locked commands
these used to be part of the core, but are now user-defined configuration values
enableIBIP
boolean should the bot conform to IBIP standard (default:true
)fetchURL
boolean should URLs posted in channel have their titles displayed (default:true
)fetchURLAll
boolean should every scraped URL be shown, or just 'useful' ones (default:false
)
to run code in a JS interpreter, combine the trigger prefix with one of the following symbols
>
prints the returned value and >>
, #
or %
run code in an async IIFE
the REPL works as a command like any other, and >
takes optional params. the params look like:
>(depth, truncate)
which correspond to the options from IRC.inspect
console output is available in real-time via a HTTP stream. this is useful for live monitoring and development
combine with IRC.sudo().node.debug.set(true)
and IRC.sudo().node.parent.dev.set(true)
to show deeper levels of debug information
to connect using curl: curl -u io:webpassword https://host/api/iostream