From c3bf9bb173fba5ab5cbdf0dd5524c2729aae9bdf Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Tue, 14 Dec 2010 17:13:52 -0700 Subject: [PATCH] Make lots more happen in a script Not only does message processing happen in a script, but you must launch an external program to connect out. This allows you to use netcat, socat, gnutls, or whatever other crazy thing you come up with. --- bot.ml | 128 ++++++++++++++++++++++++++++++++++++------- process.ml | 28 ++++++---- rollforinitiative.py | 29 ++++++++++ 3 files changed, 155 insertions(+), 30 deletions(-) create mode 100755 rollforinitiative.py diff --git a/bot.ml b/bot.ml index b72ccb2..f0422e7 100644 --- a/bot.ml +++ b/bot.ml @@ -1,7 +1,3 @@ -type bot = { - store: Infobot.t; -} - let debug = prerr_endline let file_descr_of_int (i:int) = @@ -10,7 +6,6 @@ let file_descr_of_int (i:int) = let write iobuf command args text = let cmd = Command.create None command args text in - debug ("--> " ^ (Command.as_string cmd)); Iobuf.write iobuf cmd let msg iobuf recip text = @@ -48,11 +43,68 @@ let extern_callback iobuf sender forum text = in f lines -let handle_privmsg bot iobuf sender forum text = - if text.[0] == '.' then +let nick_of_nuhost s = + try + Irc.nick (Irc.nuhost_of_string s) + with Not_found -> + s + +let handle_command outbuf handle_cmd thisbuf cmd = + let (prefix, command, args, trailing) = Command.as_tuple cmd in + let (sender, forum) = + match (prefix, command, args, trailing) with + | (Some suhost, "PRIVMSG", [target], _) + | (Some suhost, "NOTICE", [target], _) -> + let sender = nick_of_nuhost suhost in + let forum = if Irc.is_channel target then target else sender in + (sender, forum) + +(* Here's why the IRC protocol blows: *) + | (Some suhost, "PART", [forum], _) + | (Some suhost, "JOIN", [forum], _) + | (Some suhost, "MODE", forum :: _, _) + | (Some suhost, "INVITE", _, Some forum) + | (Some suhost, "TOPIC", forum :: _, _) + | (Some suhost, "KICK", forum :: _, _) -> + (nick_of_nuhost suhost, forum) + + | (Some suhost, "JOIN", [], Some chan) -> + (nick_of_nuhost suhost, chan) + + | (Some _, "NICK", [sender], _) -> + (sender, sender) + + | (Some suhost, "QUIT", _, _) + | (Some suhost, _, _, _) -> + let sender = nick_of_nuhost suhost in + (sender, sender) + + | (_, "PING", _, Some text) -> + write outbuf "PONG" [] (Some text); + ("", "") + + | (None, _, _, _) -> + ("", "") + in + let pfx = + match prefix with + | Some txt -> txt + | None -> "" + in + let text = + match trailing with + | Some txt -> txt + | None -> "" + in + let argv = + Array.append + [|handle_cmd; sender; forum; pfx; command|] + (Array.of_list args) + in Process.create_canned - (Iobuf.dispatcher iobuf) + (Iobuf.dispatcher thisbuf) text +<<<<<<< master:bot.ml (extern_callback iobuf sender forum) "./helper" [|"./helper"; sender; forum|] @@ -79,6 +131,12 @@ let handle_command bot outbuf thisbuf cmd = msg outbuf chan "hi asl" | _ -> () +======= + (extern_callback outbuf sender forum) + handle_cmd + argv + +>>>>>>> local:bot.ml let discard_command iobuf cmd = () @@ -86,6 +144,7 @@ let handle_error iobuf str = prerr_endline ("!!! " ^ str) let main () = +<<<<<<< master:bot.ml let bot = {store = Infobot.create "info.cdb"} in let dispatcher = Dispatch.create () in @@ -93,19 +152,48 @@ let main () = Process.spawn "socat" [|"socat"; "STDIO"; "OPENSSL:woozle.org:697,verify=0"|] +======= + let handler = ref "/bin/true" in + let inputfn = ref "" in + let nick = ref "bot" in + let user = ref "bot" in + let mode = ref "+i" in + let realname = ref "I'm a little printf, short and stdout" in + let connect = ref [||] in + let append_connect s = connect := Array.append !connect [|s|] in + let speclist = + [ + ("-n", Arg.Set_string nick, "Nickname"); + ("-u", Arg.Set_string user, "Username"); + ("-m", Arg.Set_string mode, "Mode"); + ("-r", Arg.Set_string realname, "Real name"); + ("-a", Arg.Set_string handler, "IRC message handler"); + ("-i", Arg.Set_string inputfn, "Command FIFO"); + ] +>>>>>>> local:bot.ml in - let iobuf_out = Iobuf.create dispatcher conn_out "collab_out" - discard_command - handle_error - in - let _ = Iobuf.create dispatcher conn_in "collab_in" - (handle_command bot iobuf_out) - handle_error - in - write iobuf_out "NICK" ["zinc"] None; - write iobuf_out "USER" ["zinc"; "zinc"; "zinc"] (Some "I'm a little printf, short and stdout"); - Dispatch.run dispatcher - + let usage = "usage: bot [OPTIONS] CONNECT-COMMAND [ARGS ...]" in + Arg.parse speclist append_connect usage; + if (Array.length !connect) < 1 then begin + prerr_endline "Error: must specify connect command."; + prerr_endline ""; + prerr_endline "Run with --help for usage information."; + exit 64 (* EX_USAGE *) + end; + + let dispatcher = Dispatch.create () in + let conn_out, conn_in = Process.spawn (!connect).(0) !connect in + let iobuf_out = Iobuf.create dispatcher conn_out "out" + discard_command + handle_error + in + let _ = Iobuf.create dispatcher conn_in "in" + (handle_command iobuf_out !handler) + handle_error + in + write iobuf_out "NICK" [!nick] None; + write iobuf_out "USER" [!user; !mode; "merf"] (Some !realname); + Dispatch.run dispatcher let _ = main () diff --git a/process.ml b/process.ml index 2894d63..43b574b 100644 --- a/process.ml +++ b/process.ml @@ -8,7 +8,6 @@ let spawn prog args = Unix.close fd0_exit; Unix.dup2 fd1_entr Unix.stdout; - Unix.dup2 fd1_entr Unix.stderr; Unix.close fd1_entr; Unix.close fd1_exit; @@ -54,15 +53,21 @@ let canned_handler d p fd event = p.finished (String.sub p.stdout 0 p.stdout_pos) end | Dispatch.Output -> - let len = - Unix.write fd p.stdin p.stdin_pos - ((String.length p.stdin) - p.stdin_pos) - in - p.stdin_pos <- p.stdin_pos + len; - if (p.stdin_pos == String.length p.stdin) then begin + begin + try + let len = + Unix.write fd p.stdin p.stdin_pos + ((String.length p.stdin) - p.stdin_pos) + in + p.stdin_pos <- p.stdin_pos + len; + if (p.stdin_pos == String.length p.stdin) then begin + Unix.close fd; + Dispatch.delete d fd + end + with Unix.Unix_error _ -> Unix.close fd; Dispatch.delete d fd - end + end | Dispatch.Exception -> () @@ -95,6 +100,9 @@ let rec sigchld s = with Unix.Unix_error (Unix.ECHILD, _, _) -> () -let _ = - Sys.set_signal Sys.sigchld (Sys.Signal_handle sigchld) +let sigpipe s = () + +let _ = + Sys.set_signal Sys.sigchld (Sys.Signal_handle sigchld); + Sys.set_signal Sys.sigpipe (Sys.Signal_handle sigpipe) diff --git a/rollforinitiative.py b/rollforinitiative.py new file mode 100755 index 0000000..16a04c2 --- /dev/null +++ b/rollforinitiative.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +import re +import sys +import random + +if __name__ == '__main__': + roll = sys.argv[1] + m = re.match('^(?P\d+)d(?P\d+)(x(?P\d+))?$', roll) + if m: + rolls = int(m.group('rolls')) + sides = int(m.group('sides')) + if m.group('multiplier'): + multiplier = int(m.group('multiplier')) + else: + multiplier = 1 + + dice = [] + acc = 0 + for i in range(rolls): + n = random.randint(1, sides) + dice.append(n) + acc += n + acc *= multiplier + if rolls > 1: + print '%s: %d %r' % (roll, acc, dice) + else: + print '%s: %d' % (roll, acc) +