diff --git a/lib/server/connection.ml b/lib/server/connection.ml index 4daf779..997ea28 100644 --- a/lib/server/connection.ml +++ b/lib/server/connection.ml @@ -34,6 +34,10 @@ type reply = string * string list type 'a result = ('a, reply) Result.t +let list_of_errors = function + | Ok () -> [] + | Error e -> [e] + let reply t (num, params) = let prefix = Server_info.prefix t.server_info in let target = @@ -59,6 +63,7 @@ let unknowncommand cmd = "421", [cmd; "Unknown command"] let nonicknamegiven = "431", ["No nickname given"] let erroneusnickname nick = "432", [nick; "Erroneus nickname"] let nicknameinuse nick = "433", [nick; "Nickname is already in use"] +let usernotinchannel n c = "442", [n; c; "They aren't on that channel"] let notonchannel chan = "442", [chan; "You're not on that channel"] let notregistered = "451", ["You have not registered"] let needmoreparams cmd = "461", [cmd; "Not enough parameters"] @@ -215,25 +220,29 @@ let on_set_chan_mode chan me modestr args ~router = set_chan_mode chan ~from:me ~add:chg.chan_modes.add ~rem:chg.chan_modes.rem; Option.iter (set_chan_key chan ~from:me) chg.chan_key; Option.iter (set_chan_limit chan ~from:me) chg.chan_limit; - List.iter - (fun (op, mode, nick) -> - try - let user = Router.find_user router nick in - let mem = Router.membership chan user in - let priv = match mode with `o -> Router.Operator | `v -> Voice in - match op with - | `add -> - set_member_priv mem priv ~from:me - | `rem -> - if mem.mem_priv = priv then - set_member_priv mem Normal ~from:me - with Not_found -> - ()) - chg.chan_privs; - (* TODO: ban (+b) *) + (* TODO: MODE +b *) - Ok [] + let results = + List.map + (fun (dir, mode, nick) -> + let* user = try Ok (Router.find_user router nick) + with Not_found -> Error (nosuchnick nick) in + let* mem = try Ok (Router.membership chan user) + with Not_found -> Error (usernotinchannel (User.nick user) (Chan.name chan)) in + let priv : Router.priv = match mode with + | `o -> Operator + | `v -> Voice + in + begin match dir with + | `add -> set_member_priv mem priv ~from:me + | `rem -> if mem.mem_priv = priv then set_member_priv mem Normal ~from:me + end; + Ok ()) + chg.chan_privs + in + + Ok (List.flat_map list_of_errors results) let on_msg_mode t name args = let* me = require_registered t in @@ -636,10 +645,14 @@ let pp_args ppf (cmd, params) = Fmt.pf ppf "@[%s@ %a@]" cmd (Fmt.list (Fmt.fmt "%S") ~sep:Fmt.sp) params let on_msg t (msg : Msg.t) : unit = - split_command_params msg.command msg.params |> - List.iter - (fun args -> - trace (fun m -> m "@[%a:@ %a@]" pp_sockaddr t.addr pp_args args); - match dispatch t args with - | Ok () -> () - | Error err -> reply t err) + let results = + List.map + (fun cmd -> + trace (fun m -> m "@[%a:@ %a@]" pp_sockaddr t.addr pp_args cmd); + dispatch t cmd) + (split_command_params + msg.command + msg.params) + in + List.iter (reply t) + (List.flat_map list_of_errors results)