1 |
|
%%%---------------------------------------------------------------------- |
2 |
|
%%% File : ejabberd_hooks.erl |
3 |
|
%%% Author : Alexey Shchepin <alexey@process-one.net> |
4 |
|
%%% Purpose : Manage hooks |
5 |
|
%%% Created : 8 Aug 2004 by Alexey Shchepin <alexey@process-one.net> |
6 |
|
%%% |
7 |
|
%%% |
8 |
|
%%% ejabberd, Copyright (C) 2002-2011 ProcessOne |
9 |
|
%%% |
10 |
|
%%% This program is free software; you can redistribute it and/or |
11 |
|
%%% modify it under the terms of the GNU General Public License as |
12 |
|
%%% published by the Free Software Foundation; either version 2 of the |
13 |
|
%%% License, or (at your option) any later version. |
14 |
|
%%% |
15 |
|
%%% This program is distributed in the hope that it will be useful, |
16 |
|
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 |
|
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
18 |
|
%%% General Public License for more details. |
19 |
|
%%% |
20 |
|
%%% You should have received a copy of the GNU General Public License |
21 |
|
%%% along with this program; if not, write to the Free Software |
22 |
|
%%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
23 |
|
%%% |
24 |
|
%%%---------------------------------------------------------------------- |
25 |
|
|
26 |
|
-module(ejabberd_hooks). |
27 |
|
-author('alexey@process-one.net'). |
28 |
|
|
29 |
|
%% External exports |
30 |
|
-export([add/5, |
31 |
|
delete/5, |
32 |
|
add_args/2]). |
33 |
|
|
34 |
|
-export([add/1, |
35 |
|
delete/1]). |
36 |
|
|
37 |
|
-export([gen_hook_fn_wrapper/3]). |
38 |
|
|
39 |
|
-ignore_xref([add/4, delete/4, error_running_hook/3, start_link/0]). |
40 |
|
|
41 |
|
-include("mongoose.hrl"). |
42 |
|
|
43 |
|
-type hook() :: {HookName :: atom(), |
44 |
|
HostType :: mongooseim:host_type() | global, |
45 |
|
Module :: module(), |
46 |
|
Fn :: atom(), |
47 |
|
Priority:: integer()}. |
48 |
|
|
49 |
|
-export_type([hook/0]). |
50 |
|
%%%---------------------------------------------------------------------- |
51 |
|
%%% API |
52 |
|
%%%---------------------------------------------------------------------- |
53 |
|
|
54 |
|
%% @doc Add a module and function to the given hook. |
55 |
|
%% The integer Priority is used to sort the calls: |
56 |
|
%% low numbers are executed before high numbers. |
57 |
|
-spec add(HookName :: atom(), |
58 |
|
HostType :: mongooseim:host_type() | global, |
59 |
|
Module :: module(), |
60 |
|
Function :: atom(), |
61 |
|
Priority :: integer()) -> ok. |
62 |
|
add(HookName, HostType, Module, Function, Priority) -> |
63 |
1171 |
add_hook({HookName, HostType, Module, Function, Priority}). |
64 |
|
|
65 |
|
-spec add([hook()]) -> ok. |
66 |
|
add(Hooks) when is_list(Hooks) -> |
67 |
4360 |
[add_hook(Hook) || Hook <- Hooks], |
68 |
4360 |
ok. |
69 |
|
|
70 |
|
%% @doc Delete a module and function from this hook. |
71 |
|
%% It is important to indicate exactly the same information as when the call was added. |
72 |
|
-spec delete(HookName :: atom(), |
73 |
|
HostType :: mongooseim:host_type() | global, |
74 |
|
Module :: module(), |
75 |
|
Function :: atom(), |
76 |
|
Priority :: integer()) -> ok. |
77 |
|
delete(HookName, HostType, Module, Function, Priority) -> |
78 |
332 |
delete_hook({HookName, HostType, Module, Function, Priority}). |
79 |
|
|
80 |
|
-spec delete([hook()]) -> ok. |
81 |
|
delete(Hooks) when is_list(Hooks) -> |
82 |
2981 |
[delete_hook(Hook) || Hook <- Hooks], |
83 |
2981 |
ok. |
84 |
|
|
85 |
|
-spec add_args(HookParams :: map(), LegacyArgsList :: [term()]) -> |
86 |
|
HookParamsWithArgs :: map(). |
87 |
|
add_args(HookParams, LegacyArgsList) -> |
88 |
232944 |
HookParams#{args => LegacyArgsList}. |
89 |
|
|
90 |
|
%%%---------------------------------------------------------------------- |
91 |
|
%%% Internal functions |
92 |
|
%%%---------------------------------------------------------------------- |
93 |
|
|
94 |
|
-spec add_hook(hook()) -> ok. |
95 |
|
add_hook({HookName, HostType, Module, Function, Priority}) when is_atom(Function) -> |
96 |
28194 |
gen_hook:add_handler(HookName, HostType, |
97 |
|
fun ?MODULE:gen_hook_fn_wrapper/3, |
98 |
|
#{module => Module, function => Function}, |
99 |
|
Priority). |
100 |
|
|
101 |
|
-spec delete_hook(hook()) -> ok. |
102 |
|
delete_hook({HookName, HostType, Module, Function, Priority}) when is_atom(Function) -> |
103 |
16549 |
gen_hook:delete_handler(HookName, HostType, |
104 |
|
fun ?MODULE:gen_hook_fn_wrapper/3, |
105 |
|
#{module => Module, function => Function}, |
106 |
|
Priority). |
107 |
|
|
108 |
|
gen_hook_fn_wrapper(Acc, #{args := Args}, #{module := Module, function := Function}) -> |
109 |
207813 |
case apply(Module, Function, [Acc | Args]) of |
110 |
:-( |
stop -> {stop, stopped}; |
111 |
2586 |
{stop, NewAcc} -> {stop, NewAcc}; |
112 |
205225 |
NewAcc -> {ok, NewAcc} |
113 |
|
end. |