Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for ejabberd 21.12 #8

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 24 additions & 22 deletions src/mod_unread.erl
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@
-author("[email protected]").
-behaviour(gen_mod).
-export([%% ejabberd module API
start/2, stop/1, reload/3, mod_opt_type/1, depends/2,
start/2, stop/1, reload/3, mod_doc/0, mod_opt_type/1, mod_options/1, depends/2,
%% Helpers (database, packet handling)
store/3, drop/4, add_unread_to_mam_result/5,
%% Hooks
on_muc_filter_message/3, on_store_mam_message/6, on_filter_packet/1,
on_muc_filter_message/3, on_store_mam_message/7, on_filter_packet/1,
%% IQ handlers
on_iq/1
]).

-include("ejabberd.hrl").
-include("logger.hrl").
-include("xmpp.hrl").
-include("mod_muc.hrl").
Expand Down Expand Up @@ -41,10 +40,8 @@
%% custom unread functionality.
-spec start(binary(), gen_mod:opts()) -> ok.
start(Host, Opts) ->
%% Initialize the module options
IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)),
%% Initialize the database module
Mod = gen_mod:db_mod(Host, Opts, ?MODULE),
Mod = gen_mod:db_mod(Host, ?MODULE),
Mod:init(Host, Opts),
%% Register the custom XMPP codec
xmpp:register_codec(hg_unread),
Expand All @@ -61,7 +58,7 @@ start(Host, Opts) ->
?MODULE, on_filter_packet, 50),
%% Register IQ handlers
gen_iq_handler:add_iq_handler(ejabberd_local, Host, ?NS_UNREAD,
?MODULE, on_iq, IQDisc),
?MODULE, on_iq),
%% Log the boot up
?INFO_MSG("[UR] Start ejabberd-unread (v~s) for ~s", [?MODULE_VERSION, Host]),
ok.
Expand Down Expand Up @@ -115,18 +112,18 @@ on_muc_filter_message(Acc, _MUCState, _FromNick) -> Acc.
%% Hook on all MAM (message archive management) storage requests to grab the
%% stanza packet and write it to the database. This is the core of this module
%% and takes care of the unread message tracking per user.
-spec on_store_mam_message(message() | drop, binary(), binary(), jid(),
-spec on_store_mam_message(message() | drop, binary(), binary(), jid(), binary(),
chat | groupchat, recv | send) -> message().
on_store_mam_message(#message{to = Conversation} = Packet,
_LUser, _LServer, _Peer, groupchat, recv) ->
_LUser, _LServer, _Peer, _Nick, groupchat, recv) ->
%% Add the current message as unread for all room members.
lists:foreach(fun(User) -> store(User, Conversation, Packet) end,
affiliated_jids(Packet)),
Packet;
on_store_mam_message(#message{from = Conversation, to = User} = Packet,
_LUser, _LServer, _Peer, chat, recv) ->
_LUser, _LServer, _Peer, _Nick, chat, recv) ->
store(User, Conversation, Packet);
on_store_mam_message(Packet, _LUser, _LServer, _Peer, _Type, _Dir) -> Packet.
on_store_mam_message(Packet, _LUser, _LServer, _Peer, _Nick, _Type, _Dir) -> Packet.

%% Handle all IQ packets from the user.
-spec on_iq(iq()) -> iq().
Expand Down Expand Up @@ -160,7 +157,7 @@ on_iq(IQ) -> xmpp:make_error(IQ, xmpp:err_not_allowed()).
-spec on_filter_packet(stanza()) -> stanza().
on_filter_packet(#message{from = From, to = To,
sub_els = [#mam_result{sub_els = [#forwarded{
xml_els = [#xmlel{name = <<"message">>} = El]
sub_els = [#xmlel{name = <<"message">>} = El]
}]}]} = Packet) ->
%% Decode the original MAM message element again to extend it
try xmpp:decode(El) of
Expand Down Expand Up @@ -205,7 +202,7 @@ add_unread_to_mam_result(#message{sub_els = [#mam_result{
%% defined custom stanza elements. Therefore we fiddle directly with the
%% fast_xml module here to overcome the issue.
NewMessage = fxml:append_subtags(Message, [xmpp:encode(Unread)]),
NewForwarded = Forwarded#forwarded{xml_els = [NewMessage]},
NewForwarded = Forwarded#forwarded{sub_els = [NewMessage]},
NewMamResult = MamResult#mam_result{sub_els = [NewForwarded]},
Packet#message{sub_els = [NewMamResult]};
%% Any non matching packet/parsed message combination will be passed through.
Expand Down Expand Up @@ -247,17 +244,15 @@ affiliated_jids(#message{from = Sender} = Packet) ->
%% JID representation for filtering.
-spec admin_jids(binary()) -> [binary()].
admin_jids(Server) ->
Jids = mnesia:dirty_select(acl, [
{{acl, {admin, Server}, {user, '$2'}}, [], ['$2']}
]),
Jids = ets:select(acl, [{ {{admin,Server}, [{user,'$2'}]}, [], ['$2'] }]),
lists:map(fun(Raw) ->
bare_jid(jid:make(erlang:insert_element(3, Raw, <<"">>)))
end, Jids).

%% Extract all relevant users from the given MUC state (room).
-spec get_muc_users(#state{}) -> [jid()].
get_muc_users(StateData) ->
dict:fold(
maps:fold(
fun(LJID, owner, Acc) -> [jid:make(LJID)|Acc];
(LJID, member, Acc) -> [jid:make(LJID)|Acc];
(LJID, {owner, _}, Acc) -> [jid:make(LJID)|Acc];
Expand Down Expand Up @@ -295,8 +290,15 @@ make_iq_result_els(#iq{from = From, to = To} = IQ, SubEls) ->
depends(_Host, _Opts) -> [{mod_mam, hard},
{mod_muc, hard}].

mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end;
mod_opt_type(iqdisc) -> fun gen_iq_handler:check_type/1;
%% TODO: http://bit.ly/2LU3jto
%% mod_opt_type(_) -> [db_type, iqdisc].
mod_opt_type(_) -> [].
%% Validate runtime options according to docs: https://docs.ejabberd.im/developer/guide/#validation
mod_opt_type(db_type) -> econf:db_type(?MODULE);
mod_opt_type(_) -> [db_type].

%% Callback to provide known options and defaults
mod_options(_Host) ->
[ {db_type, <<"sql">>} ].

%% Callback for documentation
mod_doc() ->
#{desc => "This module allows users to acknowledge/retrieve their unread messages from direct chats and multi user conferences"}.