./ct_report/coverage/mod_inbox_utils.COVER.html

1 %%%-------------------------------------------------------------------
2 %%% @copyright (C) 2018, Erlang-Solutions
3 %%% @doc
4 %%%
5 %%% @end
6 %%% Created : 30. Jan 2018 13:22
7 %%%-------------------------------------------------------------------
8 -module(mod_inbox_utils).
9
10 -include("mod_inbox.hrl").
11 -include("jlib.hrl").
12
13 -type inbox_fun() :: fun((mongooseim:host_type(),
14 jid:jid(),
15 jid:jid(),
16 exml:element(),
17 mongoose_acc:t()) -> mod_inbox:count_res()).
18
19 %%%%%%%%%%%%%%%%%%%
20 %% DB Operations shared by mod_inbox_one2one and mod_inbox_muclight
21 -export([maybe_reset_unread_count/5,
22 reset_unread_count_to_zero/3,
23 maybe_write_to_inbox/6,
24 write_to_sender_inbox/5,
25 write_to_receiver_inbox/5,
26 clear_inbox/3,
27 get_reset_markers/1,
28 if_chat_marker_get_id/2,
29 has_chat_marker/1,
30 get_option_write_aff_changes/1,
31 get_option_remove_on_kicked/1,
32 extract_attr_jid/1,
33 maybe_binary_to_positive_integer/1,
34 binary_to_bool/1,
35 bool_to_binary/1,
36 build_inbox_entry_key/2,
37 build_forward_el/1,
38 all_valid_boxes_for_query/1,
39 list_single_form_field/3,
40 calculate_ts_from/2
41 ]).
42
43 -ignore_xref([get_reset_markers/1, if_chat_marker_get_id/2]).
44
45 -spec maybe_reset_unread_count(HostType :: mongooseim:host_type(),
46 User :: jid:jid(),
47 Remote :: jid:jid(),
48 Packet :: exml:element(),
49 Acc :: mongoose_acc:t()) -> ok.
50 maybe_reset_unread_count(HostType, User, Remote, Packet, Acc) ->
51
:-(
ResetMarkers = get_reset_markers(HostType),
52
:-(
case if_chat_marker_get_id(Packet, ResetMarkers) of
53 undefined ->
54
:-(
ok;
55 Id ->
56
:-(
TS = mongoose_acc:timestamp(Acc),
57
:-(
reset_unread_count(HostType, User, Remote, Id, TS)
58 end.
59
60 -spec reset_unread_count_to_zero(mongoose_acc:t(), jid:jid(), jid:jid()) -> ok.
61 reset_unread_count_to_zero(Acc, From, Remote) ->
62
:-(
TS = mongoose_acc:timestamp(Acc),
63
:-(
HostType = mongoose_acc:host_type(Acc),
64
:-(
InboxEntryKey = build_inbox_entry_key(From, Remote),
65
:-(
ok = mod_inbox_backend:reset_unread(HostType, InboxEntryKey, undefined, TS).
66
67 -spec reset_unread_count(HostType ::mongooseim:host_type(),
68 From :: jid:jid(),
69 Remote :: jid:jid(),
70 MsgId :: id(),
71 TS :: integer()) -> ok.
72 reset_unread_count(HostType, From, Remote, MsgId, TS) ->
73
:-(
InboxEntryKey = build_inbox_entry_key(From, Remote),
74
:-(
ok = mod_inbox_backend:reset_unread(HostType, InboxEntryKey, MsgId, TS).
75
76 -spec write_to_sender_inbox(HostType :: mongooseim:host_type(),
77 Sender :: jid:jid(),
78 Receiver :: jid:jid(),
79 Packet :: exml:element(),
80 Acc :: mongoose_acc:t()) -> ok.
81 write_to_sender_inbox(HostType, Sender, Receiver, Packet, Acc) ->
82
:-(
MsgId = get_msg_id(Packet),
83
:-(
Timestamp = mongoose_acc:timestamp(Acc),
84 %% no unread for a user because he writes new messages which assumes he read all previous messages.
85
:-(
Count = 0,
86
:-(
InboxEntryKey = build_inbox_entry_key(Sender, Receiver),
87
:-(
mod_inbox_backend:set_inbox(HostType, InboxEntryKey, Packet, Count, MsgId, Timestamp).
88
89 -spec write_to_receiver_inbox(HostType :: mongooseim:host_type(),
90 Sender :: jid:jid(),
91 Receiver :: jid:jid(),
92 Packet :: exml:element(),
93 Acc :: mongoose_acc:t()) -> ok | {ok, integer()}.
94 write_to_receiver_inbox(HostType, Sender, Receiver, Packet, Acc) ->
95
:-(
MsgId = get_msg_id(Packet),
96
:-(
Timestamp = mongoose_acc:timestamp(Acc),
97
:-(
InboxEntryKey = build_inbox_entry_key(Receiver, Sender),
98
:-(
mod_inbox_backend:set_inbox_incr_unread(HostType, InboxEntryKey,
99 Packet, MsgId, Timestamp).
100
101 -spec clear_inbox(HostType :: mongooseim:host_type(),
102 User :: jid:user(),
103 Server :: jid:server()) -> mod_inbox:write_res().
104 clear_inbox(HostType, User, Server) when is_binary(User) ->
105
:-(
LUser = jid:nodeprep(User),
106
:-(
LServer = jid:nameprep(Server),
107
:-(
ok = mod_inbox_backend:clear_inbox(HostType, LUser, LServer).
108
109 %%%%%%%%%%%%%%%%%%%
110 %% Helpers
111
112 -spec get_reset_markers(HostType :: mongooseim:host_type()) -> list(marker()).
113 get_reset_markers(HostType) ->
114
:-(
gen_mod:get_module_opt(HostType, mod_inbox, reset_markers).
115
116 -spec if_chat_marker_get_id(Packet :: exml:element(),
117 Markers :: list(marker())) -> undefined | id().
118 if_chat_marker_get_id(Packet, Markers) when is_list(Markers) ->
119
:-(
Ids = [if_chat_marker_get_id(Packet, M) || M <- Markers],
120
:-(
Filtered = [El || El <- Ids, El /= undefined],
121
:-(
case Filtered of
122 [] ->
123
:-(
undefined;
124 [H | _] ->
125
:-(
H
126 end;
127 if_chat_marker_get_id(Packet, Marker) ->
128
:-(
case exml_query:paths(Packet, [{element, Marker}, {attr, <<"id">>}]) of
129 [Id] ->
130
:-(
Id;
131 _ ->
132
:-(
undefined
133 end.
134
135
136 -spec has_chat_marker(Packet :: exml:element()) -> boolean().
137 has_chat_marker(Packet) ->
138
:-(
mongoose_chat_markers:has_chat_markers(Packet).
139
140 -spec maybe_write_to_inbox(HostType, User, Remote, Packet, Acc, WriteF) ->
141 mod_inbox:count_res() when
142 HostType ::mongooseim:host_type(),
143 User :: jid:jid(),
144 Remote :: jid:jid(),
145 Packet :: exml:element(),
146 Acc :: mongoose_acc:t(),
147 %% WriteF is write_to_receiver_inbox/5 or write_to_sender_inbox/5
148 WriteF :: inbox_fun().
149 maybe_write_to_inbox(HostType, User, Remote, Packet, Acc, WriteF) ->
150
:-(
case has_chat_marker(Packet) of
151 true ->
152
:-(
ok;
153 false ->
154
:-(
Packet2 = fill_from_attr(Packet, User),
155
:-(
WriteF(HostType, User, Remote, Packet2, Acc)
156 end.
157
158 -spec get_msg_id(Msg :: exml:element()) -> binary().
159 get_msg_id(#xmlel{name = <<"message">>} = Msg) ->
160
:-(
exml_query:attr(Msg, <<"id">>, <<>>).
161
162 -spec fill_from_attr(Msg :: exml:element(), From :: jid:jid()) -> exml:element().
163 fill_from_attr(Msg = #xmlel{attrs = Attrs}, From) ->
164
:-(
case exml_query:attr(Msg, <<"from">>, undefined) of
165 undefined ->
166
:-(
FromBin = jid:to_binary(From),
167
:-(
Msg#xmlel{attrs = [{<<"from">>, FromBin} | Attrs]};
168 _ ->
169
:-(
Msg
170 end.
171
172 -spec get_option_write_aff_changes(HostType :: mongooseim:host_type()) -> boolean().
173 get_option_write_aff_changes(HostType) ->
174
:-(
gen_mod:get_module_opt(HostType, mod_inbox, aff_changes).
175
176 -spec get_option_remove_on_kicked(HostType :: mongooseim:host_type()) -> boolean().
177 get_option_remove_on_kicked(HostType) ->
178
:-(
gen_mod:get_module_opt(HostType, mod_inbox, remove_on_kicked).
179
180 extract_attr_jid(ResetStanza) ->
181
:-(
case exml_query:attr(ResetStanza, <<"jid">>) of
182 undefined ->
183
:-(
{error, <<"jid-required">>};
184 Value ->
185
:-(
case jid:from_binary(Value) of
186 error ->
187
:-(
{error, <<"invalid-jid">>};
188
:-(
JID -> JID
189 end
190 end.
191
192 -spec maybe_binary_to_positive_integer(binary()) -> non_neg_integer() | {error, atom()}.
193 maybe_binary_to_positive_integer(Bin) ->
194
:-(
try erlang:binary_to_integer(Bin) of
195
:-(
N when N >= 0 -> N;
196
:-(
_ -> {error, non_positive_integer}
197
:-(
catch error:badarg -> {error, 'NaN'}
198 end.
199
200 -spec binary_to_bool(binary()) -> true | false | error.
201
:-(
binary_to_bool(<<"true">>) -> true;
202
:-(
binary_to_bool(<<"false">>) -> false;
203
:-(
binary_to_bool(_) -> error.
204
205 -spec bool_to_binary(integer() | boolean()) -> binary() | error.
206
:-(
bool_to_binary(1) -> <<"true">>;
207
:-(
bool_to_binary(0) -> <<"false">>;
208
:-(
bool_to_binary(true) -> <<"true">>;
209
:-(
bool_to_binary(false) -> <<"false">>;
210
:-(
bool_to_binary(_) -> error.
211
212 build_inbox_entry_key(FromJid, ToJid) ->
213
:-(
{LUser, LServer} = jid:to_lus(FromJid),
214
:-(
ToBareJid = jid:nameprep(jid:to_bare_binary(ToJid)),
215
:-(
{LUser, LServer, ToBareJid}.
216
217 -spec build_forward_el(inbox_res()) -> exml:element().
218 build_forward_el(#{msg := Content, timestamp := Timestamp}) ->
219
:-(
Delay = build_delay_el(Timestamp),
220
:-(
#xmlel{name = <<"forwarded">>, attrs = [{<<"xmlns">>, ?NS_FORWARD}],
221 children = [Delay, Content]}.
222
223 -spec build_delay_el(Timestamp :: integer()) -> exml:element().
224 build_delay_el(Timestamp) ->
225
:-(
TS = calendar:system_time_to_rfc3339(Timestamp, [{offset, "Z"}, {unit, microsecond}]),
226
:-(
jlib:timestamp_to_xml(TS, undefined, undefined).
227
228 all_valid_boxes_for_query(HostType) ->
229
:-(
[<<"all">> | gen_mod:get_module_opt(HostType, mod_inbox, boxes)].
230
231 -spec list_single_form_field(Var :: binary(),
232 Default :: binary(),
233 Options :: [ Option | {Label, Value}]) -> exml:element() when
234 Option :: binary(), Label :: binary(), Value :: binary().
235 list_single_form_field(Var, Default, Options) ->
236
:-(
Value = form_field_value(Default),
237
:-(
#xmlel{
238 name = <<"field">>,
239 attrs = [{<<"var">>, Var}, {<<"type">>, <<"list-single">>}],
240
:-(
children = [Value | [ form_field_option(Option) || Option <- Options ]]
241 }.
242
243 -spec form_field_option(Option | {Label, Value}) -> exml:element() when
244 Option :: binary(), Label :: binary(), Value :: binary().
245 form_field_option({Label, Value}) ->
246
:-(
#xmlel{
247 name = <<"option">>,
248 attrs = [{<<"label">>, Label}],
249 children = [form_field_value(Value)]
250 };
251 form_field_option(Option) ->
252
:-(
form_field_option({Option, Option}).
253
254 -spec form_field_value(Value :: binary()) -> exml:element().
255 form_field_value(Value) ->
256
:-(
#xmlel{name = <<"value">>, children = [#xmlcdata{content = Value}]}.
257
258 -spec calculate_ts_from(integer(), non_neg_integer()) -> integer().
259 calculate_ts_from(Now, Days) ->
260
:-(
DaysInMicroSeconds = 86400000000 * Days, % 8.64e+10 microseconds in a day
261
:-(
Now - DaysInMicroSeconds.
Line Hits Source