Push notification Ejabberd:处理脱机消息的简单模块中出错
我安装了Ejabberd 17.01,需要在收件人脱机时推送通知。这似乎是一项常见的任务,使用定制Ejabberd模块的解决方案随处可见。然而,我就是不能让它运行。首先,这里是我的脚本:Push notification Ejabberd:处理脱机消息的简单模块中出错,push-notification,erlang,xmpp,ejabberd,Push Notification,Erlang,Xmpp,Ejabberd,我安装了Ejabberd 17.01,需要在收件人脱机时推送通知。这似乎是一项常见的任务,使用定制Ejabberd模块的解决方案随处可见。然而,我就是不能让它运行。首先,这里是我的脚本: -module(mod_offline_push). -behaviour(gen_mod). -export([start/2, stop/1]). -export([push_message/3]). -include("ejabberd.hrl"). -
-module(mod_offline_push).
-behaviour(gen_mod).
-export([start/2, stop/1]).
-export([push_message/3]).
-include("ejabberd.hrl").
-include("logger.hrl").
-include("jlib.hrl").
start(Host, _Opts) ->
?INFO_MSG("mod_offline_push loading", []),
ejabberd_hooks:add(offline_message_hook, Host, ?MODULE, push_message, 10),
ok.
stop(Host) ->
?INFO_MSG("mod_offline_push stopping", []),
ejabberd_hooks:add(offline_message_hook, Host, ?MODULE, push_message, 10),
ok.
push_message(From, To, Packet) ->
?INFO_MSG("mod_offline_push -> push_message", [To]),
Type = fxml:get_tag_attr_s(<<"type">>, Packet), % Supposedly since 16.04
%Type = xml:get_tag_attr_s(<<"type">>, Packet), % Supposedly since 13.XX
%Type = xml:get_tag_attr_s("type", Packet),
%Type = xml:get_tag_attr_s(list_to_binary("type"), Packet),
?INFO_MSG("mod_offline_push -> push_message", []),
ok.
我是新来的Ejabberd和Erlang,所以我不能真正解释错误,但是{mod_offline\u push,push_message,3,[{file,“mod_offline\u push.erl”},{Line,33}]}
中提到的第33行肯定是调用get_tag\u attr\u s
的行
2017/01/27更新:因为这让我很头疼——我还是不太开心——我在这里发布了我当前的工作模块,希望它能帮助其他人。我的安装程序是Ejabberd17.01,运行在Ubuntu 16.04上。我尝试过但失败的大多数东西似乎都适用于Ejabberd的旧版本:
-module(mod_fcm_fork).
-behaviour(gen_mod).
%% public methods for this module
-export([start/2, stop/1]).
-export([push_notification/3]).
%% included for writing to ejabberd log file
-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp_codec.hrl").
%% Copied this record definition from jlib.hrl
%% Including "xmpp_codec.hrl" and "jlib.hrl" resulted in errors ("XYZ already defined")
-record(jid, {user = <<"">> :: binary(),
server = <<"">> :: binary(),
resource = <<"">> :: binary(),
luser = <<"">> :: binary(),
lserver = <<"">> :: binary(),
lresource = <<"">> :: binary()}).
start(Host, _Opts) ->
?INFO_MSG("mod_fcm_fork loading", []),
% Providing the most basic API to the clients and servers that are part of the Inets application
inets:start(),
% Add hook to handle message to user who are offline
ejabberd_hooks:add(offline_message_hook, Host, ?MODULE, push_notification, 10),
ok.
stop(Host) ->
?INFO_MSG("mod_fcm_fork stopping", []),
ejabberd_hooks:add(offline_message_hook, Host, ?MODULE, push_notification, 10),
ok.
push_notification(From, To, Packet) ->
% Generate JID of sender and receiver
FromJid = lists:concat([binary_to_list(From#jid.user), "@", binary_to_list(From#jid.server), "/", binary_to_list(From#jid.resource)]),
ToJid = lists:concat([binary_to_list(To#jid.user), "@", binary_to_list(To#jid.server), "/", binary_to_list(To#jid.resource)]),
% Get message body
MessageBody = Packet#message.body,
% Check of MessageBody is not empty
case MessageBody/=[] of
true ->
% Get first element (no idea when this list can have more elements)
[First | _ ] = MessageBody,
% Get message data and convert to string
MessageBodyText = binary_to_list(First#text.data),
send_post_request(FromJid, ToJid, MessageBodyText);
false ->
?INFO_MSG("mod_fcm_fork -> push_notification: MessageBody is empty",[])
end,
ok.
send_post_request(FromJid, ToJid, MessageBodyText) ->
%?INFO_MSG("mod_fcm_fork -> send_post_request -> MessageBodyText = ~p", [Demo]),
Method = post,
PostURL = gen_mod:get_module_opt(global, ?MODULE, post_url,fun(X) -> X end, all),
% Add data as query string. Not nice, query body would be preferable
% Problem: message body itself can be in a JSON string, and I couldn't figure out the correct encoding.
URL = lists:concat([binary_to_list(PostURL), "?", "fromjid=", FromJid,"&tojid=", ToJid,"&body=", edoc_lib:escape_uri(MessageBodyText)]),
Header = [],
ContentType = "application/json",
Body = [],
?INFO_MSG("mod_fcm_fork -> send_post_request -> URL = ~p", [URL]),
% ADD SSL CONFIG BELOW!
%HTTPOptions = [{ssl,[{versions, ['tlsv1.2']}]}],
HTTPOptions = [],
Options = [],
httpc:request(Method, {URL, Header, ContentType, Body}, HTTPOptions, Options),
ok.
-模块(mod_fcm_fork)。
-行为(gen_mod)。
%%此模块的公共方法
-导出([开始/2,停止/1])。
-导出([推送通知/3])。
%%包括用于写入ejabberd日志文件
-包括(“ejabberd.hrl”)。
-包括(“logger.hrl”)。
-包括(“xmpp_codec.hrl”)。
%%从jlib.hrl复制了此记录定义
%%包括“xmpp_codec.hrl”和“jlib.hrl”会导致错误(“XYZ已定义”)
-记录(jid,{user=::binary(),
服务器=::二进制(),
资源=::二进制(),
luser=::binary(),
lserver=::binary(),
lresource=::binary()})。
开始(主机,选择)->
?信息信息(“模块fcm货叉装载”,[]),
%为作为iNet应用程序一部分的客户端和服务器提供最基本的API
inets:start(),
%添加钩子以处理脱机用户的消息
ejabberd挂钩:添加(离线消息挂钩、主机、模块、推送通知、10),
好啊
停止(主机)->
?信息信息(“模块fcm叉停止”,[]),
ejabberd挂钩:添加(离线消息挂钩、主机、模块、推送通知、10),
好啊
推送通知(从、到、数据包)->
%生成发送方和接收方的JID
FromJid=list:concat([二进制到二进制列表(从#jid.user)、“@”、二进制到二进制列表(从#jid.server)、“/”、二进制到二进制列表(从#jid.resource)],
ToJid=list:concat([binary-to-list(to-jid.user),“@”,binary-to-list(to-jid.server),“/”,binary-to-list(to-jid.resource)],
%获取消息正文
MessageBody=数据包#message.body,
%MessageBody的检查不为空
案例MessageBody/=[]共
正确->
%获取第一个元素(不知道此列表何时可以包含更多元素)
[First | |]=MessageBody,
%获取消息数据并转换为字符串
MessageBodyText=binary_to_列表(第一个#text.data),
发送post请求(FromJid、ToJid、MessageBodyText);
错误->
信息消息(“mod\u fcm\u fork->push\u通知:消息体为空”,[])
完,,
好啊
发送发布请求(FromJid、ToJid、MessageBodyText)->
%信息消息(“mod\u fcm\u fork->send\u post\u request->MessageBodyText=~p”,[Demo]),
方法=员额,
postrl=gen_mod:get_module_opt(全局、模块、post_url、fun(X)->X end,all),
%将数据添加为查询字符串。不太好,最好是查询主体
%问题:消息体本身可能是JSON字符串,我无法找出正确的编码。
URL=lists:concat([binary_to_list(postrl),“?”,“fromjid=”,fromjid,&tojid=”,tojid,&body=”,edoc_lib:escape_uri(MessageBodyText)],
页眉=[],
ContentType=“application/json”,
正文=[],
信息消息(“mod\u fcm\u fork->send\u post\u request->URL=~p”,[URL]),
%在下面添加SSL配置!
%HTTPOptions=[{ssl,[{versions,['tlsv1.2']}]}],
HTTPOptions=[],
选项=[],
httpc:request(方法,{URL,Header,ContentType,Body},HTTPOptions,Options),
好啊
最新的方法似乎是使用xmpp:get\u type/1
:
Type = xmpp:get_type(Packet),
它返回一个atom,在本例中,它是normal
实际上,它失败了,因为第二个arg数据包
传递给fxml:get\u tag\u attr\s in push\u message函数
{message,<<>>,normal,<<>>,
{jid,<<"homer">>,<<"xxx.xxx.xxx.xxx">>,<<"conference">>,
<<"homer">>,<<"xxx.xxx.xxx.xxx">>,<<"conference">>},
{jid,<<"carl">>,<<"xxx.xxx.xxx.xxx">>,<<>>,<<"carl">>,
<<"xxx.xxx.xxx.xxx">>,<<>>},
[],
[{text,<<>>,<<"sfsdfsdf">>}],
undefined,[],#{}}
包括此文件并仅使用
Type = Packet#message.type
或者,如果需要二进制值
Type = erlang:atom_to_binary(Packet#message.type, utf8)
太好了,谢谢!作为一个新手,我太不了解错误信息了。我想这些变化是伴随着最新的Ejabberd版本而来的?因为即使是去年年底的搜索结果也使用了我尝试过的方法。我不知道,也许是最新版本,我使用的是14.07除了数据包
,我如何处理从
和到
?像到#jid.luser
这样的东西会抛出错误。这仅在我还包括jlib.hrl
,但它似乎与cose的xmpp\u codec.hrl
冲突时才有效,您需要包括jlib.hrl,这是一个很好的解决方案code
ToJid=Packet#message.to,ToLUser=ToJid#jid.lusercode
我已经尝试过了,但正如我所写的,这些to包括(xmpp\u codec.hrl
和jlib.hrel
)与一些记录已经定义的错误冲突。我最后做的是只包含xmpp\u codec.hrl
,并将jid记录的定义-record(jid,{user=::binary(),…
)添加到我自己的文件中。它似乎有点“脏”但它是这样工作的。一旦我解决了所有其他小问题,我会更新我的问题。作为一个附加问题:我现在如何获得正文
。它不适用于xmpp:get_body(Packet)
,我认为应该根据body=Packet\message.body
或者,如果需要文本:xmpp:get_text(Packet#message.body)
您能帮我回答以下问题吗:
Type = Packet#message.type
Type = erlang:atom_to_binary(Packet#message.type, utf8)