【问题标题】:Ejabberd: error in simple module to handle offline messagesEjabberd:处理离线消息的简单模块中的错误
【发布时间】:2017-06-10 15:58:06
【问题描述】:

我有一个 Ejabberd 17.01 安装,我需要在其中推送通知以防收件人离线。这似乎是一项常见的任务,使用定制的 Ejabberd 模块的解决方案随处可见。但是,我只是不让它运行。首先,这是我的脚本:

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

问题是方法push_message中的Type = ...行;如果没有该行,则会记录最后一条信息消息(因此该挂钩肯定有效)。在网上浏览时,我可以找到各种函数调用来从Packet 中提取元素。据我了解,随着新版本的发布,它随着时间的推移而变化。但这并不好,所有变体都会导致某种错误。当前方式返回:

2017-01-25 20:38:08.701 [error] <0.21678.0>@ejabberd_hooks:run1:332 {function_clause,[{fxml,get_tag_attr_s,[<<"type">>,{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,[],#{}}],[{file,"src/fxml.erl"},{line,169}]},{mod_offline_push,push_message,3,[{file,"mod_offline_push.erl"},{line,33}]},{ejabberd_hooks,safe_apply,3,[{file,"src/ejabberd_hooks.erl"},{line,382}]},{ejabberd_hooks,run1,3,[{file,"src/ejabberd_hooks.erl"},{line,329}]},{ejabberd_sm,route,3,[{file,"src/ejabberd_sm.erl"},{line,126}]},{ejabberd_local,route,3,[{file,"src/ejabberd_local.erl"},{line,110}]},{ejabberd_router,route,3,[{file,"src/ejabberd_router.erl"},{line,87}]},{ejabberd_c2s,check_privacy_route,5,[{file,"src/ejabberd_c2s.erl"},{line,1886}]}]}

running hook: {offline_message_hook,[{jid,<<"homer">>,<<"xxx.xxx.xxx.xxx">>,<<"conference">>,<<"homer">>,<<"xxx.xxx.xxx.xxx">>,<<"conference">>},{jid,<<"carl">>,<<"xxx.xxx.xxx.xxx">>,<<>>,<<"carl">>,<<"xxx.xxx.xxx.xxx">>,<<>>},{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,[],#{}}]}

我是新的 Ejabberd 和 Erlang,所以我无法真正解释错误,但 {mod_offline_push,push_message,3,[{file,"mod_offline_push.erl"}, {line,33}]} 中提到的第 33 行绝对是调用 get_tag_attr_s 的行。

2017 年 1 月 27 日更新: 因为这让我很头疼——而且我仍然不是很开心——我在这里发布我当前的工作模块,希望它可能会有所帮助其他。我的设置是在 Ubuntu 16.04 上运行的 Ejabberd 17.01。我尝试过但失败的大多数东西似乎都适用于旧版本的 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.

【问题讨论】:

标签: push-notification erlang xmpp ejabberd


【解决方案1】:

实际上,它在 push_message 函数中传递给 fxml:get_tag_attr_s 的第二个参数 Packet 失败

{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,[],#{}}

因为它不是xmlel

看起来它是在 tools/xmpp_codec.hrl 中定义的记录“消息” 带有 > id 并输入“正常”

xmpp_codec.hrl
    -record(message, {id :: binary(),
                      type = normal :: 'chat' | 'error' | 'groupchat' | 'headline' | 'normal',
                      lang :: binary(),
                      from :: any(),
                      to :: any(),
                      subject = [] :: [#text{}],
                      body = [] :: [#text{}],
                      thread :: binary(),
                      error :: #error{},
                      sub_els = [] :: [any()]}).

包含此文件并仅使用

Type =  Packet#message.type

或者,如果您期望二进制值

 Type =  erlang:atom_to_binary(Packet#message.type, utf8)

【讨论】:

  • 完美,谢谢!我太不了解新手了,无法理解错误消息。我假设这些更改是最新的 Ejabberd 版本附带的?因为即使是去年年底的搜索结果也使用了我尝试过的方式。
  • 我不知道,可能是最新版本,我用的是14.07
  • 除了Packet,我该如何处理FromToTo#jid.luser 之类的东西会抛出错误。这仅在我还包含jlib.hrl 时才有效,但它似乎与xmpp_codec.hrl 发生冲突。
  • 当然你需要包含 jlib.hrl,这是一个很好的解决方案。 code ToJid = Packet#message.to, ToLUser = ToJid#jid.luser code
  • 我已经尝试过了,但正如我所写,这些包含(xmpp_codec.hrljlib.hrel)与一些记录已经定义的错误发生冲突。我最终做的是只包含xmpp_codec.hrl 并将jid 记录-record(jid, {user = &lt;&lt;""&gt;&gt; :: binary(), ... 的定义添加到我自己的文件中。这似乎有点“脏”,但它是这样工作的。一旦我解决了所有其他小怪癖,我会更新我的问题。
【解决方案2】:

最新的方法似乎是xmpp:get_type/1

Type = xmpp:get_type(Packet),

它返回一个原子,在本例中为normal

【讨论】:

  • 作为附加问题:我现在如何获得body。它不适用于xmpp:get_body(Packet),我认为它应该根据process-one.net/docs/exmpp/devdoc/trunk/…
  • Body = Packet#message.body 或者,如果您需要文本:xmpp:get_text(Packet#message.body)
猜你喜欢
  • 2017-05-05
  • 1970-01-01
  • 2016-02-28
  • 1970-01-01
  • 2015-01-13
  • 2016-08-26
  • 2016-09-07
  • 2016-08-13
  • 2016-08-19
相关资源
最近更新 更多