0

I want to build a customer support chat app. There are users and an admin. Below admin there are multiple sub-admins. Initially the chat is initiated with admin only, but if the admin is offline I need to route the message to sub-admins.

offline_message_hook hook serves the purpose. I'll check if the To is admin, then I need to route the Packet to one of the sub-admins. How do I route/send the packet to other user within offline_message_hook. In short how do I change the To from the packet so that the packet is re-directed to the new sub-admin?

Here is what I've tried:-

offline_message_hook({_Action, #message{from = Peer, to = To} = Pkt} = Acc) ->
    ?INFO_MSG("Inside offline", []),
    ejabberd_router:route(From, To, Packet),
    ok.

I'm using ejabberd 17.04.105.

Update

After following user2610053's advice, I did this:-

-spec offline_message_hook({any(), message()}) -> {any(), message()}.
offline_message_hook({_Action, Msg} = Acc) ->
    ejabberd_router:route(xmpp:set_to(Msg, 'praful@localhost')),
    {routed, Msg}.

Following is the error:-

15:13:12.291 [error] failed to route packet:
#message{id = <<"purple187f6502">>,type = chat,lang = <<"en">>,
         from = {jid,<<"praful2">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>,
                     <<"praful2">>,<<"localhost">>,<<"Prafuls-MacBook-Pro">>},
         to = praful@localhost,subject = [],
         body = [#text{lang = <<>>,data = <<"co=umon">>}],
         thread = undefined,
         sub_els = [{xmlel,<<"active">>,
                           [{<<"xmlns">>,
                             <<"http://jabber.org/protocol/chatstates">>}],
                           []}],
         meta = #{ip => {0,0,0,0,0,0,0,1}}}
Reason = {error,{{badrecord,jid},[{ejabberd_router,do_route,1,[{file,"src/ejabberd_router.erl"},{line,343}]},{ejabberd_router,route,1,[{file,"src/ejabberd_router.erl"},{line,87}]},{mod_sunshine,offline_message_hook,1,[{file,"src/mod_sunshine.erl"},{line,24}]},{ejabberd_hooks,safe_apply,4,[{file,"src/ejabberd_hooks.erl"},{line,380}]},{ejabberd_hooks,run_fold1,4,[{file,"src/ejabberd_hooks.erl"},{line,364}]},{ejabberd_sm,route,1,[{file,"src/ejabberd_sm.erl"},{line,138}]},{ejabberd_local,route,1,[{file,"src/ejabberd_local.erl"},{line,116}]},{ejabberd_router,do_route,1,[{file,"src/ejabberd_router.erl"},{line,348}]}]}}

The user praful@localhost exist. Please advice what exactly is wrong?

Update2 - `UserReceivePacket Hook

In user_receive_packet packet hook, upon using the same function ejabberd_router:route(xmpp:set_to(Packet, jid:decode("praful@localhost"))), it throws an error saying :-

Hook user_receive_packet crashed when running mod_sunshine:user_receive_packet/1:
** Reason = {error,function_clause,[{jid,decode,[{file,"src/jid.erl"},{line,132}],["praful@localhost"]},{mod_sunshine,user_receive_packet,[{file,"src/mod_sunshine.erl"},{line,29}],1},{ejabberd_hooks,safe_apply,[{file,"src/ejabberd_hooks.erl"},{line,380}],4},{ejabberd_hooks,run_fold1,[{file,"src/ejabberd_hooks.erl"},{line,364}],4},{ejabberd_c2s,process_info,[{file,"src/ejabberd_c2s.erl"},{line,231}],2},{ejabberd_hooks,safe_apply,[{file,"src/ejabberd_hooks.erl"},{line,380}],4},{ejabberd_hooks,run_fold1,[{file,"src/ejabberd_hooks.erl"},{line,364}],4},{xmpp_stream_in,handle_info,[{file,"src/xmpp_stream_in.erl"},{line,373}],2}]}

So, I read about function_clause, but couldnt understand the same. What exactly is wrong over here?

Praful Bagai
  • 16,684
  • 50
  • 136
  • 267

1 Answers1

1

I think you're asking about xmpp:set_to/2. Here is an example:

offline_message_hook({_Action, Msg} = Acc) ->
  SubAdmins = get_sub_admins(Msg#message.to),
  lists:foreach(
    fun(Admin) ->
      ejabberd_router:route(xmpp:set_to(Msg, Admin))
    end, Admins),
  {routed, Msg}.
user2610053
  • 516
  • 2
  • 7
  • I followed your approach and did exactly the same, but I'm getting an error saying `failed to route packet`. Kindly see the updated question and provide your valuable advice. – Praful Bagai May 26 '17 at 10:35
  • In `to` field there should be record `#jid{}` and you're putting an atom there. Please read for details: https://github.com/processone/xmpp/blob/master/doc/API.md#jid – user2610053 May 26 '17 at 12:08
  • 1
    Used `jid:decode` and it worked like a charm. Thanks a lot :) – Praful Bagai May 26 '17 at 13:08
  • Hey, I'm receiving another error `function_clause` while routing the message in a similar way. Can you please have a look at the updated question. Thanks :) – Praful Bagai Jun 13 '17 at 19:04
  • 1
    You should use `binary()` type as input for `jid:decode/1`, not a `string()`. – user2610053 Jun 13 '17 at 22:16
  • Wow. Thanks. :) – Praful Bagai Jun 14 '17 at 05:44
  • Can you also provide your valuable advice to this post. https://stackoverflow.com/questions/44543033/ejabberd-create-a-custom-stanza-get-set-subtags It will be very helpful!!! Thanks – Praful Bagai Jun 14 '17 at 13:26