Ejabberd - 为自定义命令运行 SQL 查询

Posted

技术标签:

【中文标题】Ejabberd - 为自定义命令运行 SQL 查询【英文标题】:Ejabberd - Run SQL Query for Custom Command 【发布时间】:2020-08-07 07:41:18 【问题描述】:

我正在尝试在mod_admin_extra.erl 中创建自定义命令。获取 2 个 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;

我通过 this 线程了解 IQ 查询的工作原理,并希望通过命令和 API 构建类似的东西。

如何在上述函数中触发查询以获取 2 个 JID 的对话之间的消息??

我的回答是字典列表:-

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

我会反过来使用相同的命令让 POST API 获取消息。

更新

根据@Badlop 提供的建议,我更新了我的函数

 % ----------------- Custom Command Get Message ----------------------
 #ejabberd_commandsname = 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;"

【问题讨论】:

【参考方案1】:

这是独立于数据库的:

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
).

【讨论】:

我尝试了您的解决方案,但它返回错误。看来我很近,但到目前为止。我已经用错误和遵循的步骤更新了问题。请看一看。 有什么建议@Badlop?非常感谢您的帮助! 我对代码进行了更多研究,我相信这是因为格式错误。我已经更新了格式,但仍然无法正确返回响应。请看一下。【参考方案2】:

嗯,你还远,命令结果错误,调用结果必须处理。这个呢?

$ 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))
+     || _, _, #forwardedsub_els = [Subels] <- Stanzas].
+
 get_commands_spec() ->
-    [#ejabberd_commandsname = 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_commandsname = delete_old_mam_messages, tags = [purge],
            desc = "Delete MAM messages older than DAYS",
            longdesc = "Valid message TYPEs: "
                   "\"chat\", \"groupchat\", \"all\".",

【讨论】:

以上是关于Ejabberd - 为自定义命令运行 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

如何在 EF Core 5 中为自定义 SQL 配置导航属性

使用自定义 mysql 模式的模块扩展 ejabberd?

ejabberd 'make' 通过“无法运行已编译的 C 程序”

将 PySpark 命令转换为自定义函数

Swift之深入解析如何将代码添加为自定义LLDB命令

Ejabberd - 处理 SQL 查询时出错