parse and set +k/+l flags
This commit is contained in:
parent
3641f4c773
commit
7372227578
|
@ -122,8 +122,6 @@ module Parse = struct
|
|||
let fail fmt =
|
||||
Format.kasprintf (fun _ -> raise Error) fmt
|
||||
|
||||
type user_modes = Set.change
|
||||
|
||||
let parse_mode_set str ~of_char ~add ~rem ~init =
|
||||
let rec loop dir acc i =
|
||||
if i >= String.length str then acc
|
||||
|
@ -142,6 +140,17 @@ module Parse = struct
|
|||
in
|
||||
loop `none init 0
|
||||
|
||||
let take = function
|
||||
| [] -> fail "expected argument"
|
||||
| x :: xs -> x, xs
|
||||
|
||||
let take_int = function
|
||||
| [] -> fail "expected argument"
|
||||
| x :: xs -> try int_of_string x, xs
|
||||
with Invalid_argument _ -> fail "invalid integer"
|
||||
|
||||
type user_modes = Set.change
|
||||
|
||||
let user_modes str =
|
||||
parse_mode_set str
|
||||
~of_char:of_char_user
|
||||
|
@ -157,13 +166,20 @@ module Parse = struct
|
|||
chan_modes : Set.change;
|
||||
chan_key : (string, string) set_or_unset option;
|
||||
chan_limit : (int, unit) set_or_unset option;
|
||||
chan_priv : (chan_b * (string, string) set_or_unset) list;
|
||||
}
|
||||
|
||||
let chan_modes_add (args, modes) = function
|
||||
| #chan_a -> fail "TODO: + type A modes"
|
||||
| #chan_b -> fail "TODO: + type B modes"
|
||||
| #chan_c -> fail "TODO: + type C modes"
|
||||
| `k ->
|
||||
(* type B *)
|
||||
let key, args = take args in
|
||||
let chan_key = Some (Set key) in
|
||||
args, { modes with chan_key }
|
||||
| `l ->
|
||||
(* type C *)
|
||||
let lim, args = take_int args in
|
||||
let chan_limit = Some (Set lim) in
|
||||
args, { modes with chan_limit }
|
||||
| `b | `o | `v -> fail "TODO: + ban/op/voice"
|
||||
| #chan_d as m ->
|
||||
let chan_modes = {
|
||||
Set.add = Set.add m modes.chan_modes.add;
|
||||
|
@ -172,9 +188,16 @@ module Parse = struct
|
|||
args, { modes with chan_modes }
|
||||
|
||||
let chan_modes_rem (args, modes) = function
|
||||
| #chan_a -> fail "TODO: - type A modes"
|
||||
| #chan_b -> fail "TODO: - type B modes"
|
||||
| #chan_c -> fail "TODO: - type C modes"
|
||||
| `k ->
|
||||
(* type B *)
|
||||
let key, args = take args in
|
||||
let chan_key = Some (Unset key) in
|
||||
args, { modes with chan_key }
|
||||
| `l ->
|
||||
(* type C *)
|
||||
let chan_limit = Some (Unset ()) in
|
||||
args, { modes with chan_limit }
|
||||
| `b | `o | `v -> fail "TODO: - ban/op/voice"
|
||||
| #chan_d as m ->
|
||||
let chan_modes = {
|
||||
Set.add = Set.remove m modes.chan_modes.add;
|
||||
|
@ -187,7 +210,6 @@ module Parse = struct
|
|||
chan_modes = Set.no_change;
|
||||
chan_key = None;
|
||||
chan_limit = None;
|
||||
chan_priv = [];
|
||||
} in
|
||||
let _, modes =
|
||||
parse_mode_set str
|
||||
|
@ -196,7 +218,7 @@ module Parse = struct
|
|||
~add:chan_modes_add
|
||||
~rem:chan_modes_rem
|
||||
in
|
||||
{ modes with chan_priv = List.rev modes.chan_priv }
|
||||
modes
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ module Parse : sig
|
|||
chan_modes : Set.change;
|
||||
chan_key : (string, string) set_or_unset option;
|
||||
chan_limit : (int, unit) set_or_unset option;
|
||||
chan_priv : (chan_b * (string, string) set_or_unset) list;
|
||||
(* TODO: bad, op, voice *)
|
||||
}
|
||||
|
||||
val user_modes : string -> user_modes
|
||||
|
|
|
@ -74,7 +74,7 @@ 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"]
|
||||
let alreadyregistered = "462", ["Unauthorized command (already registered)"]
|
||||
let modeunknownflag = "501", ["Unknown MODE flag"]
|
||||
let modeunknownflag = "501", ["Didn't understand MODE command"]
|
||||
let usersdontmatch_set = "502", ["Can't change mode for other users"]
|
||||
let usersdontmatch_get = "502", ["Can't view mode for other users"]
|
||||
|
||||
|
@ -270,6 +270,37 @@ let set_chan_mode chan ~from chg =
|
|||
Chan.set_mode chan mode;
|
||||
end
|
||||
|
||||
let set_chan_key chan ~from = function
|
||||
| Irc.Mode.Parse.Set key ->
|
||||
let msg = Irc.Msg.make "MODE" [Chan.name chan; "+k"; key] ~always_trailing:true in
|
||||
begin
|
||||
Router.relay msg ~from [`to_chan chan; `to_self];
|
||||
Chan.set_key chan (Some key);
|
||||
end
|
||||
| Irc.Mode.Parse.Unset _key ->
|
||||
if Chan.key chan <> None then
|
||||
let msg = Irc.Msg.make "MODE" [Chan.name chan; "-k"; "*"] in
|
||||
begin
|
||||
Router.relay msg ~from [`to_chan chan; `to_self];
|
||||
Chan.set_key chan None;
|
||||
end
|
||||
|
||||
let set_chan_limit chan ~from = function
|
||||
| Irc.Mode.Parse.Set lim ->
|
||||
if Chan.limit chan <> Some lim then
|
||||
let msg = Irc.Msg.make "MODE" [Chan.name chan; "+l"; string_of_int lim] in
|
||||
begin
|
||||
Router.relay msg ~from [`to_chan chan; `to_self];
|
||||
Chan.set_limit chan (Some lim);
|
||||
end
|
||||
| Irc.Mode.Parse.Unset () ->
|
||||
if Chan.limit chan <> None then
|
||||
let msg = Irc.Msg.make "MODE" [Chan.name chan; "-l"] in
|
||||
begin
|
||||
Router.relay msg ~from [`to_chan chan; `to_self];
|
||||
Chan.set_limit chan None;
|
||||
end
|
||||
|
||||
let on_get_user_mode user me =
|
||||
let* () = if user != me then Error usersdontmatch_get else Ok () in
|
||||
Ok [
|
||||
|
@ -289,12 +320,23 @@ let on_set_user_mode user me modestr _args =
|
|||
Ok []
|
||||
|
||||
let on_get_chan_mode chan _me =
|
||||
Ok [
|
||||
"324", [Chan.name chan; Fmt.str "+%a" Irc.Mode.Set.pp (Chan.mode chan)];
|
||||
(* TODO: +k *)
|
||||
(* TODO: +l *)
|
||||
let rpls =[
|
||||
["324", [Chan.name chan; Fmt.str "+%a" Irc.Mode.Set.pp (Chan.mode chan)]];
|
||||
|
||||
begin match Chan.limit chan with
|
||||
| Some lim -> ["324", [Chan.name chan; "+l"; string_of_int lim]]
|
||||
| None -> []
|
||||
end;
|
||||
|
||||
(* TODO: only display key if priveledged enough to see it *)
|
||||
begin match Chan.key chan with
|
||||
| Some key -> ["324", [Chan.name chan; "+k"; key]]
|
||||
| None -> []
|
||||
end;
|
||||
|
||||
(* TODO: RPL_CREATIONTIME (329) *)
|
||||
]
|
||||
] in
|
||||
Ok (List.flatten rpls)
|
||||
|
||||
let on_set_chan_mode chan me modestr args =
|
||||
(* TODO: If <modestring> is given, the user sending the command MUST have appropriate
|
||||
|
@ -311,10 +353,11 @@ let on_set_chan_mode chan me modestr args =
|
|||
Error modeunknownflag
|
||||
in
|
||||
|
||||
set_chan_mode chan chg.chan_modes ~from:me;
|
||||
(* TODO: chg.chan_key *)
|
||||
(* TODO: chg.chan_limit *)
|
||||
(* TODO: chg.chan_priv *)
|
||||
set_chan_mode chan ~from:me chg.chan_modes;
|
||||
Option.iter (set_chan_key chan ~from:me) chg.chan_key;
|
||||
Option.iter (set_chan_limit chan ~from:me) chg.chan_limit;
|
||||
|
||||
(* TODO: chg.chan_ban/op/voice *)
|
||||
|
||||
Ok []
|
||||
|
||||
|
|
|
@ -20,9 +20,9 @@ and chan = {
|
|||
mutable topic : string option;
|
||||
mutable members : membership Dllist.t;
|
||||
mutable chan_mode : Irc.Mode.Set.t; (* +imstn *)
|
||||
mutable chan_limit : int option; (* +l *)
|
||||
mutable chan_key : string option; (* +k *)
|
||||
(* TODO: +b, +o, +v *)
|
||||
(* TODO: +k *)
|
||||
(* TODO: +l *)
|
||||
(* TODO: creation time *)
|
||||
}
|
||||
|
||||
|
@ -135,6 +135,8 @@ module Chan = struct
|
|||
topic = None;
|
||||
members = Dllist.create ();
|
||||
chan_mode = Irc.Mode.Set.empty;
|
||||
chan_limit = None;
|
||||
chan_key = None;
|
||||
}
|
||||
|
||||
let name t = t.name
|
||||
|
@ -143,6 +145,10 @@ module Chan = struct
|
|||
let no_members t = Dllist.is_empty t.members
|
||||
let mode t = t.chan_mode
|
||||
let set_mode t new_mode = t.chan_mode <- new_mode
|
||||
let limit t = t.chan_limit
|
||||
let set_limit t n = t.chan_limit <- n
|
||||
let key t = t.chan_key
|
||||
let set_key t k = t.chan_key <- k
|
||||
|
||||
let register t ~router =
|
||||
Hashtbl.replace router.channels t.name_key t
|
||||
|
|
Loading…
Reference in New Issue