Trigger PEP notifications on CAPS updates

Let mod_pubsub send last items whenever a contact updates the entity
capabilities.  This was already done for remote contacts and is now also
done for local contacts.
This commit is contained in:
Holger Weiss 2015-07-07 00:24:06 +02:00
parent edb18deb8f
commit 0f96414279
2 changed files with 33 additions and 29 deletions

View File

@ -243,27 +243,24 @@ c2s_presence_in(C2SState,
error -> gb_trees:empty() error -> gb_trees:empty()
end, end,
Caps = read_caps(Els), Caps = read_caps(Els),
{CapsUpdated, NewRs} = case Caps of NewRs = case Caps of
nothing when Insert == true -> {false, Rs}; nothing when Insert == true -> Rs;
_ when Insert == true -> _ when Insert == true ->
case gb_trees:lookup(LFrom, Rs) of case gb_trees:lookup(LFrom, Rs) of
{value, Caps} -> {false, Rs}; {value, Caps} -> Rs;
none -> none ->
{true, ejabberd_hooks:run(caps_add, To#jid.lserver,
gb_trees:insert(LFrom, Caps, [From, To,
Rs)}; get_features(To#jid.lserver, Caps)]),
_ -> gb_trees:insert(LFrom, Caps, Rs);
{true, _ ->
gb_trees:update(LFrom, Caps, Rs)} ejabberd_hooks:run(caps_update, To#jid.lserver,
end; [From, To,
_ -> {false, gb_trees:delete_any(LFrom, Rs)} get_features(To#jid.lserver, Caps)]),
end, gb_trees:update(LFrom, Caps, Rs)
if CapsUpdated -> end;
ejabberd_hooks:run(caps_update, To#jid.lserver, _ -> gb_trees:delete_any(LFrom, Rs)
[From, To, end,
get_features(To#jid.lserver, Caps)]);
true -> ok
end,
ejabberd_c2s:set_aux_field(caps_resources, NewRs, ejabberd_c2s:set_aux_field(caps_resources, NewRs,
C2SState); C2SState);
true -> C2SState true -> C2SState

View File

@ -62,7 +62,7 @@
-define(PEPNODE, <<"pep">>). -define(PEPNODE, <<"pep">>).
%% exports for hooks %% exports for hooks
-export([presence_probe/3, caps_update/3, -export([presence_probe/3, caps_add/3, caps_update/3,
in_subscription/6, out_subscription/4, in_subscription/6, out_subscription/4,
on_user_offline/3, remove_user/2, on_user_offline/3, remove_user/2,
disco_local_identity/5, disco_local_features/5, disco_local_identity/5, disco_local_features/5,
@ -293,6 +293,8 @@ init([ServerHost, Opts]) ->
?MODULE, remove_user, 50), ?MODULE, remove_user, 50),
case lists:member(?PEPNODE, Plugins) of case lists:member(?PEPNODE, Plugins) of
true -> true ->
ejabberd_hooks:add(caps_add, ServerHost,
?MODULE, caps_add, 80),
ejabberd_hooks:add(caps_update, ServerHost, ejabberd_hooks:add(caps_update, ServerHost,
?MODULE, caps_update, 80), ?MODULE, caps_update, 80),
ejabberd_hooks:add(disco_sm_identity, ServerHost, ejabberd_hooks:add(disco_sm_identity, ServerHost,
@ -683,21 +685,24 @@ disco_items(Host, Node, From) ->
%% presence hooks handling functions %% presence hooks handling functions
%% %%
caps_update(#jid{luser = U, lserver = S, lresource = R}, #jid{lserver = Host} = JID, _Features) caps_add(#jid{luser = U, lserver = S, lresource = R}, #jid{lserver = Host} = JID, _Features)
when Host =/= S -> when Host =/= S ->
%% When a remote contact goes online while the local user is offline, the %% When a remote contact goes online while the local user is offline, the
%% remote contact won't receive last items from the local user even if %% remote contact won't receive last items from the local user even if
%% ignore_pep_from_offline is set to false. To work around this issue a bit, %% ignore_pep_from_offline is set to false. To work around this issue a bit,
%% we'll also send the last items to remote contacts when the local user %% we'll also send the last items to remote contacts when the local user
%% connects. That's the reason to use the caps_update hook instead of the %% connects. That's the reason to use the caps_add hook instead of the
%% presence_probe_hook for remote contacts: The latter is only called when a %% presence_probe_hook for remote contacts: The latter is only called when a
%% contact becomes available; the former also is also executed when the %% contact becomes available; the former is also executed when the local
%% local user goes online (because that triggers the contact to send a %% user goes online (because that triggers the contact to send a presence
%% presence packet with CAPS). %% packet with CAPS).
presence(Host, {presence, U, S, [R], JID}); presence(Host, {presence, U, S, [R], JID});
caps_update(_From, _To, _Feature) -> caps_add(_From, _To, _Feature) ->
ok. ok.
caps_update(#jid{luser = U, lserver = S, lresource = R}, #jid{lserver = Host} = JID, _Features) ->
presence(Host, {presence, U, S, [R], JID}).
presence_probe(#jid{luser = U, lserver = S, lresource = R} = JID, JID, Pid) -> presence_probe(#jid{luser = U, lserver = S, lresource = R} = JID, JID, Pid) ->
presence(S, {presence, JID, Pid}), presence(S, {presence, JID, Pid}),
presence(S, {presence, U, S, [R], JID}); presence(S, {presence, U, S, [R], JID});
@ -709,7 +714,7 @@ presence_probe(#jid{luser = U, lserver = S, lresource = R}, #jid{lserver = S} =
presence(S, {presence, U, S, [R], JID}); presence(S, {presence, U, S, [R], JID});
presence_probe(_Host, _JID, _Pid) -> presence_probe(_Host, _JID, _Pid) ->
%% ignore presence_probe from remote contacts, %% ignore presence_probe from remote contacts,
%% those are handled via caps_update %% those are handled via caps_add
ok. ok.
presence(ServerHost, Presence) -> presence(ServerHost, Presence) ->
@ -881,6 +886,8 @@ terminate(_Reason,
ejabberd_router:unregister_route(Host), ejabberd_router:unregister_route(Host),
case lists:member(?PEPNODE, Plugins) of case lists:member(?PEPNODE, Plugins) of
true -> true ->
ejabberd_hooks:delete(caps_add, ServerHost,
?MODULE, caps_add, 80),
ejabberd_hooks:delete(caps_update, ServerHost, ejabberd_hooks:delete(caps_update, ServerHost,
?MODULE, caps_update, 80), ?MODULE, caps_update, 80),
ejabberd_hooks:delete(disco_sm_identity, ServerHost, ejabberd_hooks:delete(disco_sm_identity, ServerHost,