1 |
|
%%%------------------------------------------------------------------- |
2 |
|
%%% @copyright (C) 2018, Erlang-Solutions |
3 |
|
%%% @doc |
4 |
|
%%% |
5 |
|
%%% @end |
6 |
|
%%% Created : 30. Jan 2018 13:22 |
7 |
|
%%%------------------------------------------------------------------- |
8 |
|
-module(mod_inbox_muclight). |
9 |
|
|
10 |
|
-include("mod_muc_light.hrl"). |
11 |
|
-include("jlib.hrl"). |
12 |
|
-include("mongoose.hrl"). |
13 |
|
|
14 |
|
-export([handle_outgoing_message/5, handle_incoming_message/5]). |
15 |
|
|
16 |
|
-type role() :: r_member() | r_owner() | r_none(). |
17 |
|
-type r_member() :: binary(). |
18 |
|
-type r_owner() :: binary(). |
19 |
|
-type r_none() :: binary(). |
20 |
|
|
21 |
|
-spec handle_outgoing_message(HostType :: mongooseim:host_type(), |
22 |
|
User :: jid:jid(), |
23 |
|
Room :: jid:jid(), |
24 |
|
Packet :: exml:element(), |
25 |
|
Acc :: mongoose_acc:t()) -> |
26 |
|
mod_inbox:count_res(). |
27 |
|
handle_outgoing_message(HostType, User, Room, Packet, Acc) -> |
28 |
191 |
mod_inbox_utils:maybe_reset_unread_count(HostType, User, Room, Packet, Acc). |
29 |
|
|
30 |
|
-spec handle_incoming_message(HostType :: mongooseim:host_type(), |
31 |
|
RoomUser :: jid:jid(), |
32 |
|
Remote :: jid:jid(), |
33 |
|
Packet :: exml:element(), |
34 |
|
Acc :: mongoose_acc:t()) -> |
35 |
|
mod_inbox:count_res(). |
36 |
|
handle_incoming_message(HostType, RoomUser, Remote, Packet, Acc) -> |
37 |
899 |
case mod_inbox_utils:has_chat_marker(Packet) of |
38 |
|
true -> |
39 |
|
%% don't store chat markers in inbox |
40 |
459 |
ok; |
41 |
|
false -> |
42 |
440 |
maybe_handle_system_message(HostType, RoomUser, Remote, Packet, Acc) |
43 |
|
end. |
44 |
|
|
45 |
|
-spec maybe_handle_system_message(HostType :: mongooseim:host_type(), |
46 |
|
RoomOrUser :: jid:jid(), |
47 |
|
Receiver :: jid:jid(), |
48 |
|
Packet :: exml:element(), |
49 |
|
Acc :: mongoose_acc:t()) -> |
50 |
|
mod_inbox:count_res(). |
51 |
|
maybe_handle_system_message(HostType, RoomOrUser, Receiver, Packet, Acc) -> |
52 |
440 |
case is_system_message(HostType, RoomOrUser, Receiver, Packet) of |
53 |
|
true -> |
54 |
328 |
handle_system_message(HostType, RoomOrUser, Receiver, Packet, Acc); |
55 |
|
_ -> |
56 |
112 |
Sender = jid:from_binary(RoomOrUser#jid.lresource), |
57 |
112 |
write_to_inbox(HostType, RoomOrUser, Receiver, Sender, Packet, Acc) |
58 |
|
end. |
59 |
|
|
60 |
|
-spec handle_system_message(HostType :: mongooseim:host_type(), |
61 |
|
Room :: jid:jid(), |
62 |
|
Remote :: jid:jid(), |
63 |
|
Packet :: exml:element(), |
64 |
|
Acc :: mongoose_acc:t()) -> ok. |
65 |
|
handle_system_message(HostType, Room, Remote, Packet, Acc) -> |
66 |
328 |
case system_message_type(Remote, Packet) of |
67 |
|
kick -> |
68 |
61 |
handle_kicked_message(HostType, Room, Remote, Packet, Acc); |
69 |
|
invite -> |
70 |
170 |
handle_invitation_message(HostType, Room, Remote, Packet, Acc); |
71 |
|
other -> |
72 |
97 |
?LOG_DEBUG(#{what => irrelevant_system_message_for_mod_inbox_muclight, |
73 |
97 |
room => Room, exml_packet => Packet}), |
74 |
97 |
ok |
75 |
|
end. |
76 |
|
|
77 |
|
-spec handle_invitation_message(HostType :: mongooseim:host_type(), |
78 |
|
Room :: jid:jid(), |
79 |
|
Remote :: jid:jid(), |
80 |
|
Packet :: exml:element(), |
81 |
|
Acc :: mongoose_acc:t()) -> ok. |
82 |
|
handle_invitation_message(HostType, Room, Remote, Packet, Acc) -> |
83 |
170 |
maybe_store_system_message(HostType, Room, Remote, Packet, Acc). |
84 |
|
|
85 |
|
-spec handle_kicked_message(HostType :: mongooseim:host_type(), |
86 |
|
Room :: jid:jid(), |
87 |
|
Remote :: jid:jid(), |
88 |
|
Packet :: exml:element(), |
89 |
|
Acc :: mongoose_acc:t()) -> ok. |
90 |
|
handle_kicked_message(HostType, Room, Remote, Packet, Acc) -> |
91 |
61 |
CheckRemove = mod_inbox_utils:get_option_remove_on_kicked(HostType), |
92 |
61 |
maybe_store_system_message(HostType, Room, Remote, Packet, Acc), |
93 |
61 |
maybe_remove_inbox_row(HostType, Room, Remote, CheckRemove). |
94 |
|
|
95 |
|
-spec maybe_store_system_message(HostType :: mongooseim:host_type(), |
96 |
|
Room :: jid:jid(), |
97 |
|
Remote :: jid:jid(), |
98 |
|
Packet :: exml:element(), |
99 |
|
Acc :: mongoose_acc:t()) -> ok. |
100 |
|
maybe_store_system_message(HostType, Room, Remote, Packet, Acc) -> |
101 |
231 |
WriteAffChanges = mod_inbox_utils:get_option_write_aff_changes(HostType), |
102 |
231 |
case WriteAffChanges of |
103 |
|
true -> |
104 |
217 |
write_to_inbox(HostType, Room, Remote, Room, Packet, Acc); |
105 |
|
false -> |
106 |
14 |
ok |
107 |
|
end. |
108 |
|
|
109 |
|
-spec maybe_remove_inbox_row(HostType :: mongooseim:host_type(), |
110 |
|
Room :: jid:jid(), |
111 |
|
Remote :: jid:jid(), |
112 |
|
WriteAffChanges :: boolean()) -> ok. |
113 |
|
maybe_remove_inbox_row(_, _, _, false) -> |
114 |
4 |
ok; |
115 |
|
maybe_remove_inbox_row(HostType, Room, Remote, true) -> |
116 |
57 |
InboxEntryKey = mod_inbox_utils:build_inbox_entry_key(Remote, Room), |
117 |
57 |
ok = mod_inbox_backend:remove_inbox_row(HostType, InboxEntryKey). |
118 |
|
|
119 |
|
-spec write_to_inbox(HostType :: mongooseim:host_type(), |
120 |
|
RoomUser :: jid:jid(), |
121 |
|
Remote :: jid:jid(), |
122 |
|
Sender :: jid:jid(), |
123 |
|
Packet :: exml:element(), |
124 |
|
Acc :: mongoose_acc:t()) -> |
125 |
|
mod_inbox:count_res(). |
126 |
|
write_to_inbox(HostType, RoomUser, Remote, Sender, Packet, Acc) -> |
127 |
329 |
case jid:are_equal(Remote, Sender) of |
128 |
38 |
true -> mod_inbox_utils:write_to_sender_inbox(HostType, Remote, RoomUser, Packet, Acc); |
129 |
291 |
false -> mod_inbox_utils:write_to_receiver_inbox(HostType, RoomUser, Remote, Packet, Acc) |
130 |
|
end. |
131 |
|
|
132 |
|
%%%%%%% |
133 |
|
%% Predicate funs |
134 |
|
|
135 |
|
%% @doc Check if sender is just 'roomname@muclight.domain' with no resource |
136 |
|
%% TODO: Replace sender domain check with namespace check - current logic won't handle all cases! |
137 |
|
-spec is_system_message(HostType :: mongooseim:host_type(), |
138 |
|
Sender :: jid:jid(), |
139 |
|
Receiver :: jid:jid(), |
140 |
|
Packet :: exml:element()) -> boolean(). |
141 |
|
is_system_message(_HostType, #jid{lresource = <<>>}, _Receiver, _Packet) -> |
142 |
328 |
true; |
143 |
|
is_system_message(_HostType, #jid{lresource = _RoomUser}, _Receiver, _Packet) -> |
144 |
112 |
false. |
145 |
|
|
146 |
|
-spec is_change_aff_message(jid:jid(), exml:element(), role()) -> boolean(). |
147 |
|
is_change_aff_message(User, Packet, Role) -> |
148 |
984 |
AffItems = exml_query:paths(Packet, [{element_with_ns, ?NS_MUC_LIGHT_AFFILIATIONS}, |
149 |
|
{element, <<"user">>}]), |
150 |
984 |
AffList = get_users_with_affiliation(AffItems, Role), |
151 |
984 |
Jids = [Jid || #xmlel{children = [#xmlcdata{content = Jid}]} <- AffList], |
152 |
984 |
UserBin = jid:to_binary(jid:to_lower(jid:to_bare(User))), |
153 |
984 |
lists:member(UserBin, Jids). |
154 |
|
|
155 |
|
-spec system_message_type(User :: jid:jid(), Packet :: exml:element()) -> invite | kick | other. |
156 |
|
system_message_type(User, Packet) -> |
157 |
328 |
case {is_invitation_message(User, Packet), |
158 |
|
is_new_owner_message(User, Packet), |
159 |
|
is_kicked_message(User, Packet)} of |
160 |
104 |
{true, _, _} -> invite; |
161 |
66 |
{_, true, _} -> invite; |
162 |
61 |
{_, _, true} -> kick; |
163 |
97 |
_ -> other |
164 |
|
end. |
165 |
|
|
166 |
|
-spec is_invitation_message(jid:jid(), exml:element()) -> boolean(). |
167 |
|
is_invitation_message(User, Packet) -> |
168 |
328 |
is_change_aff_message(User, Packet, <<"member">>). |
169 |
|
|
170 |
|
-spec is_new_owner_message(jid:jid(), exml:element()) -> boolean(). |
171 |
|
is_new_owner_message(User, Packet) -> |
172 |
328 |
is_change_aff_message(User, Packet, <<"owner">>). |
173 |
|
|
174 |
|
-spec is_kicked_message(jid:jid(), exml:element()) -> boolean(). |
175 |
|
is_kicked_message(User, Packet) -> |
176 |
328 |
is_change_aff_message(User, Packet, <<"none">>). |
177 |
|
|
178 |
|
-spec get_users_with_affiliation(list(exml:element()), role()) -> list(exml:element()). |
179 |
|
get_users_with_affiliation(AffItems, Role) -> |
180 |
984 |
[M || #xmlel{name = <<"user">>, attrs = [{<<"affiliation">>, R}]} = M <- AffItems, R == Role]. |