问题
I'm trying to make a custom command in mod_admin_extra.erl
. to fetch messages between 2 JIDs.
My command will look like this:-
ejabberdctl get_messages HOST FROM TO START_TIME END_TIME
The SQL query will be like:-
select * from archive where (username = FROM and bare_peer = TO) OR (username=TO and bare_peer = FROM) where created_at BETWEEN START_TIME AND END_TIME;
I went through this thread to understand how IQ query works and want to build a similar sort of a thing via the command and API.
How do I fire the query in the above function so as to fetch the messages between the conversations of 2 JIDs??
My response would be a list of dictionaries:-
[{from: jid1, to: jid2, body: Hello, created_at: T1}]
I would be in turn using the same command for the POST API to fetch messages.
UPDATE
As per the suggestion provided by @Badlop, I updated my function with
% ----------------- Custom Command Get Message ----------------------
#ejabberd_commands{name = get_message, tags = [stanza],
desc = "Get messages from a local or remote bare of full JID",
longdesc = "Get messages of a specific JID sent to a JID",
module = ?MODULE, function = get_message,
args = [{host, binary}, {from, binary}, {to, binary},
{start_time, binary}, {end_time, binary}],
args_example = [<<"localhost">>, <<"admin">>, <<"user1">>,
<<"2015-07-00T00:00:00Z">>, <<"2015-07-029T13:23:54Z">>],
args_desc = ["Host", "From JID", "Receiver JID", "Start Time", "End Time"],
result = {result, {
tuple, [{messages, list, {message, {tuple,
[
{timestamp, string},
{xml, string},
{txt, string},
{peer, integer},
{kind, integer},
{nick, string}
]}}},
{status, string},
{count, integer}]}}
},
% ----------------- Custom Command Ends -----------------------------
This is my function that gets called when the command is received.
% ----------------- Custom Function Get Message ----------------------
get_message(Host, From, To, StartTime, EndTime) ->
mod_mam:select(
Host,
jid:make(From, Host),
jid:make(From, Host),
[{start, xmpp_util:decode_timestamp(StartTime)},
{'end', xmpp_util:decode_timestamp(EndTime)},
{with, jid:make(To, Host)}],
#rsm_set{},
chat,
all
).
% ----------------- Custom Function Get Message ----------------------
However, it returns an error response:-
Unhandled exception occurred executing the command:
** exception error: no function clause matching
ejabberd_ctl:format_result([],
{messages,list,
{message,
{tuple,
[{timestamp,string},
{xml,string},
{peer,integer},
{kind,integer},
{nick,string}]}}}) (src/ejabberd_ctl.erl, line 405)
in function ejabberd_ctl:format_result/2 (src/ejabberd_ctl.erl, line 461)
in call from ejabberd_ctl:try_call_command/4 (src/ejabberd_ctl.erl, line 321)
in call from ejabberd_ctl:process2/4 (src/ejabberd_ctl.erl, line 274)
in call from ejabberd_ctl:process/2 (src/ejabberd_ctl.erl, line 252)
in call from rpc:'-handle_call_call/6-fun-0-'/5 (rpc.erl, line 197)
The query printed in the logs in as follow:-
2020-04-24 21:57:13.717746+05:30 [debug] SQL: "SELECT timestamp, xml, peer, kind, nick FROM archive WHERE username=E'admin' and server_host=E'localhost' and bare_peer=E'test@localhost' and timestamp >= 1587692943312536 and timestamp <= 1587779343312536 ORDER BY timestamp ASC ;"
2020-04-24 21:57:13.726745+05:30 [debug] SQL: "SELECT COUNT(*) FROM archive WHERE username=E'admin' and server_host=E'localhost' and bare_peer=E'test@localhost' and timestamp >= 1587692943312536 and timestamp <= 1587779343312536;"
回答1:
This is database independent:
mod_mam:select(
<<"localhost">>,
jid:make(<<"user1">>, <<"localhost">>),
jid:make(<<"user1">>, <<"localhost">>),
[{start, xmpp_util:decode_timestamp(<<"2020-04-24T14:37:25Z">>)},
{'end', xmpp_util:decode_timestamp(<<"2020-04-24T14:37:30Z">>)},
{with, jid:make(<<"user2">>,<<"localhost">>)}],
#rsm_set{},
chat,
all
).
回答2:
Umm, you were still far away, the command result was wrong, and the call result must be processed. what about this?
$ ejabberdctl get_mam_messages user1@localhost user2@localhost 2020-04-27T00:00:00Z 2020-04-27T23:59:59Z
Required patch:
diff --git a/src/mod_mam.erl b/src/mod_mam.erl
index 08a4059b4..d2d74913c 100644
--- a/src/mod_mam.erl
+++ b/src/mod_mam.erl
@@ -42,6 +42,7 @@
get_room_config/4, set_room_option/3, offline_message/1, export/1,
mod_options/1, remove_mam_for_user_with_peer/3, remove_mam_for_user/2,
is_empty_for_user/2, is_empty_for_room/3, check_create_room/4,
+ get_messages_command/4,
process_iq/3, store_mam_message/7, make_id/0, wrap_as_mucsub/2, select/7]).
-include("xmpp.hrl").
@@ -1355,8 +1356,29 @@ get_jids(undefined) ->
get_jids(Js) ->
[jid:tolower(jid:remove_resource(J)) || J <- Js].
+get_messages_command(From, To, StartTime, EndTime) ->
+ FromJid = jid:decode(From),
+ {Stanzas, _, _} =
+ mod_mam:select(
+ FromJid#jid.lserver, FromJid, FromJid,
+ [{start, xmpp_util:decode_timestamp(StartTime)},
+ {'end', xmpp_util:decode_timestamp(EndTime)},
+ {with, jid:decode(To)}],
+ #rsm_set{}, chat, all),
+ [fxml:element_to_binary(xmpp:encode(Subels))
+ || {_, _, #forwarded{sub_els = [Subels]}} <- Stanzas].
+
get_commands_spec() ->
- [#ejabberd_commands{name = delete_old_mam_messages, tags = [purge],
+ [#ejabberd_commands{
+ name = get_mam_messages, tags = [mam],
+ desc = "Get archived messages of an account with another contact",
+ module = ?MODULE, function = get_messages_command,
+ args = [{from, binary}, {to, binary}, {start, binary}, {'end', binary}],
+ args_example = [<<"user1@localhost">>, <<"user2@example.org">>,
+ <<"2020-04-27T00:00:00Z">>, <<"2020-04-27T23:59:59Z">>],
+ args_desc = ["Local JID", "Contact JID", "Start Time", "End Time"],
+ result = {messages, {list, {message, string}}}},
+ #ejabberd_commands{name = delete_old_mam_messages, tags = [purge],
desc = "Delete MAM messages older than DAYS",
longdesc = "Valid message TYPEs: "
"\"chat\", \"groupchat\", \"all\".",
来源:https://stackoverflow.com/questions/61396406/ejabberd-run-sql-query-for-custom-command