24
1
mirror of https://github.com/processone/ejabberd.git synced 2024-06-12 21:52:07 +02:00

Add stanza-id to every archived message (#1477)

This commit is contained in:
Evgeniy Khramtsov 2017-01-20 23:21:06 +03:00
parent 17fe272dc5
commit 56ef607904
3 changed files with 92 additions and 52 deletions

View File

@ -750,14 +750,19 @@ select(_LServer, JidRequestor, JidArchive, Query, RSM,
case match_interval(Now, Start, End) and case match_interval(Now, Start, End) and
match_rsm(Now, RSM) of match_rsm(Now, RSM) of
true -> true ->
[{integer_to_binary(TS), TS, case msg_to_el(#archive_msg{
msg_to_el(#archive_msg{ id = integer_to_binary(TS),
type = groupchat, type = groupchat,
timestamp = Now, timestamp = Now,
peer = undefined, peer = undefined,
nick = Nick, nick = Nick,
packet = Pkt}, packet = Pkt},
MsgType, JidRequestor, JidArchive)}]; MsgType, JidRequestor, JidArchive) of
{ok, Msg} ->
[{integer_to_binary(TS), TS, Msg}];
{error, _} ->
[]
end;
false -> false ->
[] []
end end
@ -776,25 +781,23 @@ select(LServer, JidRequestor, JidArchive, Query, RSM, MsgType) ->
Mod = gen_mod:db_mod(LServer, ?MODULE), Mod = gen_mod:db_mod(LServer, ?MODULE),
Mod:select(LServer, JidRequestor, JidArchive, Query, RSM, MsgType). Mod:select(LServer, JidRequestor, JidArchive, Query, RSM, MsgType).
msg_to_el(#archive_msg{timestamp = TS, packet = Pkt1, nick = Nick, peer = Peer}, msg_to_el(#archive_msg{timestamp = TS, packet = El, nick = Nick,
peer = Peer, id = ID},
MsgType, JidRequestor, #jid{lserver = LServer} = JidArchive) -> MsgType, JidRequestor, #jid{lserver = LServer} = JidArchive) ->
Pkt2 = maybe_update_from_to(Pkt1, JidRequestor, JidArchive, Peer, MsgType, try xmpp:decode(El, ?NS_CLIENT, [ignore_els]) of
Nick), Pkt1 ->
El = case Pkt2 of Pkt2 = set_stanza_id(Pkt1, JidArchive, ID),
#xmlel{attrs = Attrs} -> Pkt3 = maybe_update_from_to(
Attrs1 = lists:keystore(<<"xmlns">>, 1, Attrs, Pkt2, JidRequestor, JidArchive, Peer, MsgType, Nick),
{<<"xmlns">>, ?NS_CLIENT}), Delay = #delay{stamp = TS, from = jid:make(LServer)},
Pkt2#xmlel{attrs = Attrs1}; {ok, #forwarded{xml_els = [xmpp:encode(Pkt3)], delay = Delay}}
_ -> catch _:{xmpp_codec, Why} ->
xmpp:encode(Pkt2) ?ERROR_MSG("Failed to decode raw element ~p from message "
end, "archive of user ~s: ~s",
#forwarded{xml_els = [El], [El, jid:to_string(JidArchive), xmpp:format_error(Why)]),
delay = #delay{stamp = TS, from = jid:make(LServer)}}. {error, invalid_xml}
end.
maybe_update_from_to(#xmlel{} = El, JidRequestor, JidArchive, Peer,
{groupchat, _, _} = MsgType, Nick) ->
Pkt = xmpp:decode(El, ?NS_CLIENT, [ignore_els]),
maybe_update_from_to(Pkt, JidRequestor, JidArchive, Peer, MsgType, Nick);
maybe_update_from_to(#message{sub_els = Els} = Pkt, JidRequestor, JidArchive, maybe_update_from_to(#message{sub_els = Els} = Pkt, JidRequestor, JidArchive,
Peer, {groupchat, Role, Peer, {groupchat, Role,
#state{config = #config{anonymous = Anon}}}, #state{config = #config{anonymous = Anon}}},

View File

@ -160,12 +160,17 @@ select(_LServer, JidRequestor,
SortedMsgs = lists:keysort(#archive_msg.timestamp, Msgs), SortedMsgs = lists:keysort(#archive_msg.timestamp, Msgs),
{FilteredMsgs, IsComplete} = filter_by_rsm(SortedMsgs, RSM), {FilteredMsgs, IsComplete} = filter_by_rsm(SortedMsgs, RSM),
Count = length(Msgs), Count = length(Msgs),
Result = {lists:map( Result = {lists:flatmap(
fun(Msg) -> fun(Msg) ->
{Msg#archive_msg.id, case mod_mam:msg_to_el(
binary_to_integer(Msg#archive_msg.id), Msg, MsgType, JidRequestor, JidArchive) of
mod_mam:msg_to_el(Msg, MsgType, JidRequestor, {ok, El} ->
JidArchive)} [{Msg#archive_msg.id,
binary_to_integer(Msg#archive_msg.id),
El}];
{error, _} ->
[]
end
end, FilteredMsgs), IsComplete, Count}, end, FilteredMsgs), IsComplete, Count},
erlang:garbage_collect(), erlang:garbage_collect(),
Result. Result.

View File

@ -168,28 +168,12 @@ select(LServer, JidRequestor, #jid{luser = LUser} = JidArchive,
end, end,
{lists:flatmap( {lists:flatmap(
fun([TS, XML, PeerBin, Kind, Nick]) -> fun([TS, XML, PeerBin, Kind, Nick]) ->
try case make_archive_el(
#xmlel{} = El = fxml_stream:parse_element(XML), TS, XML, PeerBin, Kind, Nick,
Now = usec_to_now(binary_to_integer(TS)), MsgType, JidRequestor, JidArchive) of
PeerJid = jid:tolower(jid:from_string(PeerBin)), {ok, El} ->
T = case Kind of [{TS, binary_to_integer(TS), El}];
<<"">> -> chat; {error, _} ->
null -> chat;
_ -> jlib:binary_to_atom(Kind)
end,
[{TS, binary_to_integer(TS),
mod_mam:msg_to_el(#archive_msg{timestamp = Now,
packet = El,
type = T,
nick = Nick,
peer = PeerJid},
MsgType, JidRequestor, JidArchive)}]
catch _:Err ->
?ERROR_MSG("failed to parse data from SQL: ~p. "
"The data was: "
"timestamp = ~s, xml = ~s, "
"peer = ~s, kind = ~s, nick = ~s",
[Err, TS, XML, PeerBin, Kind, Nick]),
[] []
end end
end, Res1), IsComplete, binary_to_integer(Count)}; end, Res1), IsComplete, binary_to_integer(Count)};
@ -319,3 +303,51 @@ get_max_direction_id(RSM) ->
_ -> _ ->
{undefined, undefined, <<>>} {undefined, undefined, <<>>}
end. end.
-spec make_archive_el(binary(), binary(), binary(), binary(),
binary(), _, jid(), jid()) ->
{ok, xmpp_element()} | {error, invalid_jid |
invalid_timestamp |
invalid_xml}.
make_archive_el(TS, XML, Peer, Kind, Nick, MsgType, JidRequestor, JidArchive) ->
case fxml_stream:parse_element(XML) of
#xmlel{} = El ->
try binary_to_integer(TS) of
TSInt ->
case jid:from_string(Peer) of
#jid{} = PeerJID ->
Now = usec_to_now(TSInt),
PeerLJID = jid:tolower(PeerJID),
T = case Kind of
<<"">> -> chat;
null -> chat;
_ -> jlib:binary_to_atom(Kind)
end,
mod_mam:msg_to_el(
#archive_msg{timestamp = Now,
id = TS,
packet = El,
type = T,
nick = Nick,
peer = PeerLJID},
MsgType, JidRequestor, JidArchive);
error ->
?ERROR_MSG("Malformed 'peer' field with value "
"'~s' detected for user ~s in table "
"'archive': invalid JID",
[Peer, jid:to_string(JidArchive)]),
{error, invalid_jid}
end
catch _:_ ->
?ERROR_MSG("Malformed 'timestamp' field with value '~s' "
"detected for user ~s in table 'archive': "
"not an integer",
[TS, jid:to_string(JidArchive)]),
{error, invalid_timestamp}
end;
{error, {_, Reason}} ->
?ERROR_MSG("Malformed 'xml' field with value '~s' detected "
"for user ~s in table 'archive': ~s",
[XML, jid:to_string(JidArchive), Reason]),
{error, invalid_xml}
end.