mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-22 16:20:52 +01:00
Add commands for MUC subscriptions management
This commit is contained in:
parent
c4b14d045a
commit
1fc58ace2f
@ -20,6 +20,7 @@
|
||||
change_room_option/4, get_room_options/2,
|
||||
set_room_affiliation/4, get_room_affiliations/2,
|
||||
web_menu_main/2, web_page_main/2, web_menu_host/3,
|
||||
subscribe_room/4, unsubscribe_room/2,
|
||||
web_page_host/3, mod_opt_type/1, get_commands_spec/0]).
|
||||
|
||||
-include("ejabberd.hrl").
|
||||
@ -151,7 +152,17 @@ get_commands_spec() ->
|
||||
{value, string}
|
||||
]}}
|
||||
}}},
|
||||
|
||||
#ejabberd_commands{name = subscribe_room, tags = [muc_room],
|
||||
desc = "Subscribe to a MUC conference",
|
||||
module = ?MODULE, function = subscribe_room,
|
||||
args = [{user, binary}, {nick, binary}, {room, binary},
|
||||
{nodes, binary}],
|
||||
result = {list, {node, string}}},
|
||||
#ejabberd_commands{name = unsubscribe_room, tags = [muc_room],
|
||||
desc = "Unsubscribe from a MUC conference",
|
||||
module = ?MODULE, function = unsubscribe_room,
|
||||
args = [{user, binary}, {room, binary}],
|
||||
result = {res, rescode}},
|
||||
#ejabberd_commands{name = set_room_affiliation, tags = [muc_room],
|
||||
desc = "Change an affiliation in a MUC room",
|
||||
module = ?MODULE, function = set_room_affiliation,
|
||||
@ -884,6 +895,64 @@ set_room_affiliation(Name, Service, JID, AffiliationString) ->
|
||||
error
|
||||
end.
|
||||
|
||||
%%%
|
||||
%%% MUC Subscription
|
||||
%%%
|
||||
|
||||
subscribe_room(_User, Nick, _Room, _Nodes) when Nick == <<"">> ->
|
||||
throw({error, "Nickname must be set"});
|
||||
subscribe_room(User, Nick, Room, Nodes) ->
|
||||
NodeList = re:split(Nodes, "\\h*,\\h*"),
|
||||
case jid:from_string(Room) of
|
||||
#jid{luser = Name, lserver = Host} when Name /= <<"">> ->
|
||||
case jid:from_string(User) of
|
||||
error ->
|
||||
throw({error, "Malformed user JID"});
|
||||
JID ->
|
||||
UserJID = jid:replace_resource(JID, Nick),
|
||||
case get_room_pid(Name, Host) of
|
||||
Pid when is_pid(Pid) ->
|
||||
case gen_fsm:sync_send_all_state_event(
|
||||
Pid,
|
||||
{muc_subscribe, UserJID, Nick, NodeList}) of
|
||||
{ok, SubscribedNodes} ->
|
||||
SubscribedNodes;
|
||||
{error, Reason} ->
|
||||
throw({error, binary_to_list(Reason)})
|
||||
end;
|
||||
_ ->
|
||||
throw({error, "The room does not exist"})
|
||||
end
|
||||
end;
|
||||
_ ->
|
||||
throw({error, "Malformed room JID"})
|
||||
end.
|
||||
|
||||
unsubscribe_room(User, Room) ->
|
||||
case jid:from_string(Room) of
|
||||
#jid{luser = Name, lserver = Host} when Name /= <<"">> ->
|
||||
case jid:from_string(User) of
|
||||
error ->
|
||||
throw({error, "Malformed user JID"});
|
||||
UserJID ->
|
||||
case get_room_pid(Name, Host) of
|
||||
Pid when is_pid(Pid) ->
|
||||
case gen_fsm:sync_send_all_state_event(
|
||||
Pid,
|
||||
{muc_unsubscribe, UserJID}) of
|
||||
ok ->
|
||||
ok;
|
||||
{error, Reason} ->
|
||||
throw({error, binary_to_list(Reason)})
|
||||
end;
|
||||
_ ->
|
||||
throw({error, "The room does not exist"})
|
||||
end
|
||||
end;
|
||||
_ ->
|
||||
throw({error, "Malformed room JID"})
|
||||
end.
|
||||
|
||||
make_opts(StateData) ->
|
||||
Config = StateData#state.config,
|
||||
[
|
||||
|
@ -749,6 +749,60 @@ handle_sync_event({change_state, NewStateData}, _From,
|
||||
handle_sync_event({process_item_change, Item, UJID}, _From, StateName, StateData) ->
|
||||
NSD = process_item_change(Item, StateData, UJID),
|
||||
{reply, {ok, NSD}, StateName, NSD};
|
||||
handle_sync_event({muc_subscribe, From, Nick, Nodes}, _From,
|
||||
StateName, StateData) ->
|
||||
SubEl = #xmlel{name = <<"subscribe">>,
|
||||
attrs = [{<<"xmlns">>, ?NS_MUCSUB}, {<<"nick">>, Nick}],
|
||||
children = [#xmlel{name = <<"event">>,
|
||||
attrs = [{<<"node">>, Node}]}
|
||||
|| Node <- Nodes]},
|
||||
IQ = #iq{type = set, id = randoms:get_string(),
|
||||
xmlns = ?NS_MUCSUB, sub_el = SubEl},
|
||||
Packet = jlib:iq_to_xml(IQ#iq{sub_el = [SubEl]}),
|
||||
Config = StateData#state.config,
|
||||
CaptchaRequired = Config#config.captcha_protected,
|
||||
PasswordProtected = Config#config.password_protected,
|
||||
TmpConfig = Config#config{captcha_protected = false,
|
||||
password_protected = false},
|
||||
TmpState = StateData#state{config = TmpConfig},
|
||||
case process_iq_mucsub(From, Packet, IQ, TmpState) of
|
||||
{result, _, NewState} ->
|
||||
NewConfig = (NewState#state.config)#config{
|
||||
captcha_protected = CaptchaRequired,
|
||||
password_protected = PasswordProtected},
|
||||
{reply, {ok, get_subscription_nodes(Packet)}, StateName,
|
||||
NewState#state{config = NewConfig}};
|
||||
{ignore, NewState} ->
|
||||
NewConfig = (NewState#state.config)#config{
|
||||
captcha_protected = CaptchaRequired,
|
||||
password_protected = PasswordProtected},
|
||||
{reply, {error, <<"Requrest is ignored">>},
|
||||
NewState#state{config = NewConfig}};
|
||||
{error, Err, NewState} ->
|
||||
NewConfig = (NewState#state.config)#config{
|
||||
captcha_protected = CaptchaRequired,
|
||||
password_protected = PasswordProtected},
|
||||
{reply, {error, get_error_text(Err)}, StateName,
|
||||
NewState#state{config = NewConfig}};
|
||||
{error, Err} ->
|
||||
{reply, {error, get_error_text(Err)}, StateName, StateData}
|
||||
end;
|
||||
handle_sync_event({muc_unsubscribe, From}, _From, StateName, StateData) ->
|
||||
SubEl = #xmlel{name = <<"unsubscribe">>,
|
||||
attrs = [{<<"xmlns">>, ?NS_MUCSUB}]},
|
||||
IQ = #iq{type = set, id = randoms:get_string(),
|
||||
xmlns = ?NS_MUCSUB, sub_el = SubEl},
|
||||
Packet = jlib:iq_to_xml(IQ),
|
||||
case process_iq_mucsub(From, Packet, IQ, StateData) of
|
||||
{result, _, NewState} ->
|
||||
{reply, ok, StateName, NewState};
|
||||
{ignore, NewState} ->
|
||||
{reply, {error, <<"Requrest is ignored">>}, NewState};
|
||||
{error, Err, NewState} ->
|
||||
{reply, {error, get_error_text(Err)}, StateName, NewState};
|
||||
{error, Err} ->
|
||||
{reply, {error, get_error_text(Err)}, StateName, StateData}
|
||||
end;
|
||||
handle_sync_event(_Event, _From, StateName,
|
||||
StateData) ->
|
||||
Reply = ok, {reply, Reply, StateName, StateData}.
|
||||
@ -1346,6 +1400,14 @@ get_error_condition2(Packet) ->
|
||||
<- EEls],
|
||||
{condition, Condition}.
|
||||
|
||||
get_error_text(Error) ->
|
||||
case fxml:get_subtag_with_xmlns(Error, <<"text">>, ?NS_STANZAS) of
|
||||
#xmlel{} = Tag ->
|
||||
fxml:get_tag_cdata(Tag);
|
||||
false ->
|
||||
<<"">>
|
||||
end.
|
||||
|
||||
make_reason(Packet, From, StateData, Reason1) ->
|
||||
{ok, #user{nick = FromNick}} = (?DICT):find(jid:tolower(From), StateData#state.users),
|
||||
Condition = get_error_condition(Packet),
|
||||
@ -4608,6 +4670,18 @@ process_iq_mucsub(From, _Packet,
|
||||
NewStateData = remove_subscription(From, User, StateData),
|
||||
store_room(NewStateData),
|
||||
{result, [], NewStateData};
|
||||
error when From#jid.lresource == <<"">> ->
|
||||
{LUser, LServer, _} = LJID,
|
||||
NewStateData =
|
||||
dict:fold(
|
||||
fun({U, S, _}, #user{jid = J, is_subscriber = true} = User,
|
||||
AccState) when U == LUser, S == LServer ->
|
||||
remove_subscription(J, User, AccState);
|
||||
(_, _, AccState) ->
|
||||
AccState
|
||||
end, StateData, StateData#state.users),
|
||||
store_room(NewStateData),
|
||||
{result, [], NewStateData};
|
||||
_ ->
|
||||
{result, [], StateData}
|
||||
end;
|
||||
|
Loading…
Reference in New Issue
Block a user