您好,我正在尝试创建一个自定义 ejabberd 模块,一旦消息到达服务器,该模块就会向消息发送者发回确认信息。基本上与 Whatsapp 具有相同的功能,带有一个复选标记。 在我的客户端,我将 smack 与 Java 结合使用。我有一个自定义节扩展,需要节侦听器中的某种格式。
-module(mod_acknowledgment).
-behaviour(gen_mod).
%% Exported functions
-export([start/2, stop/1, on_user_send_packet/4, depends/2, mod_doc/0, mod_options/1]).
%% Records
-record(xmlel, {name, attrs = [], children = []}).
-record(jid, {user = <<"">>, server = <<"">>, resource = <<>>}).
-define(NS_ARRIVED, <<"urn:xmpp:ack">>).
%% Start module and register hooks
start(Host, _Opts) ->
ejabberd_hooks:add(user_send_packet, Host, ?MODULE, on_user_send_packet, 10),
ok.
%% Stop module and unregister hooks
stop(Host) ->
ejabberd_hooks:delete(user_send_packet, Host, ?MODULE, on_user_send_packet, 10),
ok.
%% Dependencies function
depends(_Host, _Opts) ->
[].
%% Documentation function
mod_doc() ->
"This module sends an acknowledgment when a message arrives at the server.".
%% Options function
mod_options(_Host) ->
[].
%% Packet filtering and acknowledgment sending
on_user_send_packet(Packet, _C2SState, From, To) ->
case should_acknowledge(Packet) of
true ->
send_acknowledgment(From, To, Packet);
false ->
ok
end,
Packet.
%% Determine if a packet should trigger an acknowledgment
should_acknowledge(#xmlel{name = <<"message">>, attrs = Attrs, children = Children}) ->
case lists:keyfind(<<"type">>, 1, Attrs) of
{_, <<"chat">>} ->
%% Check if the message has a body
lists:any(fun(C) -> C#xmlel.name =:= <<"body">> end, Children);
_ ->
false
end;
should_acknowledge(_) ->
false.
%% Send acknowledgment back to the sender
send_acknowledgment(FromJID, ToJID, Packet) ->
%% Extract the message ID to include in the acknowledgment
ReceiptId = xml:get_tag_attr_s(<<"id">>, Packet),
AckPacket = #xmlel{
name = <<"message">>,
attrs = [
{<<"to">>, jid_to_binary(FromJID)},
{<<"from">>, jid_to_binary(ToJID)},
{<<"type">>, <<"chat">>}
],
children = [
#xmlel{name = <<"arrived">>, attrs = [{<<"xmlns">>, ?NS_ARRIVED}, {<<"id">>, ReceiptId}], children = []}
]
},
ejabberd_router:route(ToJID, FromJID, AckPacket),
ok.
%% JID to binary conversion
jid_to_binary(#jid{user = User, server = Server, resource = Resource}) when Resource =:= <<>> ->
<<User/binary, "@", Server/binary>>;
jid_to_binary(#jid{user = User, server = Server, resource = Resource}) ->
<<User/binary, "@", Server/binary, "/", Resource/binary>>.
在我的客户端,我有一个自定义节扩展,如下所示:
package net.chatchap.extensions;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.XmlStringBuilder;
/**
* A custom stanza extension to notify user than a message has arrived at the server
*/
public class ArrivedExtension implements ExtensionElement {
public static final String ELEMENT = "arrived";
public static final String NAMESPACE = "urn:xmpp:ack";
@Override
public String getNamespace() {
return NAMESPACE;
}
@Override
public String getElementName() {
return ELEMENT;
}
@Override
public CharSequence toXML(XmlEnvironment xmlEnvironment) {
return new XmlStringBuilder(this).closeEmptyElement();
}
@Override
public CharSequence toXML() {
return toXML(XmlEnvironment.EMPTY);
}
}
因此自定义模块应该使用钩子来捕获消息,然后将确认返回给服务器 不幸的是,该模块无法工作。 Erlang 不是我的语言,所以我很难接受这个
代码中存在严重的不连贯性,即使是第一天的开发人员也不会执行,但令人惊讶的是,编码风格是完美的。显然该代码将无法工作。看来你使用了一些 AI 程序来编写 Erlang 代码,对吗?
有一些 XEP(XMPP 协议扩展)描述了此类功能如何工作:
不幸的是,这些都没有在 ejabberd 中实现。
与 Whatsapp 的功能基本相同,只是带有一个复选标记。
您计划免费完成此任务,对吧?