简体   繁体   English

用erlang解析ejabberd数据包

[英]Parsing ejabberd packet with erlang

I am using ejabberd18.09 for IM application. 我正在将ejabberd18.09用于IM应用程序。 the application has few features that needed to add extensions to the ejabberd(xmpp) messages. 该应用程序具有一些功能,无需为ejabberd(xmpp)消息添加扩展名。

I created a custom module on the offline_message_hook to capture the offline messages and send them to my own url for further processing . 我在offline_message_hook上创建了一个自定义模块,以捕获脱机消息并将其发送到我自己的url进行进一步处理。

the messages that are being sent to ejabberd have different cases depending on the type of message as following 根据邮件的类型,发送到ejabberd的邮件有不同的情况,如下所示

if I am sending a photo the message will be as following 如果我要发送照片,则消息如下

<message xmlns="jabber:client" xml:lang="en" to="someuserjid2" from="{someuserjid}" type="chat" id="mP8tO-8">
   <mtype xmlns="urn:xmpp:mtype" value="media" />
   <url xmlns="urn:xmpp:url" id="myId" mediaType="photo" link="myphotourl.com" />
   <body>thumbnail string</body>
</message>

when sending a text 发送文字时

<message xmlns="jabber:client" xml:lang="en" to="someuserjid2" from="{someuserjid}" type="chat" id="mP8tO-8">
   <mtype xmlns="urn:xmpp:mtype" value="text" />
   <body>Hi John</body>
</message>

when sending a location 发送位置时

<message xmlns="jabber:client" xml:lang="en" to="someuserjid2" from="{someuserjid}" type="chat" id="mP8tO-8">
   <mtype xmlns="urn:xmpp:mtype" value="location" />
   <location xmlns="urn:xmpp:geo" lat="1.2" lng="2.2 " />
   <body>location thumbnailstring</body>
</message>

I used a .erl code to read the body and the message ID as following 我使用.erl代码读取正文和消息ID,如下所示

create_message(_From, _To, Packet) when (Packet#message.type == chat) and (Packet#message.body /= []) ->
  Body = fxml:get_path_s(Packet, [{elem, list_to_binary("body")}, cdata]),
  MessageId = fxml:get_tag_attr_s(list_to_binary("id"), Packet),
  post_offline_message(_From, _To, Body, MessageId),
  ok.

what I want is how (in erlang) can I read the value attribute of the mtype tag the create a switch statement on ( media, location , test ) values so that I can process each message separately ? 我想要的是如何(在erlang中)读取mtype标记的value属性,从而在(media,location,test)值上创建一个switch语句,以便我可以分别处理每条消息?

You can pass attr in the list of arguments to fxml:get_path_s to pick out the value of an attribute of a certain element: 您可以在参数列表fxml:get_path_s attr传递给fxml:get_path_s以挑选出某个元素的属性值:

case fxml:get_path_s(Packet, [{elem, <<"mtype">>}, {attr, <<"value">>}]) of
    <<"media">> ->
        %% handle media...
    <<"location">> ->
        %% handle location...
    <<"">> ->
        %% no mtype element, or missing value attribute!
        %% let's handle that case as well
end

Another thought: do you actually need the <mtype> element? 另一个想法:您实际上是否需要<mtype>元素? It looks like you could just check for the presence of a <location> or <url> element. 看来您只需要检查<location><url>元素的存在即可。 You could do it like this: 您可以这样做:

case fxml:get_subtag(Packet, <<"location">>) of
    false ->
        %% No location. Try url
        case fxml:get_subtag(Packet, <<"url">>) of
            false ->
                %% Neither location nor url
                %% Handle this case somehow...
            Url ->
                %% Do something with Url...
        end
    Location ->
        %% Do something with Location...
end

The code gets a bit messy, since we need to nest the case expressions, unlike the previous version where we just checked the value of a single expression. 代码有点混乱,因为我们需要嵌套case表达式,而之前的版本中我们只检查了单个表达式的值。 One thing you could do is writing a helper function that tries each element in turn: 您可以做的一件事是编写一个辅助函数,依次尝试每个元素:

find_one_of(Packet, []) ->
    not_found;
find_one_of(Packet, [ElementName | Rest]) ->
    case fxml:get_subtag(Packet, ElementName) of
        false ->
            find_one_of(Packet, Rest);
        Element ->
            {ElementName, Element}
    end.

And then call it like: 然后像这样调用它:

case find_one_of(Packet, [<<"location">>, <<"url">>]) of
    {<<"location">>, Location} ->
        %% Do something with Location...
    {<<"url">>, Url} ->
        %% Do something with Url...
    not_found ->
        %% Neither location nor url
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM