├── .gitignore ├── Emakefile ├── README.md ├── build.sh ├── ebin └── .gitkeep └── src ├── mod_available_post.erl ├── mod_offline_post.erl └── mod_unavailable_post.erl /.gitignore: -------------------------------------------------------------------------------- 1 | ebin/*.beam -------------------------------------------------------------------------------- /Emakefile: -------------------------------------------------------------------------------- 1 | %%% You may need to comment/uncomment the correct section below according to your installation. 2 | %%% 3 | 4 | %%% On OSX with ejabberd installed through homebrew 5 | {'src/mod_offline_post', [{outdir, "ebin"},{i,"/usr/local/Cellar/ejabberd/13.10/lib/ejabberd/include"}]}. 6 | {'src/mod_available_post', [{outdir, "ebin"},{i,"/usr/local/Cellar/ejabberd/13.10/lib/ejabberd/include"}]}. 7 | {'src/mod_unavailable_post', [{outdir, "ebin"},{i,"/usr/local/Cellar/ejabberd/13.10/lib/ejabberd/include"}]}. 8 | 9 | %%% On Ubuntu 10 | %%% {'src/mod_offline_post', [{outdir, "ebin"},{i,"/usr/lib/ejabberd/include/"}]}. 11 | %%% {'src/mod_available_post', [{outdir, "ebin"},{i,"/usr/lib/ejabberd/include/"}]}. 12 | %%% {'src/mod_unavailable_post', [{outdir, "ebin"},{i,"/usr/lib/ejabberd/include/"}]}. 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Purpose: 2 | ========= 3 | 4 | Forward several types of messages as post requests to an arbitrary url. 5 | 6 | mod\_offline\_post forwards messages that are sent to offline users through a post request to a configurable url 7 | mod\_available\_post sends a post request with information about a user that has become available 8 | mod\_unavailable\_post sends a post request with information about a user that has gone offline 9 | 10 | Note: 11 | ========== 12 | 13 | Between ejabberd 2.1.13 and 13.10 there were significant changes and modules compiled for one version don't directly work with the other version. 14 | There is an ejabberd_2.1.13 branch for versions of these modules that work with ejabberd 2.1.13 15 | 16 | Installing: 17 | ========== 18 | 19 | * Make sure you have erlang installed on the machine you are building from 20 | * You probably want this to be the same machine you intend to install/run ejabberd on. I'm not sure about the interoperability of ejabberd/erlang versions. 21 | * Open the Emakefile and change ```/usr/local/Cellar/ejabberd/2.1.10/lib/ejabberd/include``` to the correct path on your machine 22 | * Run the build.sh script to build *.beam files 23 | * Copy the *.beam files from the ebin directory to the location where the other modules are for your server 24 | * Add the configuration shown below to your ejabberd.cfg file, providing the correct values for auth\_token, and post\_url 25 | 26 | Example Configuration: 27 | ===================== 28 | 29 | % configuration for ejabberd upto version 13.10 30 | {mod_offline_post, [ 31 | {auth_token, "offline_post_auth_token"}, 32 | {post_url, "http://localhost:4567/offline_post"} 33 | ]} 34 | {mod_available_post, [ 35 | {auth_token, "mod_available_post"}, 36 | {post_url, "http://localhost:4567/available_post"} 37 | ]} 38 | {mod_unavailable_post, [ 39 | {auth_token, "unavailable_post_auth_token"}, 40 | {post_url, "http://localhost:4567/unavailable_post"} 41 | ]} 42 | 43 | # configuration for ejabberd >= 13.10 44 | mod_offline_post: 45 | auth_token: "offline_post_auth_token" 46 | post_url: "http://localhost:4567/offline_post" 47 | 48 | mod_available_post: 49 | auth_token: "available_post_auth_token" 50 | post_url: "http://localhost:4567/available_post" 51 | 52 | mod_unavailable_post: 53 | auth_token: "unavailable_post_auth_token" 54 | post_url: "http://localhost:4567/unavailable_post" 55 | 56 | Results: 57 | ======== 58 | 59 | The application running at the post_url will receive a post http request with the following form parameters. 60 | 61 | mod_offline_post 62 | "to"=>"adam2@localhost" 63 | "from"=>"adam1" 64 | "body"=>"Does it still work?" 65 | "access_token"=>"offline_post_auth_token" 66 | 67 | mod_available_post 68 | "jabber_id"=>"adam2" 69 | "access_token"=>"mod_available_post" 70 | 71 | mod_unavailable_post 72 | "jabber_id"=>"adam2" 73 | "access_token"=>"unavailable_post_auth_token" 74 | 75 | License 76 | ======== 77 | The modules herein are almost entirely based on mod\_offline\_prowl written by Robert George 78 | They retain the original author's license. 79 | 80 | The original post about mod\_offline\_prowl can be found [here](http://www.unsleeping.com/2010/07/31/prowl-module-for-ejabberd/) 81 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | erl -pa . -pz ebin -make 2 | 3 | -------------------------------------------------------------------------------- /ebin/.gitkeep: -------------------------------------------------------------------------------- 1 | # want this directory to exist -------------------------------------------------------------------------------- /src/mod_available_post.erl: -------------------------------------------------------------------------------- 1 | %%%---------------------------------------------------------------------- 2 | 3 | %%% File : mod_available_post.erl 4 | %%% Author : Adam Duke 5 | %%% Purpose : Forward presence notifications to a url 6 | %%% Created : 12 Feb 2012 by Adam Duke 7 | %%% 8 | %%% 9 | %%% Copyright (C) 2012 Adam Duke 10 | %%% 11 | %%% This program is free software; you can redistribute it and/or 12 | %%% modify it under the terms of the GNU General Public License as 13 | %%% published by the Free Software Foundation; either version 2 of the 14 | %%% License, or (at your option) any later version. 15 | %%% 16 | %%% This program is distributed in the hope that it will be useful, 17 | %%% but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | %%% General Public License for more details. 20 | %%% 21 | %%% You should have received a copy of the GNU General Public License 22 | %%% along with this program; if not, write to the Free Software 23 | %%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 24 | %%% 02111-1307 USA 25 | %%% 26 | %%%---------------------------------------------------------------------- 27 | 28 | -module(mod_available_post). 29 | -author('adam.v.duke@gmail.com'). 30 | 31 | -behaviour(gen_mod). 32 | 33 | -export([start/2, 34 | init/2, 35 | stop/1, 36 | send_available_notice/4]). 37 | 38 | -define(PROCNAME, ?MODULE). 39 | 40 | -include("ejabberd.hrl"). 41 | -include("jlib.hrl"). 42 | -include("logger.hrl"). 43 | 44 | start(Host, Opts) -> 45 | ?INFO_MSG("Starting mod_available_post", [] ), 46 | register(?PROCNAME,spawn(?MODULE, init, [Host, Opts])), 47 | ok. 48 | 49 | %%% set_presence_hook(User, Server, Resource, Packet) -> none 50 | init(Host, _Opts) -> 51 | inets:start(), 52 | ssl:start(), 53 | ejabberd_hooks:add(set_presence_hook, Host, ?MODULE, send_available_notice, 10), 54 | ok. 55 | 56 | stop(Host) -> 57 | ?INFO_MSG("Stopping mod_available_post", [] ), 58 | ejabberd_hooks:delete(set_presence_hook, Host, 59 | ?MODULE, send_available_notice, 10), 60 | ok. 61 | 62 | send_available_notice(User, Server, _Resource, _Packet) -> 63 | Token = gen_mod:get_module_opt(Server, ?MODULE, auth_token, fun(S) -> iolist_to_binary(S) end, list_to_binary("")), 64 | PostUrl = gen_mod:get_module_opt(Server, ?MODULE, post_url, fun(S) -> iolist_to_binary(S) end, list_to_binary("")), 65 | if (Token /= "") -> 66 | Sep = "&", 67 | Post = [ 68 | "jabber_id=", User, Sep, 69 | "access_token=", Token ], 70 | ?INFO_MSG("Sending post request to ~s with body \"~s\"", [PostUrl, Post]), 71 | httpc:request(post, {binary_to_list(PostUrl), [], "application/x-www-form-urlencoded", list_to_binary(Post)},[],[]), 72 | ok; 73 | true -> 74 | ok 75 | end. 76 | 77 | -------------------------------------------------------------------------------- /src/mod_offline_post.erl: -------------------------------------------------------------------------------- 1 | %%%---------------------------------------------------------------------- 2 | 3 | %%% File : mod_offline_post.erl 4 | %%% Author : Adam Duke 5 | %%% Purpose : Forward offline messages to an arbitrary url 6 | %%% Created : 12 Feb 2012 by Adam Duke 7 | %%% 8 | %%% 9 | %%% Copyright (C) 2012 Adam Duke 10 | %%% 11 | %%% This program is free software; you can redistribute it and/or 12 | %%% modify it under the terms of the GNU General Public License as 13 | %%% published by the Free Software Foundation; either version 2 of the 14 | %%% License, or (at your option) any later version. 15 | %%% 16 | %%% This program is distributed in the hope that it will be useful, 17 | %%% but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | %%% General Public License for more details. 20 | %%% 21 | %%% You should have received a copy of the GNU General Public License 22 | %%% along with this program; if not, write to the Free Software 23 | %%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 24 | %%% 02111-1307 USA 25 | %%% 26 | %%%---------------------------------------------------------------------- 27 | 28 | -module(mod_offline_post). 29 | -author('rgeorge@midnightweb.net'). 30 | 31 | -behaviour(gen_mod). 32 | 33 | -export([start/2, 34 | init/2, 35 | stop/1, 36 | send_notice/3]). 37 | 38 | -define(PROCNAME, ?MODULE). 39 | 40 | -include("ejabberd.hrl"). 41 | -include("jlib.hrl"). 42 | -include("logger.hrl"). 43 | 44 | start(Host, Opts) -> 45 | ?INFO_MSG("Starting mod_offline_post", [] ), 46 | register(?PROCNAME,spawn(?MODULE, init, [Host, Opts])), 47 | ok. 48 | 49 | init(Host, _Opts) -> 50 | inets:start(), 51 | ssl:start(), 52 | ejabberd_hooks:add(offline_message_hook, Host, ?MODULE, send_notice, 10), 53 | ok. 54 | 55 | stop(Host) -> 56 | ?INFO_MSG("Stopping mod_offline_post", [] ), 57 | ejabberd_hooks:delete(offline_message_hook, Host, 58 | ?MODULE, send_notice, 10), 59 | ok. 60 | 61 | send_notice(From, To, Packet) -> 62 | Type = xml:get_tag_attr_s(list_to_binary("type"), Packet), 63 | Body = xml:get_path_s(Packet, [{elem, list_to_binary("body")}, cdata]), 64 | Token = gen_mod:get_module_opt(To#jid.lserver, ?MODULE, auth_token, fun(S) -> iolist_to_binary(S) end, list_to_binary("")), 65 | PostUrl = gen_mod:get_module_opt(To#jid.lserver, ?MODULE, post_url, fun(S) -> iolist_to_binary(S) end, list_to_binary("")), 66 | 67 | if (Type == <<"chat">>) and (Body /= <<"">>) -> 68 | Sep = "&", 69 | Post = [ 70 | "to=", To#jid.luser, Sep, 71 | "from=", From#jid.luser, Sep, 72 | "body=", url_encode(binary_to_list(Body)), Sep, 73 | "access_token=", Token], 74 | ?INFO_MSG("Sending post request to ~s with body \"~s\"", [PostUrl, Post]), 75 | httpc:request(post, {binary_to_list(PostUrl), [], "application/x-www-form-urlencoded", list_to_binary(Post)},[],[]), 76 | ok; 77 | true -> 78 | ok 79 | end. 80 | 81 | 82 | %%% The following url encoding code is from the yaws project and retains it's original license. 83 | %%% https://github.com/klacke/yaws/blob/master/LICENSE 84 | %%% Copyright (c) 2006, Claes Wikstrom, klacke@hyber.org 85 | %%% All rights reserved. 86 | url_encode([H|T]) when is_list(H) -> 87 | [url_encode(H) | url_encode(T)]; 88 | url_encode([H|T]) -> 89 | if 90 | H >= $a, $z >= H -> 91 | [H|url_encode(T)]; 92 | H >= $A, $Z >= H -> 93 | [H|url_encode(T)]; 94 | H >= $0, $9 >= H -> 95 | [H|url_encode(T)]; 96 | H == $_; H == $.; H == $-; H == $/; H == $: -> % FIXME: more.. 97 | [H|url_encode(T)]; 98 | true -> 99 | case integer_to_hex(H) of 100 | [X, Y] -> 101 | [$%, X, Y | url_encode(T)]; 102 | [X] -> 103 | [$%, $0, X | url_encode(T)] 104 | end 105 | end; 106 | 107 | url_encode([]) -> 108 | []. 109 | 110 | integer_to_hex(I) -> 111 | case catch erlang:integer_to_list(I, 16) of 112 | {'EXIT', _} -> old_integer_to_hex(I); 113 | Int -> Int 114 | end. 115 | 116 | old_integer_to_hex(I) when I < 10 -> 117 | integer_to_list(I); 118 | old_integer_to_hex(I) when I < 16 -> 119 | [I-10+$A]; 120 | old_integer_to_hex(I) when I >= 16 -> 121 | N = trunc(I/16), 122 | old_integer_to_hex(N) ++ old_integer_to_hex(I rem 16). 123 | 124 | -------------------------------------------------------------------------------- /src/mod_unavailable_post.erl: -------------------------------------------------------------------------------- 1 | %%%---------------------------------------------------------------------- 2 | 3 | %%% File : mod_unavailable_post.erl 4 | %%% Author : Adam Duke 5 | %%% Purpose : Forward offline presence notifications to a url 6 | %%% Created : 12 Feb 2012 by Adam Duke 7 | %%% 8 | %%% 9 | %%% Copyright (C) 2012 Adam Duke 10 | %%% 11 | %%% This program is free software; you can redistribute it and/or 12 | %%% modify it under the terms of the GNU General Public License as 13 | %%% published by the Free Software Foundation; either version 2 of the 14 | %%% License, or (at your option) any later version. 15 | %%% 16 | %%% This program is distributed in the hope that it will be useful, 17 | %%% but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 | %%% General Public License for more details. 20 | %%% 21 | %%% You should have received a copy of the GNU General Public License 22 | %%% along with this program; if not, write to the Free Software 23 | %%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 24 | %%% 02111-1307 USA 25 | %%% 26 | %%%---------------------------------------------------------------------- 27 | 28 | -module(mod_unavailable_post). 29 | -author('adam.v.duke@gmail.com'). 30 | 31 | -behaviour(gen_mod). 32 | 33 | -export([start/2, 34 | init/2, 35 | stop/1, 36 | send_unavailable_notice/4]). 37 | 38 | -define(PROCNAME, ?MODULE). 39 | 40 | -include("ejabberd.hrl"). 41 | -include("jlib.hrl"). 42 | -include("logger.hrl"). 43 | 44 | start(Host, Opts) -> 45 | ?INFO_MSG("Starting mod_unavailable_post", [] ), 46 | register(?PROCNAME,spawn(?MODULE, init, [Host, Opts])), 47 | ok. 48 | 49 | %%% unset_presence_hook(User, Server, Resource, Status) -> void() 50 | init(Host, _Opts) -> 51 | inets:start(), 52 | ssl:start(), 53 | ejabberd_hooks:add(unset_presence_hook, Host, ?MODULE, send_unavailable_notice, 10), 54 | ok. 55 | 56 | stop(Host) -> 57 | ?INFO_MSG("Stopping mod_unavailable_post", [] ), 58 | ejabberd_hooks:delete(unset_presence_hook, Host, 59 | ?MODULE, send_unavailable_notice, 10), 60 | ok. 61 | 62 | send_unavailable_notice(User, Server, _Resource, _Status) -> 63 | Token = gen_mod:get_module_opt(Server, ?MODULE, auth_token, fun(S) -> iolist_to_binary(S) end, list_to_binary("")), 64 | PostUrl = gen_mod:get_module_opt(Server, ?MODULE, post_url, fun(S) -> iolist_to_binary(S) end, list_to_binary("")), 65 | if (Token /= "") -> 66 | Sep = "&", 67 | Post = [ 68 | "jabber_id=", User, Sep, 69 | "access_token=", Token ], 70 | ?INFO_MSG("Sending post request ~p~n",[Post] ), 71 | httpc:request(post, {binary_to_list(PostUrl), [], "application/x-www-form-urlencoded", list_to_binary(Post)},[],[]), 72 | ok; 73 | true -> 74 | ok 75 | end. 76 | 77 | --------------------------------------------------------------------------------