add KICK command and clean up KICK/PART/QUIT reason param
This commit is contained in:
parent
4aaa96c6c1
commit
a57d5b532a
|
@ -35,6 +35,8 @@ type reply = string * string list
|
||||||
|
|
||||||
type 'a result = ('a, reply) Result.t
|
type 'a result = ('a, reply) Result.t
|
||||||
|
|
||||||
|
let ( >>= ) = Result.bind
|
||||||
|
|
||||||
let list_of_errors = function
|
let list_of_errors = function
|
||||||
| Ok () -> []
|
| Ok () -> []
|
||||||
| Error e -> [e]
|
| Error e -> [e]
|
||||||
|
@ -433,18 +435,23 @@ let on_msg_join t name =
|
||||||
Ok ()
|
Ok ()
|
||||||
end
|
end
|
||||||
|
|
||||||
let leave t user chan ~why =
|
let leave t (mem : membership) ~from ~why =
|
||||||
let mem = Router.membership chan user in
|
let user = mem.mem_user in
|
||||||
|
let chan = mem.mem_chan in
|
||||||
begin match why with
|
begin match why with
|
||||||
(* TODO: KICK *)
|
|
||||||
| `quit ->
|
| `quit ->
|
||||||
(* if called from [quit], then we already relayed the QUIT message *)
|
(* assume QUIT message has already been relayed *)
|
||||||
()
|
()
|
||||||
| `part reason ->
|
| `part reason ->
|
||||||
let always_trailing = Option.is_some reason in
|
let always_trailing = Option.is_some reason in
|
||||||
let reason = Option.to_list reason in
|
let params = Chan.name chan :: Option.to_list reason in
|
||||||
let msg = Msg.make "PART" (Chan.name chan :: reason) ~always_trailing in
|
let msg = Msg.make "PART" params ~always_trailing in
|
||||||
Router.relay msg ~from:user [`to_chan chan; `to_self]
|
Router.relay msg ~from [`to_chan chan; `to_self]
|
||||||
|
| `kick comment ->
|
||||||
|
let always_trailing = Option.is_some comment in
|
||||||
|
let params = Chan.name chan :: User.nick user :: Option.to_list comment in
|
||||||
|
let msg = Msg.make "KICK" params ~always_trailing in
|
||||||
|
Router.relay msg ~from [`to_chan chan; `to_self]
|
||||||
end;
|
end;
|
||||||
Router.part mem;
|
Router.part mem;
|
||||||
if Chan.is_empty chan then
|
if Chan.is_empty chan then
|
||||||
|
@ -454,10 +461,6 @@ let leave t user chan ~why =
|
||||||
end
|
end
|
||||||
|
|
||||||
let on_msg_part t name reason =
|
let on_msg_part t name reason =
|
||||||
let reason = match reason with
|
|
||||||
| [] -> None
|
|
||||||
| xs -> Some (String.concat " " xs)
|
|
||||||
in
|
|
||||||
let* me = require_registered t in
|
let* me = require_registered t in
|
||||||
let* chan =
|
let* chan =
|
||||||
try
|
try
|
||||||
|
@ -467,18 +470,43 @@ let on_msg_part t name reason =
|
||||||
with Not_found ->
|
with Not_found ->
|
||||||
Error (nosuchchannel name)
|
Error (nosuchchannel name)
|
||||||
in
|
in
|
||||||
try
|
let* mem = try Ok (Router.membership chan me)
|
||||||
leave t me chan ~why:(`part reason);
|
with Not_found -> Error (notonchannel name) in
|
||||||
Ok ()
|
leave t mem ~from:me ~why:(`part reason);
|
||||||
with Not_found ->
|
Ok ()
|
||||||
Error (notonchannel name)
|
|
||||||
|
let on_msg_kick t name nick comment =
|
||||||
|
let* me = require_registered t in
|
||||||
|
let* chan =
|
||||||
|
try
|
||||||
|
match name_type name with
|
||||||
|
| `chan -> Ok (Router.find_chan t.router name)
|
||||||
|
| `nick | `invalid -> raise Not_found
|
||||||
|
with Not_found ->
|
||||||
|
Error (nosuchchannel name)
|
||||||
|
in
|
||||||
|
let* () = require_membership chan me >>= require_chan_op in
|
||||||
|
let* user =
|
||||||
|
try
|
||||||
|
match name_type nick with
|
||||||
|
| `nick -> Ok (Router.find_user t.router nick)
|
||||||
|
| `chan | `invalid -> raise Not_found
|
||||||
|
with Not_found ->
|
||||||
|
Error (nosuchnick name)
|
||||||
|
in
|
||||||
|
let* mem = try Ok (Router.membership chan user)
|
||||||
|
with Not_found ->
|
||||||
|
Error (usernotinchannel (User.nick user) (Chan.name chan))
|
||||||
|
in
|
||||||
|
leave t mem ~from:me ~why:(`kick comment);
|
||||||
|
Ok ()
|
||||||
|
|
||||||
let on_msg_join_0 t =
|
let on_msg_join_0 t =
|
||||||
(* "JOIN 0" actually means part from all joined channels *)
|
(* "JOIN 0" actually means part from all joined channels *)
|
||||||
let* me = require_registered t in
|
let* me = require_registered t in
|
||||||
List.iter
|
List.iter
|
||||||
(leave t me ~why:(`part None))
|
(leave t ~from:me ~why:(`part None))
|
||||||
(User.channels me);
|
(User.membership me);
|
||||||
Ok ()
|
Ok ()
|
||||||
|
|
||||||
|
|
||||||
|
@ -523,8 +551,8 @@ let quit t me ~reason =
|
||||||
Router.relay msg ~from:me [`to_interested];
|
Router.relay msg ~from:me [`to_interested];
|
||||||
|
|
||||||
List.iter
|
List.iter
|
||||||
(leave t me ~why:`quit)
|
(leave t ~from:me ~why:`quit)
|
||||||
(User.channels me);
|
(User.membership me);
|
||||||
|
|
||||||
User.unregister me ~router:t.router;
|
User.unregister me ~router:t.router;
|
||||||
t.user <- None
|
t.user <- None
|
||||||
|
@ -536,8 +564,8 @@ let close ?(reason = "Client closed") t =
|
||||||
|
|
||||||
let on_msg_quit t reason =
|
let on_msg_quit t reason =
|
||||||
let reason = match reason with
|
let reason = match reason with
|
||||||
| [] -> "Quit"
|
| None -> "Quit"
|
||||||
| xs -> String.concat " " ("Quit:" :: xs)
|
| Some x -> "Quit: " ^ x
|
||||||
in
|
in
|
||||||
close t ~reason;
|
close t ~reason;
|
||||||
Ok ()
|
Ok ()
|
||||||
|
@ -602,11 +630,15 @@ let on_msg_user t username realname =
|
||||||
|
|
||||||
(* message parsing *)
|
(* message parsing *)
|
||||||
|
|
||||||
|
let concat_args = function
|
||||||
|
| [] -> None
|
||||||
|
| xs -> Some (String.concat " " xs)
|
||||||
|
|
||||||
let dispatch t = function
|
let dispatch t = function
|
||||||
| "NICK", nick :: _ when nick <> "" -> on_msg_nick t nick
|
| "NICK", nick :: _ when nick <> "" -> on_msg_nick t nick
|
||||||
| "NICK", _ -> Error nonicknamegiven
|
| "NICK", _ -> Error nonicknamegiven
|
||||||
| "USER", unm :: _ :: _ :: rnm :: _ -> on_msg_user t unm rnm
|
| "USER", unm :: _ :: _ :: rnm :: _ -> on_msg_user t unm rnm
|
||||||
| "QUIT", reason -> on_msg_quit t reason
|
| "QUIT", reason -> on_msg_quit t (concat_args reason)
|
||||||
| "MOTD", _ -> on_msg_motd t
|
| "MOTD", _ -> on_msg_motd t
|
||||||
| "PRIVMSG", ([] | "" :: _) -> Error norecipient
|
| "PRIVMSG", ([] | "" :: _) -> Error norecipient
|
||||||
| "PRIVMSG", ([_] | _ :: "" :: _) -> Error notexttosend
|
| "PRIVMSG", ([_] | _ :: "" :: _) -> Error notexttosend
|
||||||
|
@ -615,9 +647,11 @@ let dispatch t = function
|
||||||
| "JOIN 0", _ -> (* hack; see split_command_params *) on_msg_join_0 t
|
| "JOIN 0", _ -> (* hack; see split_command_params *) on_msg_join_0 t
|
||||||
| "NAMES", tgt :: _ when tgt <> "" -> on_msg_names t tgt
|
| "NAMES", tgt :: _ when tgt <> "" -> on_msg_names t tgt
|
||||||
| "TOPIC", tgt :: args when tgt <> "" -> on_msg_topic t tgt args
|
| "TOPIC", tgt :: args when tgt <> "" -> on_msg_topic t tgt args
|
||||||
| "PART", tgt :: reason when tgt <> "" -> on_msg_part t tgt reason
|
| "PART", tgt :: reason when tgt <> "" -> on_msg_part t tgt (concat_args reason)
|
||||||
|
| "KICK", chn :: tgt :: comment when chn <> "" && tgt <> "" ->
|
||||||
|
on_msg_kick t chn tgt (concat_args comment)
|
||||||
| "MODE", tgt :: args when tgt <> "" -> on_msg_mode t tgt args
|
| "MODE", tgt :: args when tgt <> "" -> on_msg_mode t tgt args
|
||||||
| ("USER" | "JOIN" | "NAMES" | "PART" | "MODE") as cmd, _ ->
|
| ("USER" | "JOIN" | "NAMES" | "PART" | "KICK" | "MODE") as cmd, _ ->
|
||||||
Error (needmoreparams cmd)
|
Error (needmoreparams cmd)
|
||||||
| cmd, _ ->
|
| cmd, _ ->
|
||||||
Error (unknowncommand cmd)
|
Error (unknowncommand cmd)
|
||||||
|
@ -638,6 +672,12 @@ let split_command_params cmd params =
|
||||||
(* TODO: "JOIN" should be handled specially *)
|
(* TODO: "JOIN" should be handled specially *)
|
||||||
String.split_on_char ',' tgts |>
|
String.split_on_char ',' tgts |>
|
||||||
List.map (fun tgt -> cmd, tgt :: rest)
|
List.map (fun tgt -> cmd, tgt :: rest)
|
||||||
|
|
||||||
|
| "KICK", chan :: tgts :: rest
|
||||||
|
when String.contains tgts ',' ->
|
||||||
|
String.split_on_char ',' tgts |>
|
||||||
|
List.map (fun tgt -> "KICK", chan :: tgt :: rest)
|
||||||
|
|
||||||
| _ ->
|
| _ ->
|
||||||
[cmd, params]
|
[cmd, params]
|
||||||
|
|
||||||
|
|
|
@ -31,5 +31,8 @@ let is_registered t ~router = Hashtbl.mem router.users t.nick_key
|
||||||
let prefix t =
|
let prefix t =
|
||||||
Irc.Msg.User_prefix (t.nick, Some t.userinfo)
|
Irc.Msg.User_prefix (t.nick, Some t.userinfo)
|
||||||
|
|
||||||
|
let membership t =
|
||||||
|
Dllist.fold_r (fun m xs -> m :: xs) t.membership []
|
||||||
|
|
||||||
let channels t =
|
let channels t =
|
||||||
Dllist.fold_r (fun m xs -> m.mem_chan :: xs) t.membership []
|
Dllist.fold_r (fun m xs -> m.mem_chan :: xs) t.membership []
|
||||||
|
|
Loading…
Reference in New Issue