So I got a hook in my code that says if an offline message is received, it will start up this function.
offline_msg_received(From, To, Packet) ->
The Packet has code looking like this:
{message,<<"purple2d957668">>,chat,<<>>,undefined,{jid,<<"admin">>,<<"localhost">>,<<"5280">>,<<"admin">>,<<"localhost">>,<<"5280">>},[],[{text,<<>>,<<"Hello">>}],undefined,[{xmlel,<<"active">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/chatstates">>}],[]}],#{}}
What I wanted out of this is the part containing my message. Which is:
[{text,<<>>,<<"Hello">>}]
I could get this part out with a pattern matching against the whole package variable. However, when I tried a pattern matching with my message, it says bad argument. I know that if I specify a variable with just
{text,<<>>,<<"Hello">>}
then I can pattern match against that. From my understanding, seeing [ ] around something means it is a list, or a string.
I can show some of the code here.
{P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11} = Packet, %% P8 is the message I want.
?INFO_MSG("----------------------P8: ~p~n", P8), %% This shows {text,<<>>,<<"Hello">>}
{A, B, C} = P8, %% This gives me a badmatch error.
Now, if I were to instead do this manually in the code shell:
{text,<<>>,<<"Hello">>} = P8,
{A, B, C} = P8,
Then the code works, and puts <<"Hello">> in the C variable.
My guess is that the [ ] around it in the "Package" variable has something to do with my badmatch error, but for some reason those symbols don't appear when I print out P8. Does anyone have a good suggestion why it doesn't work? I am guessing it has something to do with the hidden [ ], since otherwise it looks identical to my shell code test.
Thanks. This is my first time asking questions here, so I hope I didn't do anything wrong.
The reason you're not seeing the square brackets around the value in your INFO_MSG
call is that INFO_MSG
expects a list of values, not just a single value. In the code above it happens to work out, since the format string only contains a single directive, and the value is a list of one element, so that's why the brackets are silently stripped out.
The INFO_MSG
macro works the same as io:format
, so you could try this out in the shell:
%% two arguments
io:format("~p ~p\n", [foo, bar]).
%% one argument - we still need square brackets
io:format("~p\n", [foo]).
You're doing this the hard way :) message
and text
are records defined in xmpp_codec.hrl. If you don't have the record definitions loaded in the shell, records look like a tuple with lots of elements, but if you load the record definitions, your message looks like this instead:
1> rr("include/xmpp_codec.hrl").
[address,addresses,adhoc_actions,adhoc_command,adhoc_note,
bind,block,block_list,bob_data,bookmark_conference,
bookmark_storage,bookmark_url,bytestreams,caps,
carbons_disable,carbons_enable,carbons_private,
carbons_received,carbons_sent,chatstate,client_id,compress,
compress_failure,compressed,compression,csi,db_feature,
db_result,db_verify|...]
2> {message,<<"purple2d957668">>,chat,<<>>,undefined,{jid,<<"admin">>,<<"localhost">>,<<"5280">>,<<"admin">>,<<"localhost">>,<<"5280">>},[],[{text,<<>>,<<"Hello">>}],undefined,[{xmlel,<<"active">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/chatstates">>}],[]}],#{}}.
#message{id = <<"purple2d957668">>,type = chat,lang = <<>>,
from = undefined,
to = {jid,<<"admin">>,<<"localhost">>,<<"5280">>,
<<"admin">>,<<"localhost">>,<<"5280">>},
subject = [],
body = [#text{lang = <<>>,data = <<"Hello">>}],
thread = undefined,
sub_els = [{xmlel,<<"active">>,
[{<<"xmlns">>,
<<"http://jabber.org/protocol/chatstates">>}],
[]}],
meta = #{}}
The data you are looking for is in the body
field.
Let's assign this record to the variable M
and extract the body field:
4> Body = M#message.body.
[#text{lang = <<>>,data = <<"Hello">>}]
So that's a list containing one text
record. Let's extract the data
field from that:
6> [#text{data = Data}] = Body.
[#text{lang = <<>>,data = <<"Hello">>}]
7> Data.
<<"Hello">>
That's how it works in the shell - load the record definitions with the rr
function. When writing a module that uses record definitions, you'd need to include the hrl
file:
-include_lib("xmpp/include/xmpp_codec.hrl").
The -include_lib
directory will look for the xmpp
application on the load path, and search for the file xmpp_codec.hrl
inside its include
directory. You may need to specify the code path to the compiler, something like erlc -pa path/to/xmpp/ebin my_module.erl
- note that the ebin
directory inside the application should be on the code path.