mirror of https://github.com/nealey/irc-bot
A couple of minor infobot changes
This commit is contained in:
parent
83a76d3695
commit
607e53f417
2
Makefile
2
Makefile
|
@ -5,7 +5,7 @@ OCAMLC = ocamlc
|
|||
OCAMLDEP = ocamldep $(INCLUDES)
|
||||
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) $^
|
||||
|
||||
.PHONY: clean
|
||||
|
|
14
bot.ml
14
bot.ml
|
@ -1,10 +1,15 @@
|
|||
type bot = {
|
||||
store: Infobot.t;
|
||||
}
|
||||
|
||||
let write iobuf command args text =
|
||||
let cmd = Command.create None command args text in
|
||||
print_endline ("--> " ^ (Command.as_string cmd));
|
||||
Iobuf.write iobuf cmd
|
||||
|
||||
let handle_command iobuf cmd =
|
||||
let handle_command bot iobuf cmd =
|
||||
print_endline ("<-- " ^ (Command.as_string cmd));
|
||||
Infobot.handle_command bot.store iobuf cmd;
|
||||
match Command.as_tuple cmd with
|
||||
| (_, "PING", _, text) ->
|
||||
write iobuf "PONG" [] text
|
||||
|
@ -22,9 +27,12 @@ let main () =
|
|||
let host = Unix.gethostbyname "woozle.org" in
|
||||
let dispatcher = Dispatch.create 5 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 iobuf = Iobuf.create dispatcher conn "woozle" Plugin.handle_command handle_error in
|
||||
Plugin.register handle_command;
|
||||
let iobuf = Iobuf.create dispatcher conn "woozle"
|
||||
(handle_command bot)
|
||||
handle_error
|
||||
in
|
||||
write iobuf "NICK" ["bot"] None;
|
||||
write iobuf "USER" ["bot"; "bot"; "bot"] (Some "A Bot");
|
||||
Dispatch.run dispatcher
|
||||
|
|
37
dispatch.ml
37
dispatch.ml
|
@ -22,14 +22,6 @@ type t = {
|
|||
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 =
|
||||
{read_fds = ref [];
|
||||
write_fds = ref [];
|
||||
|
@ -88,7 +80,7 @@ let delete_timer d time =
|
|||
|
||||
|
||||
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
|
||||
if now < time then
|
||||
()
|
||||
|
@ -113,28 +105,29 @@ let rec dispatch_results d (read_ready, write_ready, except_ready) =
|
|||
dispatch Exception except_ready
|
||||
|
||||
let once d =
|
||||
let now = Unix.gettimeofday () in
|
||||
let timeout =
|
||||
(* You might think it'd work better to use the timeout of select().
|
||||
Not so! select() waits *at most* timeout ms. Doing things
|
||||
this way results in a tight loop as the timer approaches. *)
|
||||
let interval =
|
||||
try
|
||||
let (time, _) = Timer.min_elt !(d.timers) in
|
||||
let delta = (time -. now +. timeout_fudge) in
|
||||
let (next, _) = Timer.min_elt !(d.timers) in
|
||||
let delta = (next -. (Unix.gettimeofday ())) in
|
||||
max delta 0.0
|
||||
with Not_found ->
|
||||
(-1.0)
|
||||
0.0
|
||||
in
|
||||
(* select () waits *at most* timeout ms. If you have fds but they're
|
||||
not
|
||||
doing anything, multiple calls to once may be required. This is
|
||||
lame. *)
|
||||
let result = Unix.select !(d.read_fds) !(d.write_fds) !(d.except_fds) timeout in
|
||||
let s = { Unix.it_interval = interval; Unix.it_value = 0.0 } in
|
||||
let _ = Sys.set_signal Sys.sigalrm Sys.Signal_ignore in
|
||||
let _ = Unix.setitimer Unix.ITIMER_REAL s in
|
||||
let result = Unix.select !(d.read_fds) !(d.write_fds) !(d.except_fds) (-1.0) in
|
||||
dispatch_results d result;
|
||||
dispatch_timers d (Unix.gettimeofday ())
|
||||
|
||||
let rec run d =
|
||||
if ((!(d.handlers) == Fd_map.empty) &&
|
||||
(!(d.timers) == Timer.empty)) then
|
||||
let rec run d =
|
||||
if (Fd_map.is_empty !(d.handlers)) && (Timer.is_empty !(d.timers)) then
|
||||
()
|
||||
else begin
|
||||
once d;
|
||||
run d
|
||||
end
|
||||
|
||||
|
|
63
infobot.ml
63
infobot.ml
|
@ -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 create filename =
|
||||
{
|
||||
filename = filename;
|
||||
db = Cdb.open_cdb_in filename;
|
||||
}
|
||||
|
||||
let choice l =
|
||||
let n = Random.int (List.length l) in
|
||||
List.nth l n
|
||||
|
||||
let choose_one key =
|
||||
let matches = Cdb.get_matches info_db key in
|
||||
match Stream.npeek 120 matches with
|
||||
| [] -> raise Not_found
|
||||
| keys -> choice keys
|
||||
let strip s =
|
||||
let rec lastchar n =
|
||||
match s.[n-1] with
|
||||
| '.'
|
||||
| '!'
|
||||
| '?'
|
||||
| ' ' ->
|
||||
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
|
||||
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 =
|
||||
match factoid.[0] with
|
||||
| ':' ->
|
||||
|
@ -21,20 +58,16 @@ let handle_privmsg iobuf sender target text =
|
|||
| '\\' ->
|
||||
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
|
||||
Iobuf.write iobuf (Command.create None "PRIVMSG" [target] (Some response))
|
||||
with Not_found ->
|
||||
()
|
||||
|
||||
let handle_command iobuf cmd =
|
||||
print_endline ("<I- " ^ (Command.as_string cmd));
|
||||
let handle_command store iobuf cmd =
|
||||
match Command.as_tuple cmd with
|
||||
| (Some sender, "PRIVMSG", [target], Some text) ->
|
||||
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"
|
||||
|
|
24
plugin.ml
24
plugin.ml
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue