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)
|
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
14
bot.ml
|
@ -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
|
||||||
|
|
35
dispatch.ml
35
dispatch.ml
|
@ -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
|
||||||
|
|
||||||
|
|
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 _ = 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"
|
|
||||||
|
|
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