- 1 Installing and running your own 'exec' bot
- 2 Quick start
- 3 Commands requiring NickServ account authorization
- 4 Administration commands
- 5 Operator commands
- 6 Bot development
- 7 Buckets
- 8 exec.txt
- 9 Script development
- 10 Usage in IRC
- 11 IRCiv
- 12 IRC voting system
- 13 Meeting assistant
- 14 execfs
- 15 Soylent IRCd
- 16 Remote listener
- 17 Distributed web service
Installing and running your own 'exec' bot
Register a nick with NickServ on the IRC server. In these instructions, %nick% is a placeholder for your bot's actual nick. Other placeholders should hopefully be self-explanatory. If you have any issues, hop onto irc.sylnt.us and ping 'crutchy'.
$ mkdir %nick% $ cd %nick% $ mkdir data $ mkdir log $ mkdir pwd $ cd pwd $ echo "%bot_nickserv_password%" > %nick% $ cd .. $ git clone https://github.com/crutchy-/exec-irc-bot.git $ cd exec-irc-bot
You can edit default settings in irc.php, or create a settings file containing similar to the following:
NICK=%nick% USER_NAME=%nick% FULL_NAME=%nick%.bot PASSWORD_FILE=../pwd/%nick% BUCKETS_FILE=../data/buckets IGNORE_FILE=../data/ignore EXEC_FILE=exec.txt INIT_CHAN_LIST=# EXEC_LOG_PATH=../log IRC_LOG_URL= IRC_HOST_CONNECT=irc.sylnt.us IRC_HOST=irc.sylnt.us IRC_PORT=6667 MEMORY_LIMIT=128M OPERATOR_ACCOUNT=%your_personal_nickserv_account_name% DEBUG_CHAN=#debug NICKSERV_IDENTIFY_PROMPT=You have 60 seconds to identify to your nickname before it is changed. ADMIN_ACCOUNTS=
You can store this file anywhere, but its recommended that it be stored in the same directory as irc.php. In this example the config filename is 'sylnt'.
Once you have your settings sorted out, run:
php irc.php sylnt
These commands can be triggered by anyone in a channel with the bot.
- /invite exec (must be channel op)
- ~join #channel (don't have to be channel op)
- ~part (bot leaves channel)
- ~list (lists available commands)
- ~list-auth (lists available commands requiring NickServ account authorization)
- ~isup host[:port] (checks connection, returns http status if found)
- ~translate tolang text (auto-detects source lang, eg: ~translate en prueba)
- ~translate-sl fromlang tolang text (eg: ~translate-sl es en prueba)
- ~queue (returns number of SN submissions in the queue)
- ~lock alias (treats all lines entered as being prefixed with alias, channel-specific)
- ~title on|off|<url>
A whois command is issued to verify the account name of a user identified with NickServ for authentication purposes.
Commands that anyone identified with NickServ can use
- ~suggest <text>
- ~suggest-api <text>
- ~suggest-exec <text>
Commands limited to specific NickServ accounts
- ~wiki login
- ~wiki title[|section] (gets [section] content)
- ~wiki edit title|section|text
- ~wiki edit title|section| (deletes section)
- ~wiki logout
- ~say text (say as exec with no amendments)
- ~bucket <index>
- ~bucket <index> <data>
- ~bucket <index> unset
These internal bot commands are restricted to accounts in a hardcoded admin account list.
- ~q (bot quits, all child processes including SedBot2 are terminated)
- ~restart (bot process restarts, all child processes including SedBot2 are terminated)
- ~rehash (reloads exec configuration file)
- ~ps (list process id and command for all currently running child processes)
- ~kill <pid> (kills child process)
- ~buckets-dump (var_dumps bucket data to terminal)
- ~buckets-save (saves bucket data to file)
- ~buckets-load (loads bucket data from file)
- ~buckets-flush (clears all bucket data)
- ~buckets-list (lists bucket indexes in terminal)
The operator's NickServ account is hardcoded. Operator-only aliases are designated with @ in the exec line account list.
- ~x (live scripting)
Bot source files:
Download above files, open a terminal and change to that directory, and run "php irc.php" to start the bot.
There are also a few constants at the top of irc.php that you'll need to change before starting:
Scripts may be stored anywhere that is accessible to the bot script for CLI execution. If stored in a different location, the script path must be included in the exec file line.
Input to a script/program is via command line arguments only. Communication with a program through stdin is supported, but only using a similar syntax to IRC messages and currently stdin is used only to respond to bucket get messages (php scripts can use the lib.php get_bucket function).
stdout of an executed script/program may be passed to an IRC channel or output to exec's stdout (terminal), depending on the value of auto-privmsg in the exec line. If auto-privmsg=0, stdout from the script/program must begin with IRC_MSG or IRC_RAW for it to be sent to IRC. If auto-privmsg=1, all stdout from the script/program is assumed to be prefixed with IRC_MSG and is sent to IRC; this is generally required for programs that can't be easily edited, such as shell binaries (cowsay, fortune, etc).
Programs executed may be anything accessible from the CLI of the machine running the exec script. They may be shell programs (such as cowsay and fortune), php scripts (executed using the CLI php command) or scripts in any other language executable by their respective CLI interpreters (python, perl, haskell, etc).
"Buckets" are a feature of exec that allow scripts to store data in a common location which is accessible from any script and is retained/persistent between script executions. Each bucket consists of an array element in the main bot program that is read, written and cleared using IRC-like commands (see below) passed through stdout/stdin pipes from/to executed scripts - buckets are filled by pipes hahaha :-P
Complex data in array form may be stored using php's serialize/unserialize (or equivalent in other languages).
Buckets are referenced by an index string. Index strings cannot contain spaces.
:exec BUCKET_GET :index :exec BUCKET_SET :index data :exec BUCKET_UNSET :index
For PHP scripts, there are basic get_bucket, set_bucket and unset_bucket functions available, along with get_array_bucket, append_array_bucket, set_array_bucket, and bucket_list functions, which can be found here: https://github.com/crutchy-/exec-irc-bot/blob/master/scripts/lib_buckets.php
The exec.txt file resides in the same directory as the bot script (irc.php) file and links aliases (triggers typed in IRC) to scripts to be executed, and contains usage parameters and restrictions.
alias is the trigger typed in IRC at the start of a message that will trigger a script to be executed.
- All aliases should start with a common trigger character (such as ~) but can be any lowercase string without spaces.
- Aliases must be unique, but multiple scripts may be executed per alias by separating shell commands with &&.
- The aliases *, <init>, <startup>, <quit> and <log> are reserved and have special meanings to the bot.
- The * reserved alias occurs on every IRC message received. The exec bot in Soylent IRC uses a single script for this alias. cmd.php is executed on every line and contains a switch statement to dispatch internal trigger messages on various IRC events (such as numerics, PRIVMSG, NOTICE, JOIN, PART, NICK, etc). The bot then parses these internal messages to further trigger other scripts.
- The <<init>> reserved alias is triggered on bot startup before the IRC connection is made. It is useful for initializing data buckets for particular scripts. Buckets and internal trigger messages may be called at this point, but IRC functionality is not yet available.
- The <<startup>> reserved alias is triggered immediately after the bot sends an identify message to NickServ, but is not yet identified. It is useful for running scripts that require an IRC connection.
- The <<quit>> reserved alias is triggered on bot shutdown and restart. IRC functionality is still available to this alias script. It is useful for saving data buckets to file so that data can persist when the bot is restarted.
- The <<log>> reserved alias is triggered on every IRC message received (similar to *) but is executed immediately after the message is received (before other script triggers are processed) so is more stable for logging purposes due to a lower probability of messages being out of order.
A non-zero timeout is the number of seconds a script is allowed to run for before being terminated by the bot.
- If a script times out a message is sent to the destination from which the alias was triggered to inform the user.
- It is always a good idea to set a timeout to prevent infinite loops in scripts from chewing up bot host resources.
- A timeout of 5 seconds is typical except for http-enabled scripts which sometimes require more time to complete.
A non-zero repeat is the number of seconds between each automated alias trigger.
- Aliases with repeats may still be triggered manually.
- The first trigger will occur after the repeat has elapsed on startup (repeat triggers don't trigger immediately on startup).
auto-privmsg may be 0 or 1.
- A value of 1 will automatically privmsg every line of text output to a script's stdout or stderr so must be used with caution.
- This is useful for running programs that aren't scripted, such as compiled binaries that can't be changed (apt-get, fortune, etc).
- A value of 0 won't privmsg stdout/stderr and is required if a script needs to triggger other commands, send customized messages to IRC or use buckets.
empty-trailing-allowed may be 0 or 1.
- A value of 1 will allow an alias to trigger if there is no text following the alias.
- A value of 0 will require more text after the alias.
- If an alias requires more text and a user enters only the alias itself with no other text, a privmsg is sent to inform the user.
- If there is a chance that an alias may be entered without further text without intending to trigger the bot, this should be set to 0 and if need be handled silently within the triggered script.
account-list is a comma-delimited list of NickServ account names permitted to trigger the alias.
- If a user attempts to trigger an account-restricted alias and their account isn't listed or they aren't identified with NickServ, a message is output to the terminal but not to IRC.
- An empty list is unrestricted.
- A value of "*" will allow any NickServ-registered user to trigger alias.
cmd-list is a comma-delimited list of commands that the alias may be triggered on, including IRC commands (PRIVMSG, NOTICE, NICK, etc) but also internal and bucket commands intercepted by the bot (INTERNAL, BUCKET_GET, etc).
- Attempts to trigger a cmd-restricted alias on an unspecified cmd fail silently.
- An empty list is unrestricted.
dest-list is a comma-delimited list of destinations that the alias may be triggered from, including channel names and nicks.
- Attempts to trigger a dest-restricted alias from an unspecified destination fail silently.
- An empty list is unrestricted.
reserved is an unused parameter reserved for future use, and may be 0 or 1.
shell-cmd is the cli command executed in a separate process by the bot when the assocated alias is triggered and all requirements are met.
- %%trailing%% excludes alias
- aliases here must be all lower case letters
- cmd list and dest list is not case sensitive, but conventionally use uppercase for cmd
- account, cmd and dest lists are all comma-separated
- set cmd list to PRIVMSG to enable alias to only be called by PRIVMSG cmd (NOTICE etc won't trigger)
- set dest list to #soylent to restrict triggering of alias to the #soylent channel (can also use a nick to restrict to PM)
Available exec templates
- %%trailing%% = the message string visible in an IRC client
- %%dest%% = the channel/pm nick where the message originated
- %%nick%% = the nickname of the sender
- %%start%% = microtime(True) result when bot was started
- %%alias%% = the command alias that triggered the script
- %%cmd%% = the IRC command (PRIVMSG,NOTICE,QUIT,PART,NICK,JOIN,numeric,etc)
- %%data%% = the entire IRC line (refer below)
- %%exec%% = the exec line for the trigger alias
- %%params%% = the params part of the IRC line (refer below; usually same as %%dest%% except when %%cmd%% is a numeric)
IRC line syntax:
:<prefix> <command> <params> :<trailing>
PHP script template
If anyone is interested in adding their own script, talk to crutchy (usually hangs out in #soylent and #test) who will be happy to help as best he can.
IRC commands maybe manually constructed by echoing a string to stdout using the ":<prefix> <command> <params> :<trailing>" syntax, but there is also a selection of shortcuts available to make scripting easier. The following commands may be called using a "/command <trailing>" syntax.
Usage in IRC
To invoke a script in IRC client:
<crutchy> ~define atlantic ocean <exec> 1 | noun | the 2nd largest ocean; separates North and South America on the west from Europe and Africa on the east\n2 | adjective | relating to or bordering the Atlantic Ocean
In the above example, "~define" is the alias, "atlantic ocean" is passed to the script as %%trailing%% and can be accessed in PHP scripts using the $argv global array variable.
IRC voting system
- simple to use
- simple to access
- simple to get help
- secure as practicable
- difficult to vote more than once
- secret ballot
- user can get help on voting using ~vote, ~vote help or ~vote ?
- user must be identified with NickServ to use voting system
- user can get list of available polls using ~vote list|l
- user can register a new poll using ~vote <poll_id> register [<description>] - description is optional and may contain spaces
- <poll_id> can only contain alphanumeric characters or _-.
- poll founder can unregister a poll using ~vote <poll_id> unregister (this will delete all data for <poll_id>)
- poll founder is automatically added to list of admins for poll
- poll founder can add a poll admin using ~vote <poll_id> add-admin <admin_nickserv_account>
- poll founder can delete a poll admin using ~vote <poll_id> del-admin <admin_nickserv_account>
- poll can be opened for voting by poll admin using ~vote <poll_id> open
- poll can be closed for voting by poll admin using ~vote <poll_id> close
- poll admin can add a poll option using ~vote <poll_id> add-option <poll_option> [<description>] - description is optional and may contain spaces
- poll admin can delete a poll option using ~vote <poll_id> del-option <poll_option>
- user votes using ~vote <poll_id> <poll_option>
- user votes secretly using /msg exec ~vote <poll_id> <poll_option>
- user may vote any number of times, but only one vote is registered per NickServ account (to prevent ballot stuffing)
- poll admin can output a breakdown of votes with ~vote <poll_id> breakdown
- anyone identified with NickServ can output the current poll result using ~vote <poll_id>
This feature is currently under development.
Proof-of-concept script for development of a tool to assist Soylent PBC Board Meeting conduct, and also possibly to assist team meetings.
Intended to automate minute-taking and posting of minutes on the wiki. Meeting minutes will be posted automatically on the wiki on meeting close, with formatted sections for:
- basic details such as start time, finish time, chair(s), etc
- attendees with any notes regarding voiced/non-voiced nicks, speakers, authorized voters, admins, and anyone that joined/left partway through the meeting, etc
- formatted IRC script
- table of motions with vote counts, carried status, oppositions, who raised and who seconded etc
- other data may be added as the feature is evolved
~meeting open ~meeting close ~meeting chair <nick> ~meeting motion <description> aye|nay
There can only be one meeting per channel. Any number of meetings (in different channels) can occcur simultaneously.
The bot stores a list of meeting data bucket indexes in the <<MEETING_LIST>> bucket.
Meeting data buckets have indexes named <<MEETING_DATA $dest>> where $dest is the channel name.
Meeting data buckets are arrays, each containing the following elements:
channel = name of channel where meeting is being conducted chairs = array containing chair data finish = meeting close timestamp messages = array of privmsg data events = array of event data (quits/joins/kicks/nicks/etc) initial nicks = list of nicks at meeting open initial nicks complete = boolean final nicks = list of nicks at meeting close final nicks complete = boolean quorum = boolean
Each chair data element contains an array with the following elements. A new chair array is added whenever the chair position is handed over.
nick = NickServ account name of chair start = timestamp that chair commenced
Currently under development.
Source code available here:
Ideas for future development:
- make an import/export command to bring in data subtrees in text line format with tab prefixes for levels
- flexible permissions system that allows/denies based on alias, nick, account, alias permissions, creator, etc
- permissions system should have easy way to jail a script from being able to access any bucket/directory except down from a certain path
- develop feature to synchronize data between instances of exec that are authorized
Currently under development. Source code available here: https://github.com/crutchy-/exec-irc-bot/blob/master/website/ircd.php
Will be very simple. Likely won't implement all ircd functionality, but may implement some non-standard Soylent-specific features.
A basic remote listener has been developed, with source code available here: https://github.com/crutchy-/exec-irc-bot/blob/master/website/listen.php
Ideas for future development:
- provide easy access to buckets from scripts running outside of exec (such as apache php scripts that serve web content)
- provide api from remote sources (on a designated port) to control the bot similarly as from irc
- provide interface by which remote scripts (such as apache web scripts) can interact with scripts run by exec
Distributed web service
This is just a pipe dream at the moment, with some ideas jotted down for future development.
- templating system based on execfs. html is built from separate hierarchical data structures containing templates and content
- templates and content are maintained from IRC, though would be nice to develop clients and web interfaces for viewing and editing
- content and templates stored in separate execfs directories
- template directory to be protected using permissions
- any client can edit content (if permitted)
- develop a script to generate html from template and content execfs directories, or use an apache php script to construct web content on the fly