1 |
|
%% @doc This module is responsible for determining the server's strategy for a |
2 |
|
%% particular message. (See XEP section 2.2.2 "Determine Default Action") |
3 |
|
%% This work was sponsored by Grindr LLC |
4 |
|
%% @reference <a href="http://xmpp.org/extensions/xep-0079.html">XEP-0079</a> |
5 |
|
%% @author <mongooseim@erlang-solutions.com> |
6 |
|
%% @copyright 2014 Erlang Solutions, Ltd. |
7 |
|
-module(amp_strategy). |
8 |
|
|
9 |
|
-export([determine_strategy/3, |
10 |
|
null_strategy/0]). |
11 |
|
|
12 |
|
-include("amp.hrl"). |
13 |
|
-include("jlib.hrl"). |
14 |
|
|
15 |
|
-spec determine_strategy(StrategyAcc, Params, Extra) -> {ok, StrategyAcc} when |
16 |
|
StrategyAcc :: mod_amp:amp_strategy(), |
17 |
|
Params :: #{to := jid:jid() | undefined, event := mod_amp:amp_event()}, |
18 |
|
Extra :: map(). |
19 |
:-( |
determine_strategy(_, #{to := undefined}, _) -> {ok, null_strategy()}; |
20 |
|
determine_strategy(_, #{to := To, event := Event}, _) -> |
21 |
:-( |
TargetResources = get_target_resources(To), |
22 |
:-( |
Deliver = deliver_strategy(TargetResources, Event), |
23 |
:-( |
MatchResource = match_resource_strategy(TargetResources), |
24 |
|
|
25 |
:-( |
{ok, #amp_strategy{deliver = Deliver, |
26 |
|
'match-resource' = MatchResource, |
27 |
|
'expire-at' = undefined}}. |
28 |
|
|
29 |
|
%% @doc This strategy will never be matched by any amp_rules. |
30 |
|
%% Use it as a seed parameter to `mongoose_hooks'. |
31 |
|
-spec null_strategy() -> amp_strategy(). |
32 |
|
null_strategy() -> |
33 |
:-( |
#amp_strategy{deliver = undefined, |
34 |
|
'match-resource' = undefined, |
35 |
|
'expire-at' = undefined}. |
36 |
|
|
37 |
|
%% Internals |
38 |
|
get_target_resources(MessageTarget = #jid{lresource = TargetRes}) -> |
39 |
:-( |
Resources = ejabberd_sm:get_user_resources(MessageTarget), |
40 |
:-( |
ResStatus = case lists:member(TargetRes, Resources) of |
41 |
:-( |
true -> online; |
42 |
:-( |
false -> offline |
43 |
|
end, |
44 |
:-( |
{ResStatus, Resources}. |
45 |
|
|
46 |
:-( |
deliver_strategy({offline, []}, initial_check) -> [none]; |
47 |
:-( |
deliver_strategy({_Status, _}, initial_check) -> [direct, none]; |
48 |
:-( |
deliver_strategy({offline, []}, archived) -> [stored]; |
49 |
:-( |
deliver_strategy({_Status, _}, archived) -> [direct, stored]; |
50 |
:-( |
deliver_strategy(_, delivery_failed) -> [stored, none]; |
51 |
:-( |
deliver_strategy({offline, []}, mam_failed) -> [none]; |
52 |
:-( |
deliver_strategy({_Status, _}, mam_failed) -> [direct, none]; |
53 |
:-( |
deliver_strategy(_, offline_failed) -> [none]; |
54 |
:-( |
deliver_strategy(_, delivered) -> [direct]. |
55 |
|
|
56 |
|
%% @doc Notes on matching |
57 |
|
%% |
58 |
|
%% The undefined value in match-resource signifies that no resource could be matched, |
59 |
|
%% and therefore no rules with match-resource set could possibly yield true. |
60 |
|
%% Conversely, the 'any' strategy is not a valid server-side strategy: |
61 |
|
%% the server will either match the exact resource, or not. (See match_res_any CT test) |
62 |
|
%% in test/amp_resolver_SUITE.erl |
63 |
|
%% |
64 |
:-( |
match_resource_strategy({offline, []}) -> undefined; |
65 |
:-( |
match_resource_strategy({offline, [_|_ManyRes]}) -> other; |
66 |
:-( |
match_resource_strategy({online, [_|_ManyRes]}) -> exact. |