Filtering message packet's body in ejabberd
<p>I am trying to filter undesired messages in ejabberd. I took some direction from <a href="https://stackoverflow.com/questions/1939879/how-to-filter-messages-in-ejabberd">this</a> post. Here is the function snippet which gets executed via filter_packet hook:</p>

<pre><code>check_stanza({_From, _To, #xmlel{name = StanzaType}} = Input) -&gt;
    AccessRule = case StanzaType of
             &lt;&lt;"message"&gt;&gt; -&gt;
           ?DEBUG("filtering packet...~nFrom: ~p~nTo: ~p~nPacket: ~p~nResult: ",
             [_From, _To, Input]),
           Input
           %check_stanza_type(AccessRule, Input)
         end.
</code></pre>

<p>The packet printed in log :</p>

<pre><code>{{jid,&lt;&lt;"test25"&gt;&gt;,&lt;&lt;"localhost"&gt;&gt;,&lt;&lt;"Administrators-MacBook-Pro-6"&gt;&gt;,
&lt;&lt;"test25"&gt;&gt;,&lt;&lt;"localhost"&gt;&gt;,&lt;&lt;"Administrators-MacBook-Pro-6"&gt;&gt;},{jid,
&lt;&lt;"test24"&gt;&gt;,&lt;&lt;"localhost"&gt;&gt;,&lt;&lt;"Administrators-MacBook-Pro-6"&gt;&gt;,
&lt;&lt;"test24"&gt;&gt;,&lt;&lt;"localhost"&gt;&gt;,&lt;&lt;"Administrators-MacBook-Pro-6"&gt;&gt;},{xmlel,
&lt;&lt;"message"&gt;&gt;,[{&lt;&lt;"type"&gt;&gt;,&lt;&lt;"chat"&gt;&gt;},{&lt;&lt;"id"&gt;&gt;,&lt;&lt;"purpleaed2ec77"&gt;&gt;},
{&lt;&lt;"to"&gt;&gt;,&lt;&lt;"test24@localhost/Administrators-MacBook-Pro-6"&gt;&gt;}],[{xmlel,
&lt;&lt;"active"&gt;&gt;,[{&lt;&lt;"xmlns"&gt;&gt;,&lt;&lt;"http://jabber.org/protocol/chatstates"&gt;&gt;}],
[]},{xmlel,&lt;&lt;"body"&gt;&gt;,[],[{xmlcdata,&lt;&lt;"MESSAGE BODY GOES HERE"&gt;&gt;}]}]}}
</code></pre>

<p>My requirement : extract message's body and filter out abusive words. For example, if a user is sending "message body goes here", following sequence should occur:</p>

<ul>
<li>Packet by sender is intercepted by the module, via hook (done)</li>
<li>Message of body is extracted and words are run through a set of data for filtering. the data can be in Mnesia or MySQL (pending)</li>
<li>Altered packet (filtered body) is let through to receiver client </li>
</ul>

<p>the receiver will receive "message body goes ****" if "here" was an undesired word.</p>

<p>I am new to Erlang and its a small community with few good articles out there, so need some advice on best way to achieve the above. There is a great <a href="https://blog.process-one.net/ejabberd-with-elixir-packet-filters/" rel="nofollow noreferrer">post</a> on how to do the same with elixir support , but I want to stick to Erlang. Any help would be appreciated.</p>

<p><strong>UPDATE</strong></p>

<p>thanks Amiramix. Here is the code to replace a particular word: </p>

<pre><code>{xmlel,Syntax,Type,OuterBody} = Xmlel.   


case Syntax -&gt;
    "&lt;&lt;message&gt;&gt;" ,
        XmlelBody = lists:keyfind(&lt;&lt;"body"&gt;&gt;, 2, OuterBody),  %{xmlel,&lt;&lt;"body"&gt;&gt;,[],[{xmlcdata,&lt;&lt;"HI"&gt;&gt;}]}
        {xmlel,BodySyntax,_,Innerbody} = XmlelBody,      % [{xmlcdata,&lt;&lt;"HI"&gt;&gt;}]    
        Body = proplists:get_value(xmlcdata, Innerbody),   %&lt;&lt;"HI"&gt;&gt;


        TmpList = re:replace(Body,&lt;&lt;"HI$"&gt;&gt;,&lt;&lt;"**"&gt;&gt;),
        NewBody = binary:list_to_bin(TmpList),      %&lt;&lt;"**"&gt;&gt;
        NewInnerBody = lists:keyreplace(xmlcdata, 1, Innerbody, {xmlcdata, NewBody}).   %[{xmlcdata,&lt;&lt;"**"&gt;&gt;}]
        NewXmlelBody = setelement(4,XmlelBody,NewInnerBody),   %{xmlel,&lt;&lt;"body"&gt;&gt;,[],[{xmlcdata,&lt;&lt;"**"&gt;&gt;}]}


        NewOuterBody  = lists:keyreplace(&lt;&lt;"body"&gt;&gt;, 2, OuterBody, NewXmlelBody),
        NewXmlel = setelement(4, Xmlel, NewOuterBody)
</code></pre>

<p>Since it would be difficult to keep iterating each word in body over many blocked words, I want to send the extracted body to a python script which does this for me. Any suggestion on how to extract MESSAGE BODY GOES HERE from &lt;&lt;"MESSAGE BODY GOES HERE">> ?</p>