Created
March 31, 2016 16:07
-
-
Save stevenlivz/d666200595a23c42b2a662fef87bf281 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-module(mod_echobot). | |
-author('Steven Livingstone-Perez'). | |
-behavior(gen_server). | |
-behavior(gen_mod). | |
%% Interface | |
-export([start_link/2]). | |
-export([start/2, | |
stop/1, | |
init/1, | |
handle_call/3, | |
handle_cast/2, | |
handle_info/2, | |
terminate/2, | |
code_change/3]). | |
-export([route/3]). | |
-include("ejabberd.hrl"). | |
-include("logger.hrl"). | |
-define(PROCNAME, ejabberd_mod_bot). | |
-define(BOTNAME, echo_bot). | |
%% Implementation | |
start_link(Host, Opts) -> | |
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), | |
gen_server:start_link({local, Proc}, ?MODULE, [Host, Opts], []). | |
start(Host, Opts) -> | |
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), | |
ChildSpec = {Proc, | |
{?MODULE, start_link, [Host, Opts]}, | |
temporary, | |
1000, | |
worker, | |
[?MODULE]}, | |
supervisor:start_child(ejabberd_sup, ChildSpec). | |
stop(Host) -> | |
Proc = gen_mod:get_module_proc(Host, ?PROCNAME), | |
gen_server:call(Proc, stop), | |
supervisor:terminate_child(ejabberd_sup, Proc), | |
supervisor:delete_child(ejabberd_sup, Proc). | |
init([Host, Opts]) -> | |
error_logger:info_msg("ECHO_BOT: Starting echo_bot", []), | |
%?DEBUG("ECHO_BOT: Starting echo_bot", []), | |
% add a new virtual host / subdomain "echo".example.com | |
MyHost = gen_mod:get_opt_host(Host, Opts, <<"echo.@HOST@">>), | |
ejabberd_router:register_route(MyHost, {apply, ?MODULE, route}), | |
{ok, Host}. | |
handle_call(stop, _From, Host) -> | |
{stop, normal, ok, Host}. | |
handle_cast(_Msg, Host) -> | |
{noreply, Host}. | |
handle_info(_Msg, Host) -> | |
{noreply, Host}. | |
terminate(_Reason, Host) -> | |
ejabberd_router:unregister_route(Host), | |
ok. | |
code_change(_OldVsn, Host, _Extra) -> | |
{ok, Host}. | |
% Checks a presence /subscription/ is a part of this. | |
% we may want to impliment blacklisting / some kind of | |
% protection here to prevent malicious users | |
%route(From, #jid{luser = ?BOTNAME} = To, {xmlelement, "presence", _, _} = Packet) -> | |
route(From, To, {xmlelement, "presence", _, _} = Packet) -> | |
case xml:get_tag_attr_s("type", Packet) of | |
"subscribe" -> | |
send_presence(To, From, "subscribe"); | |
"subscribed" -> | |
send_presence(To, From, "subscribed"), | |
send_presence(To, From, ""); | |
"unsubscribe" -> | |
send_presence(To, From, "unsubscribed"), | |
send_presence(To, From, "unsubscribe"); | |
"unsubscribed" -> | |
send_presence(To, From, "unsubscribed"); | |
"" -> | |
send_presence(To, From, ""); | |
"unavailable" -> | |
ok; | |
"probe" -> | |
send_presence(To, From, ""); | |
_Other -> | |
error_logger:info_msg("Other kind of presence~n~p", [Packet]) | |
%?INFO_MSG("Other kind of presence~n~p", [Packet]) | |
end, | |
ok; | |
%route(From, #jid{luser = ?BOTNAME} = To, {xmlelement, "message", _, _} = Packet) -> | |
route(From, To, {xmlelement, "message", _, _} = Packet) -> | |
case xml:get_subtag_cdata(Packet, "body") of | |
"" -> | |
ok; | |
Body -> | |
case xml:get_tag_attr_s("type", Packet) of | |
"error" -> | |
error_logger:info_msg("Received error message~n~p -> ~p~n~p", [From, To, Packet]); | |
%?ERROR_MSG("Received error message~n~p -> ~p~n~p", [From, To, Packet]); | |
_ -> | |
echo(To, From, strip_bom(Body)) | |
end | |
end, | |
ok. | |
%% HELPER FUNCTIONS | |
strip_bom([239,187,191|C]) -> C; | |
strip_bom(C) -> C. | |
send_presence(From, To, "") -> | |
ejabberd_router:route(From, To, {xmlelement, "presence", [], []}); | |
send_presence(From, To, TypeStr) -> | |
ejabberd_router:route(From, To, {xmlelement, "presence", [{"type", TypeStr}], []}). | |
echo(From, To, Body) -> | |
send_message(From, To, "chat", Body). | |
send_message(From, To, TypeStr, BodyStr) -> | |
XmlBody = {xmlelement, "message", | |
[{"type", TypeStr}, | |
{"from", jlib:jid_to_string(From)}, | |
{"to", jlib:jid_to_string(To)}], | |
[{xmlelement, "body", [], | |
[{xmlcdata, BodyStr}]}]}, | |
ejabberd_router:route(From, To, XmlBody). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi Steven
I'm stumbling upon the same problem with echo bots like you. I've tried to debug and get a working version on internet and I have even found your question on stackoverflow. Now with your code (the same above) I have a bot but I cannot send anything to it.
I have the ejabberd domain/host: chat.domain.local, I'm using a common xmpp client (psi) and after a service discovery I have added "echo.chat.domain.local" to my service Agent/Transport list in the xmpp client. I can send messages but I cannot see anything back.
I'm using ejabberd v16.02 (x64) on a CentOS 6.7 machine.
Here're the error messages I can see in my ejabberd.log
2016-04-21 17:53:02.327 [error] <0.6289.0>@ejabberd_router:route:77 {function_clause,[{mod_echobot,route,[{jid,<<"ben">>,<<"chat.domain.local">>,<<"MyCustomResourceID">>,<<"ben">>,<<"chat.domain.local">>,<<"MyCustomResourceID">>},{jid,<<>>,<<"echo.chat.domain.local">>,<<>>,<<>>,<<"echo.chat.domain.local">>,<<>>},{xmlel,<<"message">>,[{<<"xml:lang">>,<<"en">>},{<<"type">>,<<"chat">>},{<<"to">>,<<"echo.chat.domain.local">>},{<<"id">>,<<"aae0a">>}],[{xmlcdata,<<"\n">>},{xmlel,<<"body">>,[],[{xmlcdata,<<"test 123">>}]},{xmlcdata,<<"\n">>},{xmlel,<<"active">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/chatstates">>}],[]},{xmlcdata,<<"\n">>},{xmlel,<<"nick">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/nick">>}],[{xmlcdata,<<"Ben">>}]},{xmlcdata,<<"\n">>}]}],[{file,"src/mod_echobot.erl"},{line,105}]},{ejabberd_router,route,3,[{file,"src/ejabberd_router.erl"},{line,75}]},{ejabberd_c2s,check_privacy_route,5,[{file,"src/ejabberd_c2s.erl"},{line,2113}]},{ejabberd_c2s,session_established2,2,[{file,"src/ejabberd_c2s.erl"},{line,1278}]},{p1_fsm,handle_msg,10,[{file,"src/p1_fsm.erl"},{line,582}]},{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,237}]}]}
when processing: {{jid,<<"ben">>,<<"chat.domain.local">>,<<"MyCustomResourceID">>,<<"ben">>,<<"chat.domain.local">>,<<"MyCustomResourceID">>},{jid,<<>>,<<"echo.chat.domain.local">>,<<>>,<<>>,<<"echo.chat.domain.local">>,<<>>},{xmlel,<<"message">>,[{<<"xml:lang">>,<<"en">>},{<<"type">>,<<"chat">>},{<<"to">>,<<"echo.chat.domain.local">>},{<<"id">>,<<"aae0a">>}],[{xmlcdata,<<"\n">>},{xmlel,<<"body">>,[],[{xmlcdata,<<"test 123">>}]},{xmlcdata,<<"\n">>},{xmlel,<<"active">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/chatstates">>}],[]},{xmlcdata,<<"\n">>},{xmlel,<<"nick">>,[{<<"xmlns">>,<<"http://jabber.org/protocol/nick">>}],[{xmlcdata,<<"Ben">>}]},{xmlcdata,<<"\n">>}]}}
It seems there's a problem with the route() function but I cannot understand why, are you able to test it or can you tell me something more about it ? It's running with your own code (downloaded on 2016/04/21)
Cheers
Ben