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 =
|
let fail fmt =
|
||||||
Format.kasprintf (fun _ -> raise Error) fmt
|
Format.kasprintf (fun _ -> raise Error) fmt
|
||||||
|
|
||||||
type user_modes = Set.change
|
|
||||||
|
|
||||||
let parse_mode_set str ~of_char ~add ~rem ~init =
|
let parse_mode_set str ~of_char ~add ~rem ~init =
|
||||||
let rec loop dir acc i =
|
let rec loop dir acc i =
|
||||||
if i >= String.length str then acc
|
if i >= String.length str then acc
|
||||||
|
@ -142,6 +140,17 @@ module Parse = struct
|
||||||
in
|
in
|
||||||
loop `none init 0
|
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 =
|
let user_modes str =
|
||||||
parse_mode_set str
|
parse_mode_set str
|
||||||
~of_char:of_char_user
|
~of_char:of_char_user
|
||||||
|
@ -157,13 +166,20 @@ module Parse = struct
|
||||||
chan_modes : Set.change;
|
chan_modes : Set.change;
|
||||||
chan_key : (string, string) set_or_unset option;
|
chan_key : (string, string) set_or_unset option;
|
||||||
chan_limit : (int, unit) 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
|
let chan_modes_add (args, modes) = function
|
||||||
| #chan_a -> fail "TODO: + type A modes"
|
| `k ->
|
||||||
| #chan_b -> fail "TODO: + type B modes"
|
(* type B *)
|
||||||
| #chan_c -> fail "TODO: + type C modes"
|
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 ->
|
| #chan_d as m ->
|
||||||
let chan_modes = {
|
let chan_modes = {
|
||||||
Set.add = Set.add m modes.chan_modes.add;
|
Set.add = Set.add m modes.chan_modes.add;
|
||||||
|
@ -172,9 +188,16 @@ module Parse = struct
|
||||||
args, { modes with chan_modes }
|
args, { modes with chan_modes }
|
||||||
|
|
||||||
let chan_modes_rem (args, modes) = function
|
let chan_modes_rem (args, modes) = function
|
||||||
| #chan_a -> fail "TODO: - type A modes"
|
| `k ->
|
||||||
| #chan_b -> fail "TODO: - type B modes"
|
(* type B *)
|
||||||
| #chan_c -> fail "TODO: - type C modes"
|
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 ->
|
| #chan_d as m ->
|
||||||
let chan_modes = {
|
let chan_modes = {
|
||||||
Set.add = Set.remove m modes.chan_modes.add;
|
Set.add = Set.remove m modes.chan_modes.add;
|
||||||
|
@ -187,7 +210,6 @@ module Parse = struct
|
||||||
chan_modes = Set.no_change;
|
chan_modes = Set.no_change;
|
||||||
chan_key = None;
|
chan_key = None;
|
||||||
chan_limit = None;
|
chan_limit = None;
|
||||||
chan_priv = [];
|
|
||||||
} in
|
} in
|
||||||
let _, modes =
|
let _, modes =
|
||||||
parse_mode_set str
|
parse_mode_set str
|
||||||
|
@ -196,7 +218,7 @@ module Parse = struct
|
||||||
~add:chan_modes_add
|
~add:chan_modes_add
|
||||||
~rem:chan_modes_rem
|
~rem:chan_modes_rem
|
||||||
in
|
in
|
||||||
{ modes with chan_priv = List.rev modes.chan_priv }
|
modes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ module Parse : sig
|
||||||
chan_modes : Set.change;
|
chan_modes : Set.change;
|
||||||
chan_key : (string, string) set_or_unset option;
|
chan_key : (string, string) set_or_unset option;
|
||||||
chan_limit : (int, unit) 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
|
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 notregistered = "451", ["You have not registered"]
|
||||||
let needmoreparams cmd = "461", [cmd; "Not enough parameters"]
|
let needmoreparams cmd = "461", [cmd; "Not enough parameters"]
|
||||||
let alreadyregistered = "462", ["Unauthorized command (already registered)"]
|
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_set = "502", ["Can't change mode for other users"]
|
||||||
let usersdontmatch_get = "502", ["Can't view 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;
|
Chan.set_mode chan mode;
|
||||||
end
|
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 on_get_user_mode user me =
|
||||||
let* () = if user != me then Error usersdontmatch_get else Ok () in
|
let* () = if user != me then Error usersdontmatch_get else Ok () in
|
||||||
Ok [
|
Ok [
|
||||||
|
@ -289,12 +320,23 @@ let on_set_user_mode user me modestr _args =
|
||||||
Ok []
|
Ok []
|
||||||
|
|
||||||
let on_get_chan_mode chan _me =
|
let on_get_chan_mode chan _me =
|
||||||
Ok [
|
let rpls =[
|
||||||
"324", [Chan.name chan; Fmt.str "+%a" Irc.Mode.Set.pp (Chan.mode chan)];
|
["324", [Chan.name chan; Fmt.str "+%a" Irc.Mode.Set.pp (Chan.mode chan)]];
|
||||||
(* TODO: +k *)
|
|
||||||
(* TODO: +l *)
|
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) *)
|
(* TODO: RPL_CREATIONTIME (329) *)
|
||||||
]
|
] in
|
||||||
|
Ok (List.flatten rpls)
|
||||||
|
|
||||||
let on_set_chan_mode chan me modestr args =
|
let on_set_chan_mode chan me modestr args =
|
||||||
(* TODO: If <modestring> is given, the user sending the command MUST have appropriate
|
(* 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
|
Error modeunknownflag
|
||||||
in
|
in
|
||||||
|
|
||||||
set_chan_mode chan chg.chan_modes ~from:me;
|
set_chan_mode chan ~from:me chg.chan_modes;
|
||||||
(* TODO: chg.chan_key *)
|
Option.iter (set_chan_key chan ~from:me) chg.chan_key;
|
||||||
(* TODO: chg.chan_limit *)
|
Option.iter (set_chan_limit chan ~from:me) chg.chan_limit;
|
||||||
(* TODO: chg.chan_priv *)
|
|
||||||
|
(* TODO: chg.chan_ban/op/voice *)
|
||||||
|
|
||||||
Ok []
|
Ok []
|
||||||
|
|
||||||
|
|
|
@ -20,9 +20,9 @@ and chan = {
|
||||||
mutable topic : string option;
|
mutable topic : string option;
|
||||||
mutable members : membership Dllist.t;
|
mutable members : membership Dllist.t;
|
||||||
mutable chan_mode : Irc.Mode.Set.t; (* +imstn *)
|
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: +b, +o, +v *)
|
||||||
(* TODO: +k *)
|
|
||||||
(* TODO: +l *)
|
|
||||||
(* TODO: creation time *)
|
(* TODO: creation time *)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,6 +135,8 @@ module Chan = struct
|
||||||
topic = None;
|
topic = None;
|
||||||
members = Dllist.create ();
|
members = Dllist.create ();
|
||||||
chan_mode = Irc.Mode.Set.empty;
|
chan_mode = Irc.Mode.Set.empty;
|
||||||
|
chan_limit = None;
|
||||||
|
chan_key = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let name t = t.name
|
let name t = t.name
|
||||||
|
@ -143,6 +145,10 @@ module Chan = struct
|
||||||
let no_members t = Dllist.is_empty t.members
|
let no_members t = Dllist.is_empty t.members
|
||||||
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 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 =
|
let register t ~router =
|
||||||
Hashtbl.replace router.channels t.name_key t
|
Hashtbl.replace router.channels t.name_key t
|
||||||
|
|
Loading…
Reference in New Issue