2024-01-08 03:28:31 +00:00
|
|
|
type nick_key = Nick_key of string [@@unboxed]
|
|
|
|
let nick_key n = Nick_key (String.lowercase_ascii n) (* TODO: "scandinavian" lowercase *)
|
|
|
|
let unset = Nick_key ""
|
|
|
|
|
|
|
|
type t = {
|
|
|
|
users : (nick_key, user) Hashtbl.t
|
|
|
|
(* TODO: channels *)
|
|
|
|
}
|
|
|
|
|
|
|
|
and user = {
|
|
|
|
router : t;
|
|
|
|
hostname : string;
|
|
|
|
mutable key : nick_key;
|
2024-01-08 05:39:39 +00:00
|
|
|
mutable nick : Irc.nick;
|
2024-01-08 03:28:31 +00:00
|
|
|
mutable userinfo : Irc.userinfo option;
|
|
|
|
mutable mode : Irc.Mode.t;
|
2024-01-08 05:05:01 +00:00
|
|
|
inbox : Irc.Msg.t Lwt_stream.t;
|
|
|
|
push_inbox : (Irc.Msg.t option -> unit);
|
2024-01-08 03:28:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let make () =
|
|
|
|
{ users = Hashtbl.create 4096 }
|
|
|
|
|
|
|
|
let find_user t nick =
|
|
|
|
Hashtbl.find_opt t.users (nick_key nick)
|
|
|
|
|
|
|
|
module User = struct
|
|
|
|
type t = user
|
|
|
|
|
|
|
|
let make router ~hostname =
|
2024-01-08 05:05:01 +00:00
|
|
|
let inbox, push_inbox = Lwt_stream.create () in
|
2024-01-08 03:28:31 +00:00
|
|
|
{
|
|
|
|
router;
|
|
|
|
hostname;
|
|
|
|
key = unset;
|
2024-01-08 05:39:39 +00:00
|
|
|
nick = "*";
|
2024-01-08 03:28:31 +00:00
|
|
|
userinfo = None;
|
|
|
|
mode = Irc.Mode.of_string "iw";
|
2024-01-08 05:05:01 +00:00
|
|
|
inbox; push_inbox;
|
2024-01-08 03:28:31 +00:00
|
|
|
}
|
|
|
|
|
2024-01-08 05:39:39 +00:00
|
|
|
let nick t = t.nick
|
|
|
|
let prefix t = Irc.Msg.User_prefix (t.nick, t.userinfo, Some t.hostname)
|
|
|
|
|
2024-01-08 05:05:01 +00:00
|
|
|
let inbox t = t.inbox
|
|
|
|
let send t msg = try t.push_inbox (Some msg) with Lwt_stream.Closed -> ()
|
|
|
|
let close t = try t.push_inbox None with Lwt_stream.Closed -> ()
|
2024-01-08 03:28:31 +00:00
|
|
|
|
|
|
|
let is_registered t = t.key <> unset
|
|
|
|
|
2024-01-08 05:39:39 +00:00
|
|
|
let unregister t =
|
2024-01-08 03:28:31 +00:00
|
|
|
Hashtbl.remove t.router.users t.key;
|
|
|
|
t.key <- unset
|
|
|
|
|
|
|
|
let set_nick t new_nick =
|
|
|
|
let key = nick_key new_nick in
|
|
|
|
if Hashtbl.mem t.router.users key then
|
|
|
|
`nick_in_use
|
|
|
|
else begin
|
2024-01-08 05:31:05 +00:00
|
|
|
((* TODO: relay NICK message *));
|
2024-01-08 05:39:39 +00:00
|
|
|
unregister t;
|
2024-01-08 03:28:31 +00:00
|
|
|
Hashtbl.add t.router.users key t;
|
|
|
|
t.key <- key;
|
2024-01-08 05:39:39 +00:00
|
|
|
t.nick <- new_nick;
|
2024-01-08 03:28:31 +00:00
|
|
|
`nick_set
|
|
|
|
end
|
|
|
|
|
2024-01-08 05:05:01 +00:00
|
|
|
let cleanup t =
|
2024-01-08 05:31:05 +00:00
|
|
|
(* TODO: relay QUIT message *)
|
2024-01-08 05:39:39 +00:00
|
|
|
unregister t;
|
|
|
|
close t
|
2024-01-08 03:28:31 +00:00
|
|
|
end
|
2024-01-08 05:05:01 +00:00
|
|
|
|
|
|
|
let privmsg src dst txt =
|
2024-01-08 05:31:05 +00:00
|
|
|
let prefix = User.prefix src in
|
2024-01-08 05:05:01 +00:00
|
|
|
match dst with
|
|
|
|
| `user dst ->
|
|
|
|
let msg = Irc.Msg.make "PRIVMSG" [User.nick dst; txt] ~prefix in
|
|
|
|
User.send dst msg
|