Get Unread Message of user per chat
Hey! How can I get the number of unread messages by chat?
I am aware that ejabberd has an endpoint that returns the total number of unread messages but I also need how many messages per chat / user are to be able to show it on my front page.
Cheers
I think that is not possible. This patch implements a new command for that. The comand doesn't work when SQL or MAM is enabled because that would require even more code.
From fcecd293ea2ee6ae599f1c52bf825df6a2186183 Mon Sep 17 00:00:00 2001
From: Badlop <[email protected]>
Date: Tue, 28 Sep 2021 13:22:19 +0200
Subject: [PATCH] get_offline_count_contact, experimental dirty patch (#3685)
---
src/mod_admin_extra.erl | 10 ++++++++++
src/mod_offline.erl | 26 ++++++++++++++++++++++++++
src/mod_offline_mnesia.erl | 26 +++++++++++++++++++++++++-
3 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/src/mod_admin_extra.erl b/src/mod_admin_extra.erl
index 9834acf01..862800569 100644
--- a/src/mod_admin_extra.erl
+++ b/src/mod_admin_extra.erl
@@ -731,6 +731,16 @@ get_commands_spec() ->
result_example = 5,
result_desc = "Number",
result = {value, integer}},
+ #ejabberd_commands{name = get_offline_count_contact,
+ tags = [offline],
+ desc = "Get the number of unread offline messages with a contact",
+ policy = user,
+ module = mod_offline, function = count_offline_messages,
+ args = [{cuser, binary}, {cserver, binary}],
+ args_rename = [{server, host}],
+ result_example = 5,
+ result_desc = "Number",
+ result = {value, integer}},
#ejabberd_commands{name = send_message, tags = [stanza],
desc = "Send a message to a local or remote bare of full JID",
longdesc = "When sending a groupchat message to a MUC room, "
diff --git a/src/mod_offline.erl b/src/mod_offline.erl
index 1d367eb72..6c33d72ea 100644
--- a/src/mod_offline.erl
+++ b/src/mod_offline.erl
@@ -55,6 +55,7 @@
export/1,
get_queue_length/2,
count_offline_messages/2,
+ count_offline_messages/4,
get_offline_els/2,
find_x_expire/2,
c2s_handle_info/2,
@@ -104,6 +105,7 @@
-callback read_all_messages(binary(), binary()) -> [#offline_msg{}].
-callback remove_all_messages(binary(), binary()) -> {atomic, any()}.
-callback count_messages(binary(), binary()) -> {ets_cache:tag(), non_neg_integer()}.
+-callback count_messages(binary(), binary(), binary(), binary()) -> {ets_cache:tag(), non_neg_integer()}.
-callback use_cache(binary()) -> boolean().
-callback cache_nodes(binary()) -> [node()].
@@ -1150,6 +1152,30 @@ count_offline_messages(User, Server) ->
end
end.
+%% Returns as integer the number of offline messages for a given user with contact
+-spec count_offline_messages(binary(), binary(), binary(), binary()) -> non_neg_integer().
+count_offline_messages(User, Server, ContactUser, ContactServer) ->
+ LUser = jid:nodeprep(User),
+ LServer = jid:nameprep(Server),
+ CUser = jid:nodeprep(ContactUser),
+ CServer = jid:nameprep(ContactServer),
+ Mod = gen_mod:db_mod(LServer, ?MODULE),
+ case use_mam_for_user(User, Server) of
+ true -> %% This is not updated !!!!
+ ?ERROR_MSG("Not supported getting count_offline_messages when MAM enabled", []), -1;
+ _ ->
+ case use_cache(Mod, LServer) of
+ true ->
+ ets_cache:lookup(
+ ?SPOOL_COUNTER_CACHE, {LUser, LServer, CUser, CServer},
+ fun() ->
+ Mod:count_messages(LUser, LServer, CUser, CServer)
+ end);
+ false ->
+ ets_cache:untag(Mod:count_messages(LUser, LServer, CUser, CServer))
+ end
+ end.
+
-spec store_message_in_db(module(), #offline_msg{}) -> ok | {error, any()}.
store_message_in_db(Mod, #offline_msg{us = {User, Server}} = Msg) ->
case Mod:store_message(Msg) of
diff --git a/src/mod_offline_mnesia.erl b/src/mod_offline_mnesia.erl
index a3c902fb3..32b42bc6b 100644
--- a/src/mod_offline_mnesia.erl
+++ b/src/mod_offline_mnesia.erl
@@ -29,7 +29,7 @@
-export([init/2, store_message/1, pop_messages/2, remove_expired_messages/1,
remove_old_messages/2, remove_user/2, read_message_headers/2,
read_message/3, remove_message/3, read_all_messages/2,
- remove_all_messages/2, count_messages/2, import/1]).
+ remove_all_messages/2, count_messages/2, count_messages/4, import/1]).
-export([need_transform/1, transform/1]).
-include_lib("xmpp/include/xmpp.hrl").
@@ -161,6 +161,17 @@ count_messages(LUser, LServer) ->
_ -> 0
end}.
+count_messages(LUser, LServer, CUser, CServer) ->
+ US = {LUser, LServer},
+ Contact = {CUser, CServer},
+ F = fun () ->
+ count_mnesia_records(US, Contact)
+ end,
+ {cache, case mnesia:async_dirty(F) of
+ I when is_integer(I) -> I;
+ _ -> 0
+ end}.
+
import(#offline_msg{} = Msg) ->
mnesia:dirty_write(Msg).
@@ -203,6 +214,19 @@ count_mnesia_records(US) ->
0
end.
+count_mnesia_records(US, {CU, CS} = _Contact) ->
+ MatchExpression = #offline_msg{us = US,
+ from = {jid, CU, CS, '_', '_', '_', '_'},
+ _ = '_'},
+ case mnesia:select(offline_msg, [{MatchExpression, [], [[]]}],
+ ?BATCHSIZE, read) of
+ {Result, Cont} ->
+ Count = length(Result),
+ count_records_cont(Cont, Count);
+ '$end_of_table' ->
+ 0
+ end.
+
count_records_cont(Cont, Count) ->
case mnesia:select(Cont) of
{Result, Cont} ->
--
2.20.1
There's an extension for this functionality, but it's not supported by ejabberd so far.
I've added the necessary code to the xmpp library a while ago, and I have a half-done patch for ejabberd. The customer who sponsored this work changed his plans and dropped the project. I have no need for this feature myself, but if someone else has, implementation cost would be cheaper given it could be based on my initial patch.