aboutsummaryrefslogtreecommitdiff
path: root/src/mod_announce.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mod_announce.erl')
-rw-r--r--src/mod_announce.erl178
1 files changed, 178 insertions, 0 deletions
diff --git a/src/mod_announce.erl b/src/mod_announce.erl
new file mode 100644
index 000000000..29ac65e87
--- /dev/null
+++ b/src/mod_announce.erl
@@ -0,0 +1,178 @@
+%%%----------------------------------------------------------------------
+%%% File : mod_announce.erl
+%%% Author : Alexey Shchepin <alexey@sevcom.net>
+%%% Purpose : Manage announce messages
+%%% Created : 11 Aug 2003 by Alexey Shchepin <alexey@sevcom.net>
+%%% Id : $Id$
+%%%----------------------------------------------------------------------
+
+-module(mod_announce).
+-author('alexey@sevcom.net').
+
+-behaviour(gen_mod).
+
+-export([start/1,
+ init/0,
+ stop/0,
+ announce/3,
+ send_motd/1]).
+
+-include("ejabberd.hrl").
+-include("jlib.hrl").
+
+-record(motd, {id, packet}).
+-record(motd_users, {luser, dummy = []}).
+
+-define(PROCNAME, ejabberd_announce).
+
+start(_) ->
+ mnesia:create_table(motd, [{disc_copies, [node()]},
+ {attributes, record_info(fields, motd)}]),
+ mnesia:create_table(motd_users, [{disc_copies, [node()]},
+ {attributes, record_info(fields, motd_users)}]),
+ ejabberd_hooks:add(local_send_to_resource_hook,
+ ?MODULE, announce, 50),
+ ejabberd_hooks:add(user_available_hook,
+ ?MODULE, send_motd, 50),
+ register(?PROCNAME, proc_lib:spawn(?MODULE, init, [])).
+
+init() ->
+ loop().
+
+loop() ->
+ receive
+ {announce_online, From, To, Packet} ->
+ announce_online(From, To, Packet),
+ loop();
+ {announce_motd, From, To, Packet} ->
+ announce_motd(From, To, Packet),
+ loop();
+ {announce_motd_update, From, To, Packet} ->
+ announce_motd_update(From, To, Packet),
+ loop();
+ {announce_motd_delete, From, To, Packet} ->
+ announce_motd_delete(From, To, Packet),
+ loop();
+ _ ->
+ loop()
+ end.
+
+stop() ->
+ ejabberd_hooks:delete(local_send_to_resource_hook,
+ ?MODULE, announce, 50),
+ ejabberd_hooks:delete(sm_register_connection_hook,
+ ?MODULE, send_motd, 50),
+ exit(whereis(?PROCNAME), stop),
+ ok.
+
+announce(From, To, Packet) ->
+ case To of
+ #jid{luser = "", lresource = Res} ->
+ {xmlelement, Name, _Attrs, _Els} = Packet,
+ case {Res, Name} of
+ {"announce/online", "message"} ->
+ ?PROCNAME ! {announce_online, From, To, Packet},
+ stop;
+ {"announce/motd", "message"} ->
+ ?PROCNAME ! {announce_motd, From, To, Packet},
+ stop;
+ {"announce/motd/update", "message"} ->
+ ?PROCNAME ! {announce_motd_update, From, To, Packet},
+ stop;
+ {"announce/motd/delete", "message"} ->
+ ?PROCNAME ! {announce_motd_delete, From, To, Packet},
+ stop;
+ _ ->
+ ok
+ end;
+ _ ->
+ ok
+ end.
+
+announce_online(From, To, Packet) ->
+ Access = gen_mod:get_module_opt(?MODULE, access, none),
+ case acl:match_rule(Access, From) of
+ deny ->
+ Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED),
+ ejabberd_router:route(To, From, Err);
+ allow ->
+ announce_online1(ejabberd_sm:dirty_get_sessions_list(), Packet)
+ end.
+
+announce_online1(Sessions, Packet) ->
+ Server = ?MYNAME,
+ Local = jlib:make_jid("", Server, ""),
+ lists:foreach(
+ fun({U, R}) ->
+ Dest = jlib:make_jid(U, Server, R),
+ ejabberd_router:route(Local, Dest, Packet)
+ end, Sessions).
+
+announce_motd(From, To, Packet) ->
+ Access = gen_mod:get_module_opt(?MODULE, access, none),
+ case acl:match_rule(Access, From) of
+ deny ->
+ Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED),
+ ejabberd_router:route(To, From, Err);
+ allow ->
+ announce_motd_update(Packet),
+ Sessions = ejabberd_sm:dirty_get_sessions_list(),
+ announce_online1(Sessions, Packet),
+ F = fun() ->
+ lists:foreach(
+ fun({U, _R}) ->
+ mnesia:write(#motd_users{luser = U})
+ end, Sessions)
+ end,
+ mnesia:transaction(F)
+ end.
+
+announce_motd_update(From, To, Packet) ->
+ Access = gen_mod:get_module_opt(?MODULE, access, none),
+ case acl:match_rule(Access, From) of
+ deny ->
+ Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED),
+ ejabberd_router:route(To, From, Err);
+ allow ->
+ announce_motd_update(Packet)
+ end.
+
+announce_motd_update(Packet) ->
+ announce_motd_delete(),
+ F = fun() ->
+ mnesia:write(#motd{id = motd, packet = Packet})
+ end,
+ mnesia:transaction(F).
+
+announce_motd_delete(From, To, Packet) ->
+ Access = gen_mod:get_module_opt(?MODULE, access, none),
+ case acl:match_rule(Access, From) of
+ deny ->
+ Err = jlib:make_error_reply(Packet, ?ERR_NOT_ALLOWED),
+ ejabberd_router:route(To, From, Err);
+ allow ->
+ announce_motd_delete()
+ end.
+
+announce_motd_delete() ->
+ mnesia:clear_table(motd),
+ mnesia:clear_table(motd_users).
+
+send_motd(#jid{luser = LUser} = JID) ->
+ case catch mnesia:dirty_read({motd, motd}) of
+ [#motd{packet = Packet}] ->
+ case catch mnesia:dirty_read({motd_users, LUser}) of
+ [#motd_users{}] ->
+ ok;
+ _ ->
+ Local = jlib:make_jid("", ?MYNAME, ""),
+ ejabberd_router:route(Local, JID, Packet),
+ F = fun() ->
+ mnesia:write(#motd_users{luser = LUser})
+ end,
+ mnesia:transaction(F)
+ end;
+ _ ->
+ ok
+ end.
+