A couple of minor infobot changes

This commit is contained in:
Neale Pickett 2010-12-08 17:18:07 -07:00
parent 83a76d3695
commit 607e53f417
6 changed files with 75 additions and 70 deletions

View File

@ -5,7 +5,7 @@ OCAMLC = ocamlc
OCAMLDEP = ocamldep $(INCLUDES) OCAMLDEP = ocamldep $(INCLUDES)
OCAMLLIBS = unix.cma str.cma nums.cma OCAMLLIBS = unix.cma str.cma nums.cma
bot: irc.cmo dispatch.cmo command.cmo iobuf.cmo cdb.cmo bindings.cmo plugin.cmo infobot.cmo bot.cmo infobot.cmo bot: irc.cmo dispatch.cmo command.cmo iobuf.cmo cdb.cmo bindings.cmo infobot.cmo bot.cmo infobot.cmo
$(OCAMLC) -o $@ $(OCAMLLIBS) $^ $(OCAMLC) -o $@ $(OCAMLLIBS) $^
.PHONY: clean .PHONY: clean

14
bot.ml
View File

@ -1,10 +1,15 @@
type bot = {
store: Infobot.t;
}
let write iobuf command args text = let write iobuf command args text =
let cmd = Command.create None command args text in let cmd = Command.create None command args text in
print_endline ("--> " ^ (Command.as_string cmd)); print_endline ("--> " ^ (Command.as_string cmd));
Iobuf.write iobuf cmd Iobuf.write iobuf cmd
let handle_command iobuf cmd = let handle_command bot iobuf cmd =
print_endline ("<-- " ^ (Command.as_string cmd)); print_endline ("<-- " ^ (Command.as_string cmd));
Infobot.handle_command bot.store iobuf cmd;
match Command.as_tuple cmd with match Command.as_tuple cmd with
| (_, "PING", _, text) -> | (_, "PING", _, text) ->
write iobuf "PONG" [] text write iobuf "PONG" [] text
@ -22,9 +27,12 @@ let main () =
let host = Unix.gethostbyname "woozle.org" in let host = Unix.gethostbyname "woozle.org" in
let dispatcher = Dispatch.create 5 in let dispatcher = Dispatch.create 5 in
let conn = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in let conn = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in
let bot = {store = Infobot.create "info.cdb"} in
let _ = Unix.connect conn (Unix.ADDR_INET (host.Unix.h_addr_list.(0), 6667)) in let _ = Unix.connect conn (Unix.ADDR_INET (host.Unix.h_addr_list.(0), 6667)) in
let iobuf = Iobuf.create dispatcher conn "woozle" Plugin.handle_command handle_error in let iobuf = Iobuf.create dispatcher conn "woozle"
Plugin.register handle_command; (handle_command bot)
handle_error
in
write iobuf "NICK" ["bot"] None; write iobuf "NICK" ["bot"] None;
write iobuf "USER" ["bot"; "bot"; "bot"] (Some "A Bot"); write iobuf "USER" ["bot"; "bot"; "bot"] (Some "A Bot");
Dispatch.run dispatcher Dispatch.run dispatcher

View File

@ -22,14 +22,6 @@ type t = {
timers : Timer.t ref; timers : Timer.t ref;
} }
(* select(), poll(), and epoll() treat timeout as an upper bound of time
to wait. This fudge factor helps ensure that given no FD activity,
this isn't run in a tight loop as a timer approaches. This value was
determined experimentally on a 1.25GHz G4 PPC to work most of the
time. Your mileage may vary. *)
let timeout_fudge = 0.001
let create size = let create size =
{read_fds = ref []; {read_fds = ref [];
write_fds = ref []; write_fds = ref [];
@ -88,7 +80,7 @@ let delete_timer d time =
let rec dispatch_timers d now = let rec dispatch_timers d now =
if (!(d.timers) != Timer.empty) then if not (Timer.is_empty !(d.timers)) then
let (time, handler) = Timer.min_elt !(d.timers) in let (time, handler) = Timer.min_elt !(d.timers) in
if now < time then if now < time then
() ()
@ -113,28 +105,29 @@ let rec dispatch_results d (read_ready, write_ready, except_ready) =
dispatch Exception except_ready dispatch Exception except_ready
let once d = let once d =
let now = Unix.gettimeofday () in (* You might think it'd work better to use the timeout of select().
let timeout = Not so! select() waits *at most* timeout ms. Doing things
this way results in a tight loop as the timer approaches. *)
let interval =
try try
let (time, _) = Timer.min_elt !(d.timers) in let (next, _) = Timer.min_elt !(d.timers) in
let delta = (time -. now +. timeout_fudge) in let delta = (next -. (Unix.gettimeofday ())) in
max delta 0.0 max delta 0.0
with Not_found -> with Not_found ->
(-1.0) 0.0
in in
(* select () waits *at most* timeout ms. If you have fds but they're let s = { Unix.it_interval = interval; Unix.it_value = 0.0 } in
not let _ = Sys.set_signal Sys.sigalrm Sys.Signal_ignore in
doing anything, multiple calls to once may be required. This is let _ = Unix.setitimer Unix.ITIMER_REAL s in
lame. *) let result = Unix.select !(d.read_fds) !(d.write_fds) !(d.except_fds) (-1.0) in
let result = Unix.select !(d.read_fds) !(d.write_fds) !(d.except_fds) timeout in
dispatch_results d result; dispatch_results d result;
dispatch_timers d (Unix.gettimeofday ()) dispatch_timers d (Unix.gettimeofday ())
let rec run d = let rec run d =
if ((!(d.handlers) == Fd_map.empty) && if (Fd_map.is_empty !(d.handlers)) && (Timer.is_empty !(d.timers)) then
(!(d.timers) == Timer.empty)) then
() ()
else begin else begin
once d; once d;
run d run d
end end

View File

@ -1,19 +1,56 @@
let info_db = Cdb.open_cdb_in "/home/neale/src/firebot/info.cdb" type t = {
filename: string;
mutable db: Cdb.cdb_file;
}
let _ = Random.self_init () let _ = Random.self_init ()
let create filename =
{
filename = filename;
db = Cdb.open_cdb_in filename;
}
let choice l = let choice l =
let n = Random.int (List.length l) in let n = Random.int (List.length l) in
List.nth l n List.nth l n
let choose_one key = let strip s =
let matches = Cdb.get_matches info_db key in let rec lastchar n =
match Stream.npeek 120 matches with match s.[n-1] with
| [] -> raise Not_found | '.'
| keys -> choice keys | '!'
| '?'
| ' ' ->
lastchar (n - 1)
| _ ->
n
in
let len = lastchar (String.length s) in
if (len = String.length s) then
None
else
Some (String.sub s 0 len)
let handle_privmsg iobuf sender target text = let choose_one ib key =
match (Cdb.get_matches ib.db key) with
| [] ->
raise Not_found
| keys ->
choice keys
let handle_privmsg store iobuf sender target text =
try try
let factoid = choose_one text in let text, factoid =
try
(text, choose_one store text)
with Not_found ->
match (strip text) with
| None ->
raise Not_found
| Some stext ->
(stext, choose_one store stext)
in
let response = let response =
match factoid.[0] with match factoid.[0] with
| ':' -> | ':' ->
@ -21,20 +58,16 @@ let handle_privmsg iobuf sender target text =
| '\\' -> | '\\' ->
Str.string_after factoid 1 Str.string_after factoid 1
| _ -> | _ ->
Printf.sprintf "I've heard that %s is %s" text factoid Printf.sprintf "I overheard that %s is %s" text factoid
in in
Iobuf.write iobuf (Command.create None "PRIVMSG" [target] (Some response)) Iobuf.write iobuf (Command.create None "PRIVMSG" [target] (Some response))
with Not_found -> with Not_found ->
() ()
let handle_command iobuf cmd = let handle_command store iobuf cmd =
print_endline ("<I- " ^ (Command.as_string cmd));
match Command.as_tuple cmd with match Command.as_tuple cmd with
| (Some sender, "PRIVMSG", [target], Some text) -> | (Some sender, "PRIVMSG", [target], Some text) ->
if Irc.is_channel target then if Irc.is_channel target then
handle_privmsg iobuf sender target text handle_privmsg store iobuf sender target text
| _ -> | _ ->
() ()
let _ = Plugin.register handle_command
let _ = print_endline "========= INFOBOT"

View File

@ -1,24 +0,0 @@
type handler = Iobuf.t -> Command.t -> unit
let handlers = ref []
let register handler =
handlers := !handlers @ [handler]
let unregister handler =
handlers := List.filter ((<>) handler) !handlers
let handle_command iobuf cmd =
let rec loop h =
match h with
| [] -> ()
| handler :: tl ->
begin
try
handler iobuf cmd
with _ ->
()
end;
loop tl
in
loop !handlers

View File

@ -1,5 +0,0 @@
type handler = Iobuf.t -> Command.t -> unit
val register : handler -> unit
val unregister : handler -> unit
val handle_command : Iobuf.t -> Command.t -> unit