./ct_report/coverage/mam_iq.COVER.html

1 -module(mam_iq).
2
3 -export([action/1]).
4 -export([action_type/1]).
5 -export([form_to_lookup_params/5]).
6 -export([lookup_params_with_archive_details/4]).
7
8 -import(mod_mam_utils,
9 [maybe_microseconds/1,
10 get_one_of_path/2]).
11
12 -include("jlib.hrl").
13 -include("mongoose_rsm.hrl").
14
15 -type action() :: 'mam_get_prefs'
16 | 'mam_lookup_messages'
17 | 'mam_set_prefs'
18 | 'mam_set_message_form'
19 | 'mam_get_message_form'
20 | 'mam_get_metadata'.
21
22 -type lookup_params() :: #{
23 archive_id => mod_mam:archive_id(),
24 owner_jid => jid:jid(),
25 caller_jid => jid:jid(),
26 rsm => jlib:rsm_in() | undefined,
27 max_result_limit => non_neg_integer(),
28 %% Contains page size value provided by client or enforced by server.
29 %% It's a final value used by backend DB modules.
30 page_size => non_neg_integer(),
31 ordering_direction => backward | forward,
32 %% unix_timestamp() is in microseconds
33 now => mod_mam:unix_timestamp(),
34 %% Filtering by date
35 start_ts => mod_mam:unix_timestamp() | undefined,
36 end_ts => mod_mam:unix_timestamp() | undefined,
37 %% Filtering by contact
38 with_jid => jid:jid() | undefined,
39 %% Filtering by body text
40 search_text => binary() | undefined,
41 %% Filtering Result Set before/after specific message ids
42 borders => mod_mam:borders() | undefined,
43 %% Filtering Result Set based on specific message ids
44 message_ids => [mod_mam:message_id()] | undefined,
45 %% Affects 'policy-violation' for a case when:
46 %% - user does not use forms to query archive
47 %% - user does not provide "set" element
48 %% see form_to_lookup_params for more info
49 limit_passed => boolean(),
50 %% Optimizations flags
51 %% see form_to_lookup_params for more info
52 is_simple => true | false,
53 %% Contains information whether the client requested to get the results in reversed order
54 flip_page => true | false,
55 %% If the groupchat messages are stored in the user's archive,
56 %% this parameter is used to decide whether to include them or not
57 include_groupchat => true | false,
58 %% Can have more fields, added in maybe_add_extra_lookup_params function
59 %% in runtime
60 atom() => _
61 }.
62
63 -export_type([action/0, lookup_params/0]).
64
65 -callback extra_lookup_params(jlib:iq(), lookup_params()) -> lookup_params().
66
67 -spec action(jlib:iq()) -> action().
68 action(IQ = #iq{xmlns = ?NS_MAM_04}) ->
69 1157 action_v04plus(IQ);
70 action(IQ = #iq{xmlns = ?NS_MAM_06}) ->
71 237 action_v04plus(IQ).
72
73 action_v04plus(#iq{type = Action, sub_el = #xmlel{name = Category}}) ->
74 1394 case {Action, Category} of
75 220 {set, <<"prefs">>} -> mam_set_prefs;
76 115 {get, <<"prefs">>} -> mam_get_prefs;
77 25 {get, <<"query">>} -> mam_get_message_form;
78 1004 {set, <<"query">>} -> mam_set_message_form;
79 30 {get, <<"metadata">>} -> mam_get_metadata
80 end.
81
82 -spec action_type(action()) -> 'get' | 'set'.
83
:-(
action_type(mam_get_prefs) -> get;
84
:-(
action_type(mam_set_prefs) -> set;
85
:-(
action_type(mam_lookup_messages) -> get;
86 308 action_type(mam_set_message_form) -> get;
87
:-(
action_type(mam_get_message_form) -> get;
88 15 action_type(mam_get_metadata) -> get.
89
90 %% @doc Convert id into internal format.
91 -spec fix_rsm('none' | jlib:rsm_in()) -> 'undefined' | jlib:rsm_in().
92 fix_rsm(none) ->
93 504 undefined;
94 fix_rsm(RSM=#rsm_in{direction = aft, id = <<>>}) ->
95 35 RSM#rsm_in{direction = undefined, id = undefined}; %% First page
96 fix_rsm(RSM=#rsm_in{direction = aft, id = undefined}) ->
97
:-(
RSM#rsm_in{direction = undefined}; %% First page
98 fix_rsm(RSM=#rsm_in{id = undefined}) ->
99 115 RSM;
100 fix_rsm(RSM=#rsm_in{id = <<>>}) ->
101 95 RSM#rsm_in{id = undefined};
102 fix_rsm(RSM=#rsm_in{id = BExtMessID}) when is_binary(BExtMessID) ->
103 245 MessID = mod_mam_utils:external_binary_to_mess_id(BExtMessID),
104 245 RSM#rsm_in{id = MessID}.
105
106 %% @doc This element's name is "limit". But it must be "max" according XEP-0313.
107 -spec elem_to_limit(any()) -> any().
108 elem_to_limit(QueryEl) ->
109 994 get_one_of_path(QueryEl, [
110 [{element, <<"set">>}, {element, <<"max">>}, cdata],
111 [{element, <<"set">>}, {element, <<"limit">>}, cdata]
112 ]).
113
114
115 -spec form_to_start_microseconds(mongoose_data_forms:kv_map()) -> 'undefined' | non_neg_integer().
116 form_to_start_microseconds(#{<<"start">> := [V]}) ->
117 35 maybe_microseconds(V);
118 form_to_start_microseconds(#{}) ->
119 959 undefined.
120
121
122 -spec form_to_end_microseconds(mongoose_data_forms:kv_map()) -> 'undefined' | non_neg_integer().
123 form_to_end_microseconds(#{<<"end">> := [V]}) ->
124 25 maybe_microseconds(V);
125 form_to_end_microseconds(#{}) ->
126 969 undefined.
127
128 -spec form_to_with_jid(mongoose_data_forms:kv_map()) -> 'error' | 'undefined' | jid:jid().
129 form_to_with_jid(#{<<"with">> := [JID]}) ->
130 20 jid:from_binary(JID);
131 form_to_with_jid(#{}) ->
132 974 undefined.
133
134 -spec form_to_lookup_params(jlib:iq(), integer(), integer(), undefined | module(), boolean()) ->
135 lookup_params().
136 form_to_lookup_params(#iq{sub_el = QueryEl} = IQ, MaxResultLimit, DefaultResultLimit, Module, EnforceSimple) ->
137 994 Params0 = common_lookup_params(QueryEl, MaxResultLimit, DefaultResultLimit),
138 994 KVs = query_to_map(QueryEl),
139 994 Params = Params0#{
140 %% Filtering by date.
141 %% Start :: integer() | undefined
142 start_ts => form_to_start_microseconds(KVs),
143 end_ts => form_to_end_microseconds(KVs),
144 %% Filtering by contact.
145 with_jid => form_to_with_jid(KVs),
146 %% Filtering by text
147 search_text => mod_mam_utils:form_to_text(KVs),
148
149 borders => mod_mam_utils:form_borders_decode(KVs),
150 message_ids => form_to_msg_ids(KVs),
151 %% Whether or not the client query included a <set/> element,
152 %% the server MAY simply return its limited results.
153 %% So, disable 'policy-violation'.
154 limit_passed => true,
155 %% `is_simple' can contain:
156 %% - true - do not count records (useful during pagination, when we already
157 %% know how many messages we have from a previous query);
158 %% - false - count messages (slow, according XEP-0313);
159 is_simple => maybe_enforce_simple(KVs, EnforceSimple),
160 include_groupchat => include_groupchat(KVs)},
161 979 maybe_add_extra_lookup_params(Module, Params, IQ).
162
163 -spec query_to_map(exml:element()) -> mongoose_data_forms:kv_map().
164 query_to_map(QueryEl) ->
165 994 case mongoose_data_forms:find_form(QueryEl) of
166 undefined ->
167 384 #{};
168 Form ->
169 610 #{kvs := KVs} = mongoose_data_forms:parse_form_fields(Form),
170 610 KVs
171 end.
172
173 -spec common_lookup_params(exml:element(), non_neg_integer(), non_neg_integer()) ->
174 lookup_params().
175 common_lookup_params(QueryEl, MaxResultLimit, DefaultResultLimit) ->
176 994 RSM = fix_rsm(jlib:rsm_decode(QueryEl)),
177 994 Limit = elem_to_limit(QueryEl),
178 994 #{now => erlang:system_time(microsecond),
179 rsm => RSM,
180 max_result_limit => MaxResultLimit,
181 page_size => min(MaxResultLimit,
182 mod_mam_utils:maybe_integer(Limit, DefaultResultLimit)),
183 limit_passed => Limit =/= <<>>,
184 ordering_direction => ordering_direction(RSM),
185 flip_page => mod_mam_utils:should_page_be_flipped(QueryEl)}.
186
187 -spec lookup_params_with_archive_details(lookup_params(), term(), jid:jid(), jid:jid()) ->
188 lookup_params().
189 lookup_params_with_archive_details(Params, ArcID, ArcJID, CallerJID) ->
190 979 Params#{archive_id => ArcID,
191 owner_jid => ArcJID,
192 caller_jid => CallerJID}.
193
194 220 ordering_direction(#rsm_in{direction = before}) -> backward;
195 774 ordering_direction(_) -> forward.
196
197 maybe_add_extra_lookup_params(undefined, Params, _) ->
198 979 Params;
199 maybe_add_extra_lookup_params(Module, Params, IQ) ->
200
:-(
Module:extra_lookup_params(IQ, Params).
201
202 maybe_enforce_simple(_, true) ->
203 5 true;
204 maybe_enforce_simple(KVs, _) ->
205 974 mod_mam_utils:form_decode_optimizations(KVs).
206
207 include_groupchat(#{<<"include-groupchat">> := [<<"false">>]}) ->
208 10 false;
209 include_groupchat(_) ->
210 969 undefined.
211
212 form_to_msg_ids(#{<<"ids">> := IDs}) ->
213 30 [mod_mam_utils:external_binary_to_mess_id(ID) || ID <- IDs];
214 form_to_msg_ids(_) ->
215 949 undefined.
Line Hits Source