如何通过IQ Stanza在Ejabberd中获取指定时间戳后两用户的消息?
在Ejabberd中通过IQ Stanza获取指定时间戳后的用户间消息
Ejabberd没有原生的IQ Stanza直接支持该需求,但可以基于内置的消息归档模块mod_mam,通过自定义扩展模块实现该功能。
实现步骤
1. 启用消息归档模块
首先确保mod_mam已在ejabberd配置文件(ejabberd.yml)中启用,它负责存储用户的聊天记录,是查询的基础:
modules: mod_mam: default: always assume_mam_usage: true
2. 编写自定义IQ处理模块
需要开发一个Erlang模块,监听自定义IQ命名空间,处理查询请求并返回结果。核心逻辑包括:
- 解析请求中的两个用户JID、起始时间戳参数
- 调用
mod_mam的API查询符合条件的消息 - 将结果封装为IQ响应返回
核心代码片段:
-module(mod_mam_custom_query). -behaviour(gen_mod). -export([start/2, stop/1, process_iq/1]). start(Host, _Opts) -> ejabberd_hooks:add(iq_get, Host, ?MODULE, process_iq, 50), ok. stop(Host) -> ejabberd_hooks:delete(iq_get, Host, ?MODULE, process_iq, 50), ok. process_iq(#iq{type = get, xmlns = <<"urn:xmpp:mam:custom:query">>, from = From, sub_el = SubEl} = IQ) -> % 解析请求参数 {xmlel, _, _, Params} = SubEl, User1Bin = proplists:get_value(<<"user1">>, Params), User2Bin = proplists:get_value(<<"user2">>, Params), StartTsBin = proplists:get_value(<<"start">>, Params), User1 = jid:from_binary(User1Bin), User2 = jid:from_binary(User2Bin), StartTs = binary_to_integer(StartTsBin), % 权限校验:仅允许消息双方或管理员查询 case lists:member(From, [User1, User2]) orelse ejabberd_auth:is_admin(From) of false -> IQ#iq{type = error, sub_el = [ejabberd_errors:not_authorized()]}; true -> % 调用mod_mam查询指定条件的消息 Messages = mod_mam:lookup_messages(jid:server(From), #{ start => StartTs, with => [User1, User2], direction => both }), % 构造响应XML ResponseEl = #xmlel{name = <<"result">>, xmlns = <<"urn:xmpp:mam:custom:query">>, children = format_messages(Messages)}, IQ#iq{type = result, sub_el = [ResponseEl]} end; process_iq(IQ) -> IQ. % 将消息列表格式化为XML元素 format_messages(Messages) -> lists:map(fun(#{id := Id, from := From, to := To, body := Body, timestamp := Ts}) -> #xmlel{name = <<"message">>, children = [ #xmlel{name = <<"id">>, children = [#xmlcdata{content = Id}]}, #xmlel{name = <<"from">>, children = [#xmlcdata{content = jid:to_binary(From)}]}, #xmlel{name = <<"to">>, children = [#xmlcdata{content = jid:to_binary(To)}]}, #xmlel{name = <<"body">>, children = [#xmlcdata{content = Body}]}, #xmlel{name = <<"timestamp">>, children = [#xmlcdata{content = integer_to_binary(Ts)}]} ]} end, Messages).
3. 客户端发送IQ请求示例
客户端需要发送符合自定义命名空间的IQ Stanza,示例如下:
<iq type="get" id="mam_custom_1" xmlns="jabber:client"> <query xmlns="urn:xmpp:mam:custom:query"> <user1>alice@example.com</user1> <user2>bob@example.com</user2> <start>1690000000</start> </query> </iq>
4. 部署自定义模块
将编写好的模块编译后,放置到Ejabberd的模块目录,并在ejabberd.yml中添加模块配置:
modules: mod_mam_custom_query: {}
内容的提问来源于stack exchange,提问作者rangarajan
相关产品推荐
相关产品推荐

