I am writing a custom service using XMPP protocol, ejabberd server and PostGis spatial database. Also I am writing the clients to the service, so I have complete control.
User Alice comes online and need to publish information to certain user entities which are within proximity to her.
So user Alice login create pubsub node, I want the other proximity entities to be automatically subscribed to Alice's node.
When Alice comes online I need automatically to query postgis about entities within proximity and automatically subscribe them to Alice.
Which way would you recommend?
Thanks
Eylon
There is no existing standard for doing exactly this, but XEP-0060 can be extended to accomplish this.
In a system I developed I made it possible to subscribe to a point+radius, within a node. This is accomplished via the subscription options, such as:
<iq type='set'
from='francisco#denmark.lit/barracks'
to='pubsub.shakespeare.lit'
id='sub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscribe node='princely_musings' jid='francisco#denmark.lit'/>
<options>
<x xmlns='jabber:x:data' type='submit'>
<field var='FORM_TYPE' type='hidden'>
<value>http://jabber.org/protocol/pubsub#subscribe_options</value>
</field>
<field var='location#latitude'><value>52.231</value></field>
<field var='location#longitude'><value>-1.49</value></field>
<field var='location#radius'><value>10</value></field>
</x>
</options>
</pubsub>
</iq>
Then I customized the pubsub service to filter notifications according to the area in the subscription options. Things only really get complicated when items are moving location, and you need to emulate a retract when an item previously published to a client goes out of range of its subscription area.
Unfortunately I can't offer any code as it is not public (not my choice), though it's for Prosody anyhow, and it looks like you are looking for an ejabberd solution. The principle I describe above is working well for me though, so I suggest it as a template solution at least.
I haven't used ejabberd, but I would think a custom module that does the correlation between location tracking and subscription management would be the simplest. This type of application specific behaviour is typically supported in most XMPP servers by usage of curomt plugins/modules.
Related
We're implementing an xmpp client and we are using ejabberd as xmpp server.
We've implemented muc (multi user chat) functionalities to our app and everything is working fine , only thing we are having problem is a member to leave the group permanently.
I know in XEP 45 says if you want to leave the group just send the unavailable presence to room but this doesnt work in our case because our admins add users of the group to memberList
by sending the below xml:
<iq from='crone1#shakespeare.lit/desktop'
id='member1'
to='coven#chat.shakespeare.lit'
type='set'>
<query xmlns='http://jabber.org/protocol/muc#admin'>
<item affiliation='member'
jid='hag66#shakespeare.lit'
nick='thirdwitch'/>
</query>
</iq>
And when a member send unavailable presence, this doesnt affect the groups member list(Which is working as we wanted)
So we want to find a way for a member to remove himself/herself from group members list permanently so he/she wont be able to receive any messages from that group anymore
Is something like that possible? Can we remove ourself from groups member's list like whatsapp's leave chat functionality.
When user leaves room he will not receive messages anymore - XMPP MUCs are presence-based. "Member lists" are only for administrative purposes and does not control message receiving.
There are some another XMPP extension specifications designed with "persistent" member list in mind, for example MUC Light - it can be more suited for you needs.
As defined in XEP-0045, if the MUC admin added another user as member, that added user cannot remove himself as member.
However, as a default in XEP-0045, MUC members do not receive message. This brings me to think this is not the problem you are hitting.
I suggest that you use MUC/Sub as implemented in ejabberd and defined in this specification for more flexibility. It is 100% compliant with MUC specification, so MUC compliant client and MUC/Sub enhanced client can participate in the same workflow.
In your case, I think that you need to subscribe your users to the events he wants (message, possibly presence or configuration changes). Subscription can be handled by users so that user can also control unsubscribe. It should do exactly what you want.
You need ejabberd 16.09 to use that specification. MUC/Sub is defined here: https://docs.ejabberd.im/developer/xmpp-clients-bots/proposed-extensions/muc-sub/
When User A and User B, both are online and one of them changes the avatar, all the rosters of the User receive a presence stanza with vcard-temp update element with the sha1 hash of the image used as avatar.
<presence from='juliet#capulet.com/balcony'>
<x xmlns='vcard-temp:x:update'>
<photo>sha1-hash-of-image</photo>
</x>
</presence>
However, no such notification/stanza is generated for the users which are offline at that time, So such a client shows no change in the avatar displayed.
How can an offline user can get v-card updates from rosters, when there is any change? I don't wish to ask for vCard for all the rosters, even if there is no change.
I think a client that support the protocol should include the avatar in all presence packet, not just on change. As explained in XEP-0153: vCard-Based Avatars:
If a client supports the protocol defined herein, it MUST include the
update child element in every presence broadcast it sends and SHOULD
also include the update child in directed presence stanzas (e.g.,
directed presence sent when joining Multi-User Chat (XEP-0045) [5]
rooms).
It means offline users will get the correct presence and can update the avatar when they are both online.
First of all, I'd like to provide some background information: I want to exchange unstructured data between various clients using XMPP. Data sources are supposed to publish their data simply to Mulit-User-Chat rooms (XEP-0045) so that any interested client can register.
XMPP MUC services can have various chat rooms and in order to find the ones my data sources push information to, I'd like to set some custom identification for that room. I figured muc#roominfo_<custom_ident> with some custom value would be great to accomplish that.
For testing purposes I wrote an application that creates a MUC on an XMPP service. Authentication etc. all works fine. I am using Smack to communicate with the XMPP server and to create the room. When I create the room, I am adding a field to the form field I requested before containing my custom information. The MUC is created and accessible. Yet the created custom field is not returned when I perform a disco#info on the room's JID.
I tested this with a local installation of (3.8.2).
I just wonder, if this is an issue of Openfire, that custom form fields (XEP-0068 used here in XEP-0045) are not stored when the MUC is created or if it is just not allowed according to XEP-0045? I read the specification for MUCs and crucially the respective section but couldn't find any evidence that convinced me, that it is explicitly not possible to create such custom form fields for a MUC.
Maybe I just misunderstand something in the specification? Has anyone tried something similar and it's working? If it is an issue of Openfire, I could try a different XMPP server.
I wonder if there is a way to query the XMPP server (passing user JID?) to find out what chat room(s) this user is currently in? If not, can we query jabber server to get a list of all active chat rooms?
BTW we're running ejabber enabled for multiuser chat. A solution using a java library (smack?) would be ideal.
As mentioned by Joe Hildebrand, there is no such a standard feature as it is a privacy violation to allow that over XMPP, so you cannot expect to do that from Smack. Maybe with admin privilege you could have a custom protocol extension that does that but that seems risky.
However, at the server level, you should be able to write a custom module for ejabberd that will query or index all rooms users are in. This is not standard and there is plugin development involved.
There are two (maybe three) XMPP entities that have that information:
the XMPP MUC component which provides the MUC room
the users XMPP client (or better the XMPP library used by the user)
maybe the XMPP server(s) (but let's ignore that)
At the time of writing this, there is no standardized way (in terms of XMPP XEPs) to query that information. As Joe Hildebrand pointed out, this would result in a information leak which is not what we want in most cases.
But you can either extend the MUC component to provide that information (remember XMPP is easily extendable) or the XMPP client library. The usual approach would be via an iq get query. For example:
<iq type='get' from='juliet#capulet.lit/balcony' to='capulet.lit' id='q1'>
<query xmlns='http://jabber.org/protocol/muc#joinedrooms'/>
</iq>
The entities which support that query would then report back the joined rooms of the requested entity. Also they would may announce the http://jabber.org/protocol/muc#joinedrooms feature in their service discovery information.
Note that this is a fictional protocol extension meant as example. I have never seen it in real use
If the MUC component provides this feature then it's not controllable by the client if this information is exposed. But if the client provides this feature then of course he can control who can retrieve this information. You may decide what's the better approach in your case.
Getting all chat rooms is no problem, just use this query.
There seems to be already a question on how to retrieve rooms with smack. Look here.
I have a web app that create groups. Each group gets their own discussion board.
I would like to add the feature of allowing users to send emails to their "group" within the web app to start a new discussion or reply to an email from the "group" to make a new post in an already ongoing discussion.
For example, to start a new discussion a user would send:
From: BillFake#gmail.com
To: group1#example.com
Subject: Hey guys! Meet up on Tuesday?
Body: Yes? No?
All members of the group would receive an email:
From: BillFake#gmail.com
Subject: Hey guys! Meet up on Tuesday?
Body: Yes? No?
Reply-To: group1# example.com
And, the app would start a new discussion with:
Author: Bill Fake
Subject: Hey guys! Meet up on Tuesday?
Body: Yes? No?
This is a pretty standard feature for Google Groups and other big sites. So how do us mere mortals go about implementing this? Is there an easy way?
Or do I:
1. Install postfix
2. Write scripts to create new accounts for each new group
3. Access the server periodically via pop3 (or imap?) to retrieve the email messages sent to each account?
4. Parse the message for content
If it's the latter, did I miss a step?
Configure your mail server to run on a database backend (such as MySQL), then you can just insert records from your app to create mail accounts.
I'm not sure if you can make it deliver messages into a MySQL table as well. You might need to access it via IMAP, or perhaps just access the Maildirs directly with Python's Maildir support.
The advantage of IMAP though, is that you could use IMAP notify to save some polling. But I suppose you could use inotify (or something similar) for Maildirs as well.
Since you're using Python, I also recommend taking a look at Lamson. Maybe look into mailman since what you're doing sounds vaguely mailinglistish (but I've heard horror stories about mailman).