From aa5caa30e27030cd7813d47b0fda13615f793846 Mon Sep 17 00:00:00 2001 From: Alexey Shchepin Date: Thu, 12 Nov 2015 19:51:20 +0300 Subject: [PATCH] Support for muc#roomconfig_presencebroadcast option --- include/mod_muc_room.hrl | 2 + src/mod_muc_room.erl | 111 ++++++++++++++++++++++++++++++++++----- 2 files changed, 100 insertions(+), 13 deletions(-) diff --git a/include/mod_muc_room.hrl b/include/mod_muc_room.hrl index c90a5c028..51e575db0 100644 --- a/include/mod_muc_room.hrl +++ b/include/mod_muc_room.hrl @@ -56,6 +56,8 @@ password_protected = false :: boolean(), password = <<"">> :: binary(), anonymous = true :: boolean(), + presence_broadcast = [moderator, participant, visitor] :: + [moderator | participant | visitor], allow_voice_requests = true :: boolean(), voice_request_min_interval = 1800 :: non_neg_integer(), max_users = ?MAX_USERS_DEFAULT :: non_neg_integer() | none, diff --git a/src/mod_muc_room.erl b/src/mod_muc_room.erl index dcf276b8b..0572bca2e 100644 --- a/src/mod_muc_room.erl +++ b/src/mod_muc_room.erl @@ -363,7 +363,8 @@ normal_state({route, From, <<"">>, catch send_new_presence(TargetJid, Reason, - NSD), + NSD, + StateData), NSD; _ -> StateData end @@ -1031,7 +1032,7 @@ process_presence(From, Nick, StateData), case (?DICT):find(Nick, StateData#state.nicks) of {ok, [_, _ | _]} -> ok; - _ -> send_new_presence(From, NewState) + _ -> send_new_presence(From, NewState, StateData) end, Reason = case xml:get_subtag(NewPacket, <<"status">>) @@ -1109,7 +1110,8 @@ process_presence(From, Nick, end, NewState = add_user_presence(From, Stanza, StateData), - send_new_presence(From, NewState), + send_new_presence( + From, NewState, StateData), NewState end end @@ -1315,7 +1317,7 @@ expulse_participant(Packet, From, StateData, Reason1) -> [{xmlcdata, Reason2}]}]}, StateData), - send_new_presence(From, NewState), + send_new_presence(From, NewState, StateData), remove_online_user(From, NewState). set_affiliation(JID, Affiliation, StateData) -> @@ -1839,7 +1841,7 @@ add_new_user(From, Nick, add_online_user(From, Nick, Role, StateData)), send_existing_presences(From, NewState), - send_new_presence(From, NewState), + send_new_presence(From, NewState, StateData), Shift = count_stanza_shift(Nick, Els, NewState), case send_history(From, Shift, NewState) of true -> ok; @@ -2070,6 +2072,10 @@ is_room_overcrowded(StateData) -> ?DEFAULT_MAX_USERS_PRESENCE), (?DICT):size(StateData#state.users) > MaxUsersPresence. +presence_broadcast_allowed(JID, StateData) -> + Role = get_role(JID, StateData), + lists:member(Role, (StateData#state.config)#config.presence_broadcast). + send_update_presence(JID, StateData) -> send_update_presence(JID, <<"">>, StateData). @@ -2097,15 +2103,17 @@ send_update_presence1(JID, Reason, StateData) -> end end, lists:foreach(fun (J) -> - send_new_presence(J, Reason, StateData) + send_new_presence(J, Reason, StateData, StateData) end, LJIDs). -send_new_presence(NJID, StateData) -> - send_new_presence(NJID, <<"">>, StateData). +send_new_presence(NJID, StateData, OldStateData) -> + send_new_presence(NJID, <<"">>, StateData, OldStateData). -send_new_presence(NJID, Reason, StateData) -> - case is_room_overcrowded(StateData) of +send_new_presence(NJID, Reason, StateData, OldStateData) -> + case is_room_overcrowded(StateData) orelse + not (presence_broadcast_allowed(NJID, StateData) orelse + presence_broadcast_allowed(NJID, OldStateData)) of true -> ok; false -> send_new_presence1(NJID, Reason, StateData) end. @@ -2289,8 +2297,12 @@ change_nick(JID, Nick, StateData) -> end, NewStateData = StateData#state{users = Users, nicks = Nicks}, - send_nick_changing(JID, OldNick, NewStateData, - SendOldUnavailable, SendNewAvailable), + case presence_broadcast_allowed(JID, NewStateData) of + true -> + send_nick_changing(JID, OldNick, NewStateData, + SendOldUnavailable, SendNewAvailable); + false -> ok + end, add_to_log(nickchange, {OldNick, Nick}, StateData), NewStateData. @@ -2666,7 +2678,7 @@ process_item_change(E, SD, UJID) -> {JID, role, Role, Reason} -> SD1 = set_role(JID, Role, SD), catch - send_new_presence(JID, Reason, SD1), + send_new_presence(JID, Reason, SD1, SD), SD1; {JID, affiliation, A, _Reason} -> SD1 = set_affiliation(JID, A, SD), @@ -3406,6 +3418,53 @@ get_config(Lang, StateData, From) -> children = [{xmlcdata, <<"anyone">>}]}]}]}, + #xmlel{name = <<"field">>, + attrs = + [{<<"type">>, <<"list-multi">>}, + {<<"label">>, + translate:translate(Lang, + <<"Roles for which Presence is Broadcasted">>)}, + {<<"var">>, <<"muc#roomconfig_presencebroadcast">>}], + children = + lists:map( + fun(Role) -> + #xmlel{name = <<"value">>, attrs = [], + children = + [{xmlcdata, + atom_to_binary(Role, utf8)}]} + end, Config#config.presence_broadcast + ) ++ + [#xmlel{name = <<"option">>, + attrs = + [{<<"label">>, + translate:translate(Lang, + <<"Moderator">>)}], + children = + [#xmlel{name = <<"value">>, attrs = [], + children = + [{xmlcdata, + <<"moderator">>}]}]}, + #xmlel{name = <<"option">>, + attrs = + [{<<"label">>, + translate:translate(Lang, + <<"Participant">>)}], + children = + [#xmlel{name = <<"value">>, attrs = [], + children = + [{xmlcdata, + <<"participant">>}]}]}, + #xmlel{name = <<"option">>, + attrs = + [{<<"label">>, + translate:translate(Lang, + <<"Visitor">>)}], + children = + [#xmlel{name = <<"value">>, attrs = [], + children = + [{xmlcdata, + <<"visitor">>}]}]} + ]}, ?BOOLXFIELD(<<"Make room members-only">>, <<"muc#roomconfig_membersonly">>, (Config#config.members_only)), @@ -3679,6 +3738,28 @@ set_xoption([{<<"muc#roomconfig_roomsecret">>, [Val]} set_xoption([{<<"anonymous">>, [Val]} | Opts], Config) -> ?SET_BOOL_XOPT(anonymous, Val); +set_xoption([{<<"muc#roomconfig_presencebroadcast">>, Vals} | Opts], + Config) -> + Roles = + lists:foldl( + fun(_S, error) -> error; + (S, {M, P, V}) -> + case S of + <<"moderator">> -> {true, P, V}; + <<"participant">> -> {M, true, V}; + <<"visitor">> -> {M, P, true}; + _ -> error + end + end, {false, false, false}, Vals), + case Roles of + error -> {error, ?ERR_BAD_REQUEST}; + {M, P, V} -> + Res = + if M -> [moderator]; true -> [] end ++ + if P -> [participant]; true -> [] end ++ + if V -> [visitor]; true -> [] end, + set_xoption(Opts, Config#config{presence_broadcast = Res}) + end; set_xoption([{<<"muc#roomconfig_allowvoicerequests">>, [Val]} | Opts], @@ -3872,6 +3953,10 @@ set_opts([{Opt, Val} | Opts], StateData) -> StateData#state{config = (StateData#state.config)#config{anonymous = Val}}; + presence_broadcast -> + StateData#state{config = + (StateData#state.config)#config{presence_broadcast = + Val}}; logging -> StateData#state{config = (StateData#state.config)#config{logging =