aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ejabberd_ctl.erl6
-rw-r--r--src/mod_http_api.erl1
-rw-r--r--src/mod_muc.erl4
-rw-r--r--src/mod_muc_admin.erl44
-rw-r--r--src/mod_muc_admin_opt.erl13
-rw-r--r--src/mod_muc_room.erl18
6 files changed, 80 insertions, 6 deletions
diff --git a/src/ejabberd_ctl.erl b/src/ejabberd_ctl.erl
index 354e5ba2f..77595cd54 100644
--- a/src/ejabberd_ctl.erl
+++ b/src/ejabberd_ctl.erl
@@ -378,7 +378,11 @@ format_arg("", string) ->
format_arg(Arg, string) ->
NumChars = integer_to_list(length(Arg)),
Parse = "~" ++ NumChars ++ "c",
- format_arg2(Arg, Parse).
+ format_arg2(Arg, Parse);
+format_arg(Arg, Format) ->
+ S = unicode:characters_to_binary(Arg, utf8),
+ JSON = jiffy:decode(S),
+ mod_http_api:format_arg(JSON, Format).
format_arg2(Arg, Parse)->
{ok, [Arg2], _RemainingArguments} = io_lib:fread(Parse, Arg),
diff --git a/src/mod_http_api.erl b/src/mod_http_api.erl
index 427833584..023df39ca 100644
--- a/src/mod_http_api.erl
+++ b/src/mod_http_api.erl
@@ -30,6 +30,7 @@
-behaviour(gen_mod).
-export([start/2, stop/1, reload/3, process/2, depends/2,
+ format_arg/2,
mod_options/1, mod_doc/0]).
-include_lib("xmpp/include/xmpp.hrl").
diff --git a/src/mod_muc.erl b/src/mod_muc.erl
index 2853632cc..72f386b00 100644
--- a/src/mod_muc.erl
+++ b/src/mod_muc.erl
@@ -1143,9 +1143,9 @@ remove_user(User, Server) ->
fun(Host) ->
lists:foreach(
fun({_, _, Pid}) ->
- mod_muc_room:change_item(
+ mod_muc_room:change_item_async(
Pid, JID, affiliation, none, <<"User removed">>),
- mod_muc_room:change_item(
+ mod_muc_room:change_item_async(
Pid, JID, role, none, <<"User removed">>)
end,
get_online_rooms(LServer, Host))
diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl
index 9952abd27..21611c585 100644
--- a/src/mod_muc_admin.erl
+++ b/src/mod_muc_admin.erl
@@ -40,8 +40,11 @@
change_room_option/4, get_room_options/2,
set_room_affiliation/4, get_room_affiliations/2, get_room_affiliation/3,
web_menu_main/2, web_page_main/2, web_menu_host/3,
- subscribe_room/4, unsubscribe_room/2, get_subscribers/2,
- web_page_host/3, mod_options/1, get_commands_spec/0, find_hosts/1]).
+ subscribe_room/4, subscribe_room_many/3,
+ unsubscribe_room/2, get_subscribers/2,
+ web_page_host/3,
+ mod_opt_type/1, mod_options/1,
+ get_commands_spec/0, find_hosts/1]).
-include("logger.hrl").
-include_lib("xmpp/include/xmpp.hrl").
@@ -331,6 +334,25 @@ get_commands_spec() ->
args = [{user, binary}, {nick, binary}, {room, binary},
{nodes, binary}],
result = {nodes, {list, {node, string}}}},
+ #ejabberd_commands{name = subscribe_room_many, tags = [muc_room],
+ desc = "Subscribe several users to a MUC conference",
+ module = ?MODULE, function = subscribe_room_many,
+ args_desc = ["Users JIDs and nicks",
+ "the room to subscribe",
+ "nodes separated by commas: ,"],
+ args_example = [[{"tom@localhost", "Tom"},
+ {"jerry@localhost", "Jerry"}],
+ "room1@conference.localhost",
+ "urn:xmpp:mucsub:nodes:messages,urn:xmpp:mucsub:nodes:affiliations"],
+ args = [{users, {list,
+ {user, {tuple,
+ [{jid, binary},
+ {nick, binary}
+ ]}}
+ }},
+ {room, binary},
+ {nodes, binary}],
+ result = {res, rescode}},
#ejabberd_commands{name = unsubscribe_room, tags = [muc_room],
desc = "Unsubscribe from a MUC conference",
module = ?MODULE, function = unsubscribe_room,
@@ -1331,6 +1353,18 @@ subscribe_room(User, Nick, Room, Nodes) ->
throw({error, "Malformed room JID"})
end.
+subscribe_room_many(Users, Room, Nodes) ->
+ MaxUsers = mod_muc_admin_opt:subscribe_room_many_max_users(global),
+ if
+ length(Users) > MaxUsers ->
+ throw({error, "Too many users in subscribe_room_many command"});
+ true ->
+ lists:foreach(
+ fun({User, Nick}) ->
+ subscribe_room(User, Nick, Room, Nodes)
+ end, Users)
+ end.
+
unsubscribe_room(User, Room) ->
try jid:decode(Room) of
#jid{luser = Name, lserver = Host} when Name /= <<"">> ->
@@ -1413,7 +1447,11 @@ find_hosts(ServerHost) ->
[]
end.
-mod_options(_) -> [].
+mod_opt_type(subscribe_room_many_max_users) ->
+ econf:int().
+
+mod_options(_) ->
+ [{subscribe_room_many_max_users, 50}].
mod_doc() ->
#{desc =>
diff --git a/src/mod_muc_admin_opt.erl b/src/mod_muc_admin_opt.erl
new file mode 100644
index 000000000..18ca64af7
--- /dev/null
+++ b/src/mod_muc_admin_opt.erl
@@ -0,0 +1,13 @@
+%% Generated automatically
+%% DO NOT EDIT: run `make options` instead
+
+-module(mod_muc_admin_opt).
+
+-export([subscribe_room_many_max_users/1]).
+
+-spec subscribe_room_many_max_users(gen_mod:opts() | global | binary()) -> integer().
+subscribe_room_many_max_users(Opts) when is_map(Opts) ->
+ gen_mod:get_opt(subscribe_room_many_max_users, Opts);
+subscribe_room_many_max_users(Host) ->
+ gen_mod:get_module_opt(Host, mod_muc_admin, subscribe_room_many_max_users).
+
diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl
index ec1c551e4..25bc7d8b6 100644
--- a/src/mod_muc_room.erl
+++ b/src/mod_muc_room.erl
@@ -50,6 +50,7 @@
set_config/2,
get_state/1,
change_item/5,
+ change_item_async/5,
config_reloaded/1,
subscribe/4,
unsubscribe/2,
@@ -202,6 +203,11 @@ change_item(Pid, JID, Type, AffiliationOrRole, Reason) ->
{error, notfound}
end.
+-spec change_item_async(pid(), jid(), affiliation | role, affiliation() | role(), binary()) -> ok.
+change_item_async(Pid, JID, Type, AffiliationOrRole, Reason) ->
+ p1_fsm:send_all_state_event(
+ Pid, {process_item_change, {JID, Type, AffiliationOrRole, Reason}, undefined}).
+
-spec get_state(pid()) -> {ok, state()} | {error, notfound | timeout}.
get_state(Pid) ->
try p1_fsm:sync_send_all_state_event(Pid, get_state)
@@ -675,6 +681,16 @@ handle_event({set_affiliations, Affiliations},
StateName, StateData) ->
NewStateData = set_affiliations(Affiliations, StateData),
{next_state, StateName, NewStateData};
+handle_event({process_item_change, Item, UJID}, StateName, StateData) ->
+ case process_item_change(Item, StateData, UJID) of
+ {error, _} ->
+ {next_state, StateName, StateData};
+ StateData ->
+ {next_state, StateName, StateData};
+ NSD ->
+ store_room(NSD),
+ {next_state, StateName, NSD}
+ end;
handle_event(_Event, StateName, StateData) ->
{next_state, StateName, StateData}.
@@ -723,6 +739,8 @@ handle_sync_event({process_item_change, Item, UJID}, _From, StateName, StateData
case process_item_change(Item, StateData, UJID) of
{error, _} = Err ->
{reply, Err, StateName, StateData};
+ StateData ->
+ {reply, {ok, StateData}, StateName, StateData};
NSD ->
store_room(NSD),
{reply, {ok, NSD}, StateName, NSD}