processone / ejabberd

Robust, Ubiquitous and Massively Scalable Messaging Platform (XMPP, MQTT, SIP Server)
https://www.process-one.net/en/ejabberd/
Other
6.09k stars 1.51k forks source link

muc offline messages #697

Closed dirkmoors closed 8 years ago

dirkmoors commented 9 years ago

What is the recommended way to implement push notifications (e.g. trigger some webservice) to offline users? In my use case, I've got members-only rooms where I want to be able to send messages, and if the message is not delivered right away (because the user is offline, network flaky, etc), Ejabberd should trigger a webservice that dispatches the message as a push notification (Android, iOS, ...).

How would I approach this?

p.s. I don't know any Erlang, otherwise I would have attempted to write a plugin or something....

dirkmoors commented 9 years ago

Also, this might be interesting approach, what do you guys think?

https://github.com/ChatSecure/ChatSecure-Push-Server/blob/master/docs/v3/README.md

nunohorta commented 9 years ago

Why don't you use a hook to listen for offline messages and to call a script that sends notifications using any library of your choice?

dirkmoors commented 9 years ago

@nunohorta I've worked with an offline message hook already, but it doesn't work with MUC afaik. In an open MUC room, where there are no 'fixed members', I understand the irrelevance of offline messages, but in my scenario, I only have rooms where there are specific members, that need to be notified if they're not online.

mremond commented 9 years ago

@dirkmoors MUC are indeed presence based. It is indeed not designed to care of offline users. The XMPP Standards Foundation started thinking about what is call MUC2, that would make it possible in a clean way.

To be frank, we have done thing for customers but nothing we have the right to share yet. However, we are willing to work actively on the MUC2 approach and have it implemented by following closely the XEP progress.

dirkmoors commented 9 years ago

@mremond Aren't there any plugins available that are able to trigger a webservice (containing message + offline members), when a message is delivered into a muc room, and not all members are online?

mremond commented 9 years ago

Not that I know of. However, it should be easier to write with the new muc_message_filter API. However, this trigger is unrelated to the fact that members in the member list are online or not. You would have to do the check in the code before triggering any remote call if you wish to.

nunohorta commented 9 years ago

@dirkmoors Okay now I understand what you need. I'm actually working on something similar. I've barely started but my idea is to use the new muc_message_filter like @mremond said above. I will also be listening for presence changes on chat rooms(https://github.com/processone/ejabberd/commit/6e61932765f9ae8e290b88cce5c2ed574fb4bbe7), thank you @weiss ! This will work, I hope, because I do all the management of users and chat rooms on my server using php and the ejabberd_xmlrpc module, meaning that the server knows which users are members in each chat room. When a message is sent to a group, I call a script that checks offline users "in" that group and sends push notifications. This will be used in groups with around 50 people max. I believe that this should not affect the server with performance issues.

dirkmoors commented 9 years ago

@nunohorta that is probably what I need too. My use case is similar, but I'll be managing the users from within a Django (python) application, via XMLRPC (actually, I've written an open source python library for that purpose: https://github.com/dirkmoors/pyejabberd). Are you implementing an erlang-based plugin? Or how do you anticipate implementing this feature?

nunohorta commented 9 years ago

@dirkmoors That looks really good! I'm using a php library that I developed myself but can't share unfortunately because it's part of a software that is not mine. To be more specific I'll listen to presence changes and chat room messages with modules that I developed. Those modules send a post request to a url in my system that caches online/offline users and sends notifications to their devices when offline. The other data I have it stored on a database because I developed a backend to manage user connections and chat rooms with a nice interface. This also runs on php and uses the xmlrpc API to call Ejabberd methods

dirkmoors commented 9 years ago

@nunohorta Yeah I did something similar: the exact approach I tried was running a 'bot' (I've used SleekXMPP, a Python library) that connects to all the rooms to listen to the messages and presence, and updates the local database accordingly, sending push notifications to offline room members. I'm afraid that this approach is not scalable (I have no idea how much MUC rooms this 'bot' can process simultaneously)

EugeneNews commented 9 years ago

@nunohorta it might be easier for you to read StateData right from muc_message_filter - which will give you online occupants for "right now". So that list of online users + = is what you use to generate push on your PHP server - but just for other/offline users. at least, this is how i do that))

nunohorta commented 9 years ago

thanks @EugeneNews ! I hope to start this over the week. It seems like a good solution!

nunohorta commented 9 years ago

@EugeneNews could you help using the muc_message_filter? How can I read the body from Stanza argument? This is what I have so far https://gist.github.com/nunohorta/fd8ecf46267deef16d86 . If you could help that would be great.

EugeneNews commented 9 years ago

@nunohorta i'm doing it with mapping list of users

  _LISTUSERS = lists:map(
    fun({_LJID, Info}) ->
      binary_to_list(Info#user.jid#jid.luser) ++ ".."
    end,
    dict:to_list(MUCState#state.users)),
  ?DEBUG(" #########    GROUPCHAT _LISTUSERS = ~p~n  #######   ", [_LISTUSERS])

you see, I'm using ".." as a separator in the string, because i like to send all users as just 1 parametor in POST request. But if advance fun() you may get LIST/array to convert it to smthn you need...

FlowerWrong commented 9 years ago

:8ball: I have the same question.

dirkmoors commented 9 years ago

Is there anyone willing to implement an (open source) Ejabberd plugin that -once a MUC room has MEMBER affiliations- simply triggers a REST/webservice, notifying which MEMBERS are offline, and which message did not get to them. I think a lot of developers would benefit from such a plugin?

If needed I can explain in more detail.

zinid commented 9 years ago

@dirkmoors I think better approach is never to go offline. Client developers should be encouraged to implement XEP-0198. I also do not understand the dance around affiliations. Have you ever seen MUC rooms with 1000 members in the list? Your REST/webservice will die during notifications.

dirkmoors commented 9 years ago

@zinid In many usecases, you're talking of less members. Think intranet chat application, friend-groups, etc. In those usecases, I think it would make perfect sense to notify a webservice?

Moreover, never going offline seems hard in mobile environments, which by nature do not provide stable connectivity?

zinid commented 9 years ago

Moreover, never going offline seems hard in mobile environments, which by nature do not provide stable connectivity?

Actually with XEP-0198 you can be always online. XEP-0198 will transparently resume your session during re-login.

dirkmoors commented 9 years ago

That sounds very interesting! I'm going to look into that XEP definitely.

Nevertheless; triggering a webservice to notify about offline room members would make (mobile) push notifications to mobile devices very straightforward to implement. Or would you suggest another approach to achieve this?

zinid commented 9 years ago

Nevertheless; triggering a webservice to notify about offline room members would make (mobile) push notifications to mobile devices very straightforward to implement. Or would you suggest another approach to achieve this?

I think push notifications should be triggerd when a client is disconnected from the server, but its session is alive (due to XEP-0198 "hibernation").

weiss commented 9 years ago

triggering a webservice to notify about offline room members would make (mobile) push notifications to mobile devices very straightforward to implement.

Is this about making room messages available to offline members, or about generating push notifications to mobile clients, or both? These are somewhat unrelated topics which require separate solutions.

Anyway, it's not quite obvious to me how a web service would be specifically useful to solve either of these things, as opposed to having an ejabberd module do whatever the web service would do. But yes, it could be done this way, just as a web service could handle any other event within ejabberd, of course.

dirkmoors commented 9 years ago

@zinid That might be a good 'trigger to send a push notification' yes, but there still needs to be a party responsible for sending the actual push notification. In my mind, the simple solution would be to offload that responsibility to a seperate (web)service.

joaoffm commented 9 years ago

Don't know much about erlang, just what I learned in the past week and taking into account all the links and feedback posted I've been able to "build" a mod for what's requested

https://github.com/diamondbybold/ejabberd_mod_offline_post

cisiqo commented 8 years ago

I also have the same question. Finally i have update 3 files to realize. The module are ejabberd_sm、mod_muc_room、mod_offline.

https://github.com/cisiqo/ejabberd-module-dev

Hiren701 commented 8 years ago

i have same issue , let me give some more detail. i have implimented ejabberd 15.11, i have used mod_http_offline module to send offline notification. i am able to start and complile my module. but when user send offline message i got below error in my error log, can anyone please suggest whare i am wrong .

     2015-12-28 21:13:28.971 [error] <0.37.0>@ejabberd_config:validate_opts:794 unknown option 'loopback' will be likely ignored
     2015-12-28 21:13:28.971 [error] <0.37.0>@ejabberd_config:validate_opts:794 unknown option 'local' will be likely ignored
     [error] <0.524.0>@ejabberd_hooks:run1:332 {function_clause,[{lists,thing_to_list,[<<>>],[{file,"lists.erl"},{line,601}]},{lists,flatmap,2,[{file,"lists.erl"},{line,1248}]},{lists,flatmap,2,[{file,"lists.erl"},{line,1248}]},{mod_http_offline,post_offline_message,2,[{file,"mod_http_offline.erl"},{line,43}]},{ejabberd_hooks,safe_apply,3,[{file,"src/ejabberd_hooks.erl"},{line,382}]},{ejabberd_hooks,run1,3,[{file,"src/ejabberd_hooks.erl"},{line,329}]},{ejabberd_sm,route,3,[{file,"src/ejabberd_sm.erl"},{line,111}]},{ejabberd_local,route,3,[{file,"src/ejabberd_local.erl"},{line,112}]}]}

   running hook: {offline_message_hook,[{jid,<<"911234567891">>,<<"xyz.com">>,<<"42629891761451308446954821">>,<<"111111111111">>,<<"xyz.com">>,<<"42629891761451308446954821">>},{jid,<<"33333333">>,<<"xyz.com">>,<<>>,<<"111111111">>,<<"xyz.com">>,<<>>},{xmlel,<<"message">>,[{<<"id">>,<<"Ge62DNXY">>},{<<"type">>,<<"One2One">>},{<<"to">>,<<"121212121@xyz.com">>}],[{xmlel,<<"msgtype">>,[],[{xmlcdata<<"chat">>}]},{xmlel,<<"body">>,[],[{xmlcdata,<<"T2s=">>}]},{xmlel,<<"FrontParterPic">>,[],[{xmlcdata,<<"57_1447745086.jpg">>}]},{xmlel,<<<"x">>,[{<<"xmlns">>,<<"jabber:x:event">>}],[{xmlel,<<"offline">>,[],[]},{xmlel,<<"delivered">>,[],[]}]}]}]}
mremond commented 8 years ago

@Hiren701 The problem is in https://github.com/raelmax/mod_http_offline/ not in ejabberd. That module is not compliant with latest ejabberd apparently.

bangarharshit commented 8 years ago

@zinid , I am using session resumption with large resumption time - 24 hours. I have a doubt about muc, if I am in group and my client rejoin, do I need to leave and rejoin the group to get the new messages. For non muc stanzas, they are kept in offline storage and delivered as soon as I reconnect. But I am not sure about muc.

If it is not so the case I don't think there is any advantage of being online - except to fetch occupants list. Again I am not sure if I will get occupant joined event if my client was offline.

weiss commented 8 years ago

I am using session resumption with large resumption time - 24 hours. I have a doubt about muc, if I am in group and my client rejoin, do I need to leave and rejoin the group to get the new messages.

No. If your client is resuming the stream management session, then you never left the room and there's no reason to rejoin it. You would receive the missing room messages during resumption.

sh-al commented 8 years ago

what i did:

  1. all rooms created with members_by_default: true options
  2. modified mod_muc room so it would route incoming packets for all room members, except the banned one
  3. modified ejabberd sm module so it would call offline_message_hook for messages with type = groupchat.
  4. when the offline_message_hook is called, i send a push notification When a user connects, he receives all the messages from muc room as regular offline messages

I have doubts that this is the best way to do it

rubenjavier commented 8 years ago

Hello sh-al, could you please share the code you used for steps 2 and 3?

"2. modified mod_muc room so it would route incoming packets for all room members, except the banned one

  1. modified ejabberd sm module so it would call offline_message_hook for messages with type = groupchat."

This sound like a good solution for many of my scenarios Thanks in Advance,

Best Regards

mremond commented 8 years ago

Closing, we are preparing some extension that could help with this in the future.

dirkmoors commented 8 years ago

@mremond Do you have more info about that extension? Where can I learn more about it?

mremond commented 8 years ago

Here is MUC Sub extension: https://blog.process-one.net/xmpp-mobile-groupchat-introducing-muc-subscription/

MurzNN commented 7 years ago

@mremond, can you describe some examples how to use this extension and implement in ejabberd server some multi-user Group chat with offline message delivery to each member in any Jabber client?

MurzNN commented 7 years ago

At now our company use Jabber Bot based on https://github.com/punchagan/childrens-park that emulate group chat with offline messages, and it works well for 100+ users with massive every day talks. But bad site is that all chatrooms must be configured manually on server side.

ismailmohammed commented 6 years ago

Don't know much about erlang, just what I learned in the past week and taking into account all the links and feedback posted I've been able to "build" a mod for what's requested

https://github.com/diamondbybold/ejabberd_mod_offline_post

Hi,

I want to send offline message to one-to-one user as well as groups. when I tried compiling the module from above github url getting below errors can you help me on this. I am using ejabbered 18.01 version.

c:/Program Files/ejabberd-18.01/lib/ejabberd-18.01/include/mod_muc_room.hrl:96: type message() undefined c:/Program Files/ejabberd-18.01/lib/ejabberd-18.01/include/mod_muc_room.hrl:97: type presence() undefined c:/Program Files/ejabberd-18.01/lib/ejabberd-18.01/include/mod_muc_room.hrl:116: type text() undefined c:/Program Files/ejabberd-18.01/lib/ejabberd-18.01/include/mod_offline_post.erl:4: Warning: undefined callback function depends/2 (behaviour 'gen_mod') c:/Program Files/ejabberd-18.01/lib/ejabberd-18.01/include/mod_offline_post.erl:4: Warning: undefined callback function mod_opt_type/1 (behaviour 'gen_mod')

Thanks in Advance.

licaon-kter commented 6 years ago

@ismailmohammed Why would you use a 3 years old module? You already have mod_offline included, that and MAM modules should take care of stuff.

If you compile your own do UPDATE to 18.09 and use the config template (that has all the good stuff enabled already) to setup your server.

ismailmohammed commented 6 years ago

@licaon-kter I agree with you but mod_offline will store the offline messages and retrived when user is online. but my case is when a user is offline even I should get the message like watsup. when the application is running in the background. 1:1 or group chat when user is offline i want a send a message as notification to the user.

Thank you ismail

licaon-kter commented 6 years ago

Ignore this old useless module and UPDATE to 18.09 and use the config template (that has all the good stuff enabled already) to setup your server.

weiss commented 6 years ago

1:1 or group chat when user is offline i want a send a message as notification to the user.

As @mremond mentioned above, using MUC/Sub solves this issue.

For standard clients that don't use this extension, mod_push_keepalive tries to work around the problem by keeping the XEP-0198 session online until at least one push notification was sent.

ismailmohammed commented 6 years ago

thanks for the update.

you mean to say once upgrade to 18.09 version with given configration user will be able to get 1:1 and group offline notifications to mobile(andriod\IOS)?

Thanks, Ismail

licaon-kter commented 6 years ago

@ismailmohammed Yes, of course.

After you're done with the setup, run it through https://compliance.conversations.im/ and see if everything works ok ;)

ismailmohammed commented 6 years ago

I have uninstalled the previous version and installed 18.09 version and changed some configurations settings. Need to test it.

but still, I have doubt how ejabbered will send mobile push notifications to Andriod and IOS mobiles without any configurations like APNS,FCM etc?

Thanks in advance Ismail.

licaon-kter commented 6 years ago

Push config is done in the client application (Conversations on Android from Play store or ChatSecure on iOS)

ismailmohammed commented 6 years ago

Hi,

I have started 18.09 with configuration shared. please clarify push notification will work ejabberd Business Edition? or even in community?

one of my colleague who's developing IOS app he is trying to enable push notification from his code and he is getting below error can you please suggest me on this error. `

http://jabber.org/protocol/pubsub#publish-options 4dd9a938d9d7376dba04295a63a6a15b508058d81e0dfaa8cb267130d2765af2com.xyz.ConnectapnsdevRetransmissionToo many child elements` Thanks, Md.Ismail.
lakmalniranga commented 5 years ago

@ismailmohammed Have you figure it out a way to trigger HTTP request for group offline messages?

ismailmohammed commented 5 years ago

Yes I did.

Thank you.

On Fri 15 Feb, 2019 5:10 pm Lakmal Dharmasena <notifications@github.com wrote:

@ismailmohammed https://github.com/ismailmohammed Have you figure it out a way to trigger HTTP request for group offline messages?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/processone/ejabberd/issues/697#issuecomment-464015546, or mute the thread https://github.com/notifications/unsubscribe-auth/AKBe-VwRkql2U-2gUQ3Va-wo_OycnnULks5vNpyfgaJpZM4FlmGh .

lock[bot] commented 4 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.