open! Import include Router_types include (val Logging.sublogs logger "Router") type t = router let make () = { users = Hashtbl.create 4096; channels = Hashtbl.create 4096 } let is_nick_available t nick = not (Hashtbl.mem t.users (string_ci nick)) let find_user t nick = Hashtbl.find t.users (string_ci nick) let find_chan t name = Hashtbl.find t.channels (string_ci name) let relay ~(from : user) (msg : Msg.t) tgts = let msg = if msg.prefix = No_prefix then { msg with prefix = User.prefix from } else msg in let bcc u = Outbox.Bcc.add u.outbox in let bcc_not_self u = if u != from then bcc u in let bcc_channel c = List.iter bcc_not_self (Chan.members c) in List.iter (function | `to_self -> bcc from | `to_user tgt -> bcc tgt | `to_chan tgt -> bcc_channel tgt | `to_interested -> bcc from; List.iter bcc_channel (User.channels from)) tgts; Outbox.Bcc.send_all msg let join chan user = let mem = { mem_chan = chan; mem_user = user; mem_priv = Normal; mem_in_chan = None; mem_in_user = None; } in begin mem.mem_in_chan <- Some (Dllist.add_r mem chan.members); mem.mem_in_user <- Some (Dllist.add_r mem user.membership); chan.member_count <- succ chan.member_count; mem end let membership chan user = Dllist.find_node_l (fun mem -> mem.mem_chan == chan) user.membership |> Dllist.get let part mem = try Dllist.remove (Option.get mem.mem_in_user); Dllist.remove (Option.get mem.mem_in_chan); mem.mem_in_user <- None; mem.mem_in_chan <- None; mem.mem_chan.member_count <- pred mem.mem_chan.member_count; with Invalid_argument _ -> warn (fun m -> m "part (%S,%S): already removed" (Chan.name mem.mem_chan) (User.nick mem.mem_user))