Ejabberd — запуск SQL-запроса для пользовательской команды

Я пытаюсь создать пользовательскую команду в mod_admin_extra.erl. для получения сообщений между двумя JID.

Моя команда будет выглядеть так: -

ejabberdctl get_messages HOST FROM TO START_TIME END_TIME

SQL-запрос будет выглядеть так: -

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;

Я прошел эту ветку, чтобы понять, как работает IQ-запрос, и создать что-то подобное с помощью команды и API.

Как запустить запрос в приведенной выше функции, чтобы получить сообщения между диалогами двух JID??

Мой ответ будет списком словарей: -

[{from: jid1, to: jid2, body: Hello, created_at: T1}]

Я бы, в свою очередь, использовал ту же команду для POST API для получения сообщений.

ОБНОВЛЕНИЕ

Согласно предложению @Badlop, я обновил свою функцию с помощью

 % ----------------- 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 -----------------------------

Это моя функция, которая вызывается при получении команды.

% ----------------- 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 ----------------------

Однако он возвращает ответ об ошибке: -

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)

Запрос, напечатанный в журналах, выглядит следующим образом: -

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;"

person PythonEnthusiast    schedule 23.04.2020    source источник


Ответы (2)


Это не зависит от базы данных:

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
).
person Badlop    schedule 24.04.2020
comment
Я попробовал ваше решение, и оно возвращает ошибку. Кажется, я близко и все же так далеко. Я обновил вопрос с ошибкой и последующими шагами. Пожалуйста, посмотрите. - person PythonEnthusiast; 24.04.2020
comment
Любое предложение @Badlop? Ваша помощь очень ценится!! - person PythonEnthusiast; 25.04.2020
comment
Я еще немного изучил код и думаю, что это из-за ошибки форматирования. Я обновил свое форматирование, но все еще не могу правильно вернуть ответ. Пожалуйста, посмотрите. - person PythonEnthusiast; 26.04.2020

Эмм, вы были еще далеко, результат команды был неверным, а результат звонка нужно обработать. что насчет этого?

$ ejabberdctl get_mam_messages user1@localhost user2@localhost 2020-04-27T00:00:00Z 2020-04-27T23:59:59Z

Требуемый патч:

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">>, <<"[email protected]">>,
+           <<"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\".",
person Badlop    schedule 27.04.2020