irctk

libircclient binding for scripts
git clone https://a3nm.net/git/irctk/
Log | Files | Refs | README

commit 9e36c73d3e18f9791cdb5466c4ce0b86c048f1df
parent 5705cd2ec34607e92341249459ce0445891d63a4
Author: Antoine Amarilli <a3nm@a3nm.net>
Date:   Mon, 10 Sep 2012 10:31:08 +0200

improve README

Diffstat:
README | 194++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
1 file changed, 117 insertions(+), 77 deletions(-)

diff --git a/README b/README @@ -14,46 +14,34 @@ PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program (see file "COPYING"). If not, see <http://www.gnu.org/licenses/>. -== 1. Features == +== 1. Description == irctk is a general-purpose IRC toolkit. It connects to an IRC server specified on the command line, joins channels specified on the command line, posts what it -receives from stdin and outputs to stdout what it hears. This makes it possible -to write simple IRC bots and scripts very quickly, either in the shell or in -your favourite programming language. +receives from stdin to the channels and outputs to stdout what it hears on the +channels. This makes it possible to write simple IRC bots and scripts very +quickly, either in the shell or in your favourite programming language. -== 2. Related projects == +== 2. Setup == - * ii <http://tools.suckless.org/ii/> - -ii is filesystem and FIFO-based but irctk is entirely FIFO-based. ii's control -FIFO is irctk's stdin, but ii's output files are replaced by irctk's stdout. -irctk does not write to disk or read from disk. irctk also includes features -which make it easy to write bots in shell script one-liners. - - * IrcTK <https://github.com/maxcountryman/irctk> - -irctk has nothing to do with this except the similar name. - -== 3. Setup == - -irctk is written using libircclient, you will need it to compile and run the -program. Install libircclient-dev (on Ubuntu and Debian systems), or get it from -<https://sourceforge.net/projects/libircclient/> and install it manually. +irctk is written using libircclient, you will need this library to compile and +run the program. Install libircclient-dev (on Ubuntu and Debian systems), or get +it from <https://sourceforge.net/projects/libircclient/> and install it +manually. -== 4. How to use == +== 3. How to use == -=== 4.1. Connecting to a server === +=== 3.1. Connecting to a server === As a simple interactive use of irctk, here is how you connect to the IRC server at example.com and join channel #test: $ irctk example.com '#test' -Messages on the channel will get output on your terminal and you can type +Messages on the channel will get output on your terminal, and you can type messages that you want so say to the channel. Press ^D to close stdin and -terminate irctk. Note that the use of quotes is to prevent your shell from -interpreting '#' (irctk won't see them). +terminate irctk. Note that the use of quotes around "#test" is to prevent your +shell from interpreting '#' (irctk won't see them). More elaborate options are supported. Here is how to connect to a password-protected channel on a password-protected server on a non-standard @@ -61,7 +49,7 @@ port, specifying a custom nickname, username and real name. $ irctk -U jh -R "James Hacker" nick:srvpass@example.com:3724 '#test:chanpass' -=== 4.2. Using irctk's stdin === +=== 3.2. Using irctk's stdin === irctk is meant to be used non-interactively. For instance, you can say the contents of a file on a channel by giving it as standard input: @@ -88,7 +76,7 @@ channel as they appear in the feed: grep --line-buffered '^ Today' | irctk fmlbot@example.com '#fml' -=== 4.3. Using irctk's stdout === +=== 3.3. Using irctk's stdout === You can log what is happening on a channel by setting stdout to be a file: @@ -113,8 +101,8 @@ speak): aplay alert.wav; done -irctk has specific features to detect when it is addressed. Say you want to log -tasks to do by addressing a bot on IRC: +irctk has specific features to detect when someone addresses it. Say you want to +log tasks to do by addressing a bot on IRC: $ irctk -f todobot@example.com '#chan' >>~/todo @@ -135,7 +123,7 @@ reverse): $ irctk listener@source.com '#chan1' | irctk repeater@destination.com '#chan2' -=== 4.4. Writing interactive bots === +=== 3.4. Writing interactive bots === We will now look at interactive examples where you interface irctk's stdout to some script or program which will do something intelligent and give something to @@ -156,15 +144,15 @@ to avoid buffering. The named FIFO is used to connect irctk's stdout to awk's stdin and awk's stdout to irctk's stdin. Note that the cat invocation is required and "<fifo" will not work. -Note that you can use your favorite programming language instead of awk. If you +Of course, you can use your favorite programming language instead of awk. If you want to write an IRC bot in an esoteric language with no IRC library (or maybe even no networking support), all you need to do is write some code which reads -incoming lines on stdin, posts outgoing lines on stdout, and *does not do -buffering*. You can then lift it to IRC very simply: +incoming lines on stdin, posts outgoing lines on stdout, and *does not buffer*. +You can then lift your program to IRC very simply: $ cat fifo | irctk example.com '#chat' | program > fifo -=== 4.5. Input and output format === +=== 3.5. Input and output format === The output format of irctk is of the following form (unless you use -F): @@ -208,7 +196,7 @@ irssi. To inhibit this (can be useful if irctk's stdin is attacker-controlled), use --no-command-to-event. To escape, use '/say' or '/ '. The supported commands are: - /nick NICKNAME (changes nick) + /nick NICKNAME (change nick) /mode MODE (set channel mode) /part [CHAN] (part from a channel) /join [CHAN] (join a channel) @@ -220,7 +208,8 @@ are: /say MSG (escape) / MSG (escape) -Optional channel names "[CHAN]" default to the current inferred destination. +Optional channel names "[CHAN]" in the above list default to the current +inferred destination (i.e., the last active channel by default). As an additional convenience, irctk can be made to address the last person who addressed him with the -r option. In conjunction with the default destination @@ -228,7 +217,32 @@ channel inference, this means that, using -fr, whenever you ask irctk to say "message", it will say it to the last person who addressed him, on the channel where it was addressed. This is very convenient to write bots. -=== 4.6. Complete examples === +=== 3.6. Complete examples === + +This bot queries user names using finger and returns a status line for them (or +an error if they do not exist): + +cat fifo | irctk -Fr fingerbot@example.com '#chat' | + while read; do + finger -s -- "$REPLY" 2>&1 | tail -1 + done >fifo + +The following bot can be used to roll dice: say something like "dmbot: 3d42" and +it will reply with the result. Note that this example is bash-specific. Thanks +to p4bl0 <http://pablo.rauzy.name/> for writing it. + +cat fifo | irctk -Fr dmbot@example.com '#chat' | + while read line; do + if grep -E '^[0-9]{1,2}d[0-9]{1,3}$' <<<"$line" &>/dev/null; then + D=(${line/d/ }) + for ((i = 0; i < ${D[0]}; i++)); do + echo -n $((RANDOM % ${D[1]} + 1))" " + done + echo + else + echo "format error: must be NdM with N<100 and M<1000" + fi + done >fifo This bot queries on wikipedia whatever is said to him, using the DNS-based wikipedia query system as an ugly way to get the beginning of pages. @@ -237,17 +251,17 @@ wikipedia query system as an ugly way to get the beginning of pages. while read line; do Q=$(echo "$line" | tr ' ' '_' | tr -dc 'a-zA-Z_()'); dig +short txt $Q.wp.dg.cx; echo; - done | tee fifo + done >fifo This is a way to play adventure on IRC. (Beware, people can overwrite files when saving their game, so run as a suitably unpriviledged user.) The "while true" loop is to restart the game whenever it exits. The socat invocation is used to -disable buffering. +disable buffering. To play, say "DM: command". $ cat fifo | irctk -F DM@example.com '#adventure' | while true; do socat EXEC:adventure,pty,ctty,echo=0 STDIO; - done | tee fifo + done >fifo Two-way gateway: gateway posts on #chan1 on server1.com whatever is said to him on #chan2 on server2.com, and vice-versa: @@ -255,9 +269,10 @@ is said to him on #chan2 on server2.com, and vice-versa: $ cat fifo | irctk -F0 gateway@server1.com '#chan1' | irctk -F0 gateway@server2.com '#chan2' | tee fifo -Run shell commands from your IRC client. BEWARE, this means that whoever is -named "admin" on the IRC server can run arbitrary commands on your machine, so -you really shouldn't do this. +Run shell commands from your IRC client (just by saying them in #tty, no need to +address the bot). BEWARE, this means that whoever is named "admin" on the IRC +server can run arbitrary commands on your machine, so you really shouldn't do +this. $ cat fifo | irctk localhost '#tty' | grep --line-buffered '^\[#tty\] <admin>' | @@ -265,38 +280,26 @@ you really shouldn't do this. Whatever admin says on #tty will get run in a bash shell and the result will be returned to the channel. Note that you can of course run irctk in this shell -(irception!). - -=== 4.7. Pipelining === +(irception!), but beware of feedback loops if you attempt to join the same +channel! -irctk tries to apply its rate limitation (-i) independently on each channel. -This means that, to ensure the fastest possible delivery, messages to channels -with an empty queue will be sent *before* messages to channels with a busy -queue. no matter the order on which they were provided on standard input. -However, within a given channel, the order relation on messages matches their -order on standard input. - -If you specify multiple destination channels like "[#a,#b,#c]", however, the -resulting message will be said on all channels simultaneously (and will -therefore wait for the buffers of all relevant channels to be empty). If you do -not want this synchronization, you should say the message several times, -addressed to each individual channel. - -=== 4.8. Implied destinations === +=== 3.7. Implied destinations === You can always specify the channel to which you speak by using a "[#channel]" -prefix. You can specify multiple channels for the same message (but see the -previous section for what this implies for timing). You can specify "[]" to -escape "[" if your message starts with it. If you do not specify a channel, then -irctk will choose one itself. Several possible ways to choose are available, -only one of them can be provided on the command line. Here are those options, -sorted by ascending complexity. A discussion of other useful options follows. +prefix. You can specify multiple channels for the same message using commas (but +see "Pipelining"). If you do not specify a channel, then irctk will choose one +itself. Note that you can start your message with "[]" if your message starts +with a '[' but you want irctk to infer the channel. + +Several possible ways to choose are available, only one of them can be provided +on the command line. Here are those options, sorted by ascending complexity. A +discussion of other useful options follows. * --default-always-first Messages with no destination will be sent to the first channel specified on the -command line invocation of irctk, or to irctk's private channel if none were -specified (this isn't very useful). +command line invocation of irctk (or to irctk's private channel if none were +specified, which is not very useful). * --default-all @@ -307,17 +310,21 @@ that might have been joined by irctk later.) * --default-last-posted Messages with no destination will be sent to the last channel to which a message -was sent. This is useful if you are lazy and want to specify the channel only -when you change it. +was sent. This is useful if you are writing to stdin manually and want to +specify the channel only when it changes. Note that you can use -P to display +the current default destination on stderr; if you send irctk's stdout elsewhere +to avoid clobbering your terminal, this makes irctk (almost) look like irssi's +prompt. (For instance, you can send stdout to a FIFO and display it in another +window (or use GNU screen) to get a poor man's IRC client.) * --default-last-active (default) Messages with no destination will be sent to the last active channel, that is, the last channel on which something took place. This is reasonable if you want to react instantaneously to something which just happened. Note that because -irctk reads stdin as greedily as possible, the last active channel is the last -active at the moment when you *write* your message to irctk's stdin, not at the -moment when irctk will *say* it (the two differ if irctk has a long pipe of +irctk reads stdin as greedily as possible, the last active channel should be the +last active at the moment when you *write* your message to irctk's stdin, not at +the moment when irctk will *say* it (the two differ if irctk has a long pipe of things to say). irctk's behavior is usually what you expect here. The --default-last-active option is perfect if you want to reply to messages by @@ -326,7 +333,7 @@ requests may arrive during that time, irctk will not be able to route the answers on its own: consider writing your own logic to route messages according to your needs (and always specify the destination explicitly). -=== 4.9. Tracking === +=== 3.8. Tracking === Because of the delay between messages which irctk observes to avoid getting kicked by a pissed server, messages can be sent to the server a long time after @@ -344,7 +351,27 @@ them on stdin. This is useful if you want to write a bot which stores e.g. a score for each user and if you want users to keep their score even if they change nick. These tracking modes are not enabled by default. -== 7. Test suite == +=== 3.9. Pipelining === + +irctk has a built-in rate limitation (configurable with -i) which it tries to +apply independently on each channel. This means that, to ensure the fastest +possible delivery, messages to channels with an empty queue will be sent +*before* messages to channels with a busy queue. no matter the order on which +they were provided on standard input. However, within a given channel, the order +relation on messages will match their order on standard input. + +If you specify multiple destination channels like "[#a,#b,#c]", however, the +resulting message will be said on all the channels simultaneously (and will +therefore wait for the buffers of all relevant channels to be empty). If you do +not want this synchronization, you should say the message several times, +addressed to each individual channel. + +Beware of the fact that the IRC server may limit irctk's rate in a fashion which +irctk will not be able to control, so any slowdowns you see may not be irctk's +fault. Use -o to know when irctk is sending messages, to see who is slowing +things down. + +== 4. Test suite == You can run the test suite with ./tests_sequential.sh. This requires a working IRC server on localhost:6667. @@ -352,7 +379,7 @@ IRC server on localhost:6667. If you have GNU parallel and if your IRC server isn't afraid of many connections from a single IP, you can run the tests in parallel: ./tests_parallel.sh. -== 8. Caveats == +== 5. Caveats == irctk has not been thoroughly audited for bugs or security vulnerabilities. Be cautious if you intend to connect it to an IRC server with untrusted users. @@ -376,3 +403,16 @@ irctk can have trouble with buffering. When writing pipelines involving irctk, be sure to disable all buffering (sed -u, awk's fflush, python -u, stdbuf in some cases, etc.). +== 6. Related projects == + + * ii <http://tools.suckless.org/ii/> + +ii is filesystem and FIFO-based but irctk is entirely FIFO-based. ii's control +FIFO is irctk's stdin, but ii's output files are replaced by irctk's stdout. +irctk does not write to disk or read from disk. irctk also includes features +which make it easy to write bots in shell script one-liners. + + * IrcTK <https://github.com/maxcountryman/irctk> + +irctk has nothing to do with this except the similar name. +