irc-bot/bot.ml

112 lines
3.0 KiB
OCaml

type bot = {
store: Infobot.t;
}
let debug = prerr_endline
let file_descr_of_int (i:int) =
let blob = Marshal.to_string i [] in
(Marshal.from_string blob 0 : Unix.file_descr)
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 =
write iobuf "PRIVMSG" [recip] (Some text)
let split = Str.split (Str.regexp "[ \t]*\r?\n")
(** Callback upon completion of the external command helper *)
let extern_callback iobuf sender forum text =
let lines = split text in
let nlines = List.length lines in
let recip =
if (nlines > 5) then begin
if (forum <> sender) then
msg iobuf forum (Format.sprintf "%d lines, sending privately" nlines);
sender
end else
forum
in
let rec f = function
| [] ->
()
| "" :: tl ->
f tl
| line :: tl ->
if line.[0] == ':' then
(* Interpret as raw IRC commands *)
let ine = Str.string_after line 1 in
let cmd = Command.from_string ine in
Iobuf.write iobuf cmd
else
(* Naive case: send to the recipient *)
msg iobuf recip line;
f tl
in
f lines
let handle_privmsg bot iobuf sender forum text =
if text.[0] == '.' then
Process.create_canned
(Iobuf.dispatcher iobuf)
text
(extern_callback iobuf sender forum)
"./helper"
[|"./helper"; sender; forum|]
else
Infobot.handle_privmsg bot.store (msg iobuf forum) sender forum text
let handle_command bot outbuf thisbuf cmd =
debug ("<-- " ^ (Command.as_string cmd));
match (Command.as_tuple cmd) with
| (Some suhost, "PRIVMSG", [target], Some text) ->
let sender = Irc.nick (Irc.nuhost_of_string suhost) in
let forum =
if Irc.is_channel target then
target
else
sender
in
handle_privmsg bot outbuf sender forum text
| (_, "PING", _, text) ->
write outbuf "PONG" [] text
| (_, "001", _, _) ->
write outbuf "JOIN" ["#bot"] None;
| (Some sender, "JOIN", [], Some chan) ->
msg outbuf chan "hi asl"
| _ ->
()
let discard_command iobuf cmd = ()
let handle_error iobuf str =
prerr_endline ("!!! " ^ str)
let main () =
let bot = {store = Infobot.create "info.cdb"} in
let dispatcher = Dispatch.create () in
let conn_out, conn_in =
Process.spawn "socat" [|"socat";
"STDIO";
"OPENSSL:woozle.org:697,verify=0"|]
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 _ =
main ()