add LIST command

This commit is contained in:
tali 2024-02-02 17:35:46 -05:00
parent a34651b283
commit 00eae82eb3
3 changed files with 48 additions and 7 deletions

View File

@ -24,6 +24,7 @@ let creation_time t = t.creation_time
let topic t = fst t.topic let topic t = fst t.topic
let topic_who_time t = snd t.topic let topic_who_time t = snd t.topic
let set_topic ~who ?time t text = t.topic <- text, Some (who, value_or_now time) let set_topic ~who ?time t text = t.topic <- text, Some (who, value_or_now time)
let member_count t = t.member_count
let mode t = t.chan_mode let mode t = t.chan_mode
let set_mode t new_mode = t.chan_mode <- new_mode let set_mode t new_mode = t.chan_mode <- new_mode
let limit t = t.chan_limit let limit t = t.chan_limit

View File

@ -347,30 +347,29 @@ let membership_prefix = function
let is_invisible user = let is_invisible user =
Mode.Set.mem `i (User.mode user) Mode.Set.mem `i (User.mode user)
let list_names t me chan = let is_secret chan =
let is_secret = Mode.Set.mem `s (Chan.mode chan) in Mode.Set.mem `s (Chan.mode chan)
let list_names t me chan =
let members = let members =
match Router.membership chan me with match Router.membership chan me with
| _is_member -> Chan.membership chan | _is_member -> Chan.membership chan
| exception Not_found -> | exception Not_found ->
if is_secret then if is_secret chan then
[] []
else else
Chan.membership_when Chan.membership_when
(fun mem -> not (is_invisible mem.mem_user)) (fun mem -> not (is_invisible mem.mem_user))
chan chan
in in
let nicks = let nicks =
List.map List.map
(fun mem -> (fun mem ->
membership_prefix mem.mem_priv ^ User.nick mem.mem_user) membership_prefix mem.mem_priv ^ User.nick mem.mem_user)
members members
in in
let chan_name = Chan.name chan in let chan_name = Chan.name chan in
let chan_sym = if is_secret then "@" else "=" in let chan_sym = if is_secret chan then "@" else "=" in
begin begin
(* TODO: concat member names until message becomes too long *) (* TODO: concat member names until message becomes too long *)
List.iter (fun nick -> reply t ("353", [chan_sym; chan_name; nick])) nicks; List.iter (fun nick -> reply t ("353", [chan_sym; chan_name; nick])) nicks;
@ -686,6 +685,43 @@ let on_msg_userhost t nicks =
reply t ("302", [String.concat " " results]); reply t ("302", [String.concat " " results]);
Ok () Ok ()
let list_channels t me channels =
begin
reply t ("321", ["Channel"; "Users Name"]);
Seq.iter
(function
| Error err -> reply t err
| Ok chan ->
try
if is_secret chan then Router.membership chan me |> ignore;
let count = Chan.member_count chan in
let topic = Option.value (Chan.topic chan) ~default:"" in
reply t ("322", [Chan.name chan; string_of_int count; topic])
with Not_found ->
())
channels;
reply t ("323", ["End of /LIST"]);
end
let on_msg_list t names =
let* me = require_registered t in
let channels = match names with
| [] ->
Seq.map Result.ok
(Router.all_channels_seq t.router)
| _ ->
Seq.map
(fun name ->
try
match name_type name with
| `chan -> Ok (Router.find_chan t.router name)
| `nick | `invalid -> raise Not_found
with Not_found ->
Error (nosuchnick name))
(List.to_seq names)
in
list_channels t me channels;
Ok ()
(* welcome and quit *) (* welcome and quit *)
@ -938,6 +974,8 @@ let dispatch t = function
| "WHOWAS", ([] | "" :: _) -> Error nonicknamegiven | "WHOWAS", ([] | "" :: _) -> Error nonicknamegiven
| "WHOWAS", [nick] -> on_msg_whowas t nick "" | "WHOWAS", [nick] -> on_msg_whowas t nick ""
| "WHOWAS", nick :: count :: _ -> on_msg_whowas t nick count | "WHOWAS", nick :: count :: _ -> on_msg_whowas t nick count
| "LIST", chans :: _ -> on_msg_list t (String.split_on_char ',' chans)
| "LIST", [] -> on_msg_list t []
| "USERHOST", nicks -> on_msg_userhost t nicks | "USERHOST", nicks -> on_msg_userhost t nicks
| ("USER" | "JOIN" | "NAMES" | "PART" | "KICK" | "MODE" | "WHO") as cmd, _ -> | ("USER" | "JOIN" | "NAMES" | "PART" | "KICK" | "MODE" | "WHO") as cmd, _ ->
Error (needmoreparams cmd) Error (needmoreparams cmd)
@ -951,7 +989,6 @@ let dispatch t = function
| tgt :: msg :: _ -> on_msg_privmsg t tgt msg ~cmd | tgt :: msg :: _ -> on_msg_privmsg t tgt msg ~cmd
end end
(* TODO: "LIST" *)
| cmd, _ -> | cmd, _ ->
Error (unknowncommand cmd) Error (unknowncommand cmd)

View File

@ -28,6 +28,9 @@ let find_chan t name =
let whowas t nick = let whowas t nick =
Cache.find_all t.whowas (string_ci nick) Cache.find_all t.whowas (string_ci nick)
let all_channels_seq t =
Hashtbl.to_seq_values t.channels
let nuke t = let nuke t =
begin begin
Hashtbl.iter (fun _ u -> Dllist.reset u.membership) t.users; Hashtbl.iter (fun _ u -> Dllist.reset u.membership) t.users;