./ct_report/coverage/mongoose_stanza_helper.COVER.html

1 -module(mongoose_stanza_helper).
2 -export([build_message/3]).
3 -export([build_message_with_headline/3]).
4 -export([parse_from_to/2]).
5 -export([get_last_messages/4]).
6 -export([route/4]).
7
8 -include("jlib.hrl").
9 -include("mongoose_logger.hrl").
10
11 -spec build_message(From :: binary(), To :: binary(), Body :: binary()) -> exml:element().
12 build_message(From, To, Body) ->
13 17 #xmlel{name = <<"message">>,
14 attrs = [{<<"type">>, <<"chat">>},
15 {<<"id">>, mongoose_bin:gen_from_crypto()},
16 {<<"from">>, From},
17 {<<"to">>, To}],
18 children = [#xmlel{name = <<"body">>,
19 children = [#xmlcdata{content = Body}]}]
20 }.
21
22 build_message_with_headline(FromBin, ToBin,
23 #{<<"body">> := Body, <<"subject">> := Subject}) ->
24 2 Children = maybe_cdata_elem(<<"subject">>, Subject) ++
25 maybe_cdata_elem(<<"body">>, Body),
26 2 Attrs = [{<<"type">>, <<"headline">>},
27 {<<"id">>, mongoose_bin:gen_from_crypto()},
28 {<<"from">>, FromBin},
29 {<<"to">>, ToBin}],
30 2 #xmlel{name = <<"message">>, attrs = Attrs, children = Children}.
31
32
:-(
maybe_cdata_elem(_, null) -> [];
33
:-(
maybe_cdata_elem(_, <<>>) -> [];
34 maybe_cdata_elem(Name, Text) when is_binary(Text) ->
35 4 [cdata_elem(Name, Text)].
36
37 cdata_elem(Name, Text) when is_binary(Name), is_binary(Text) ->
38 4 #xmlel{name = Name, children = [#xmlcdata{content = Text}]}.
39
40 -spec parse_from_to(jid:jid() | binary() | undefined, jid:jid() | binary() | undefined) ->
41 {ok, jid:jid(), jid:jid()} | {error, missing} | {error, type_error, string()}.
42 parse_from_to(F, T) when F == undefined; T == undefined ->
43 1 {error, missing};
44 parse_from_to(F, T) ->
45 53 case parse_jid_list([F, T]) of
46 41 {ok, [Fjid, Tjid]} -> {ok, Fjid, Tjid};
47 12 E -> E
48 end.
49
50 -spec parse_jid_list(BinJids :: [binary()]) -> {ok, [jid:jid()]} | {error, type_error, string()}.
51 parse_jid_list([_ | _] = BinJids) ->
52 53 Jids = lists:map(fun parse_jid/1, BinJids),
53 53 case [Msg || {error, Msg} <- Jids] of
54 41 [] -> {ok, Jids};
55 12 Errors -> {error, type_error, lists:join("; ", Errors)}
56 end.
57
58 -spec parse_jid(binary() | jid:jid()) -> jid:jid() | {error, string()}.
59 parse_jid(#jid{} = Jid) ->
60
:-(
Jid;
61 parse_jid(Jid) when is_binary(Jid) ->
62 106 case jid:from_binary(Jid) of
63 12 error -> {error, io_lib:format("Invalid jid: ~p", [Jid])};
64 94 B -> B
65 end.
66
67 -spec get_last_messages(Caller :: jid:jid(),
68 Limit :: non_neg_integer(),
69 With :: null | jid:jid(),
70 Before :: null | mod_mam:unix_timestamp()) -> {ok, map()}.
71 get_last_messages(Caller, Limit, With, Before) ->
72 9 With2 = null_as_undefined(With),
73 9 Before2 = null_as_undefined(Before), %% Before is in microseconds
74 9 Limit2 = min(500, Limit),
75 9 Rows = mongoose_stanza_api:lookup_recent_messages(Caller, With2, Before2, Limit2),
76 9 Maps = lists:map(fun row_to_map/1, Rows),
77 9 {ok, #{<<"stanzas">> => Maps, <<"limit">> => Limit2}}.
78
79 16 null_as_undefined(null) -> undefined;
80 2 null_as_undefined(Value) -> Value.
81
82 -spec row_to_map(mod_mam:message_row()) -> {ok, map()}.
83 row_to_map(#{id := Id, jid := From, packet := Msg}) ->
84 12 {Microseconds, _} = mod_mam_utils:decode_compact_uuid(Id),
85 12 StanzaID = mod_mam_utils:mess_id_to_external_binary(Id),
86 12 Map = #{<<"sender">> => From, <<"timestamp">> => Microseconds,
87 <<"stanza_id">> => StanzaID, <<"stanza">> => Msg},
88 12 {ok, Map}.
89
90 -spec route(From :: jid:jid(), To :: jid:jid(),
91 Packet :: exml:element(), SkipAuth :: boolean()) ->
92 {ok, map()} | {error, term()}.
93 route(From = #jid{lserver = LServer}, To, Packet, SkipAuth) ->
94 19 case mongoose_graphql_helper:check_user(From, SkipAuth) of
95 {ok, HostType} ->
96 17 do_route(HostType, LServer, From, To, Packet);
97 Error ->
98 2 Error
99 end.
100
101 do_route(HostType, LServer, From, To, Packet) ->
102 %% Based on mod_commands:do_send_packet/3
103 17 Acc = mongoose_acc:new(#{location => ?LOCATION,
104 host_type => HostType,
105 lserver => LServer,
106 element => Packet}),
107 17 Acc1 = mongoose_hooks:user_send_packet(Acc, From, To, Packet),
108 17 Acc2 = ejabberd_router:route(From, To, Acc1),
109 17 MessID = mod_mam_utils:get_mam_id_ext(Acc2),
110 17 {ok, #{ <<"id">> => MessID }}.
Line Hits Source