Access muc roster from an ejabberd module (disco_items?) - xmpp

I'm building an ejabberd module to send carbon copies of messages to an external RESTful API. Everything works okay, and requests to that API are sending POST params with Sender, Recipient and the message Body.
I'm triggering the user_send_packet and user_receive_packet hooks for this, and I can extract the params (Sender, Recipient, Body) from the packet:
Sender = xml:get_tag_attr_s("from", Packet),
Recipient = xml:get_tag_attr_s("to", Packet),
Body = xml:get_path_s(Packet, [{elem, "body"}, cdata])
For group chats (MUC) I'd also like to send the MUC roster (participants) in a parameter, but I don't know how to access them.
Is there an event for this? Can anyone point me to some documentation?
Thanks in advance!

It seems that you want to get MUC participants of specific room.
You need to look at mod_muc.erl and mod_muc_room.erl.
I'm not sure which version of ejabberd you use, so I will explain based on latest ejabberd.
After getting pid of room by calling
mnesia:dirty_read(muc_online_room, {Room, Host})
you can call
gen_fsm:sync_send_all_state_event(Pid, {get_disco_item, From, Lang}, 100)
or use similar code. User list is in the reply.
If you don't like reply format, you may want to add custom handle_sync_event to mod_muc_room.erl .

Related

Display message 'user typing...' to everyone, including sender, if I am typing a message, VUE JS and socket.io

I am using vuejs and socket.io in my application. The task is this: if I type a message in a dialogue with the user, display a message to both the interlocutor and myself, that I am typing a message.
How can I implement this?
Socket.io gives you lots of options to send messages across the board. What I always found very helpful is the Emit cheatsheet from the official docs (https://socket.io/docs/emit-cheatsheet/).
Here are some of the methods on how to broadcast messages to all clients including sender.
io.on('connect', onConnect);
function onConnect(socket) {
// sending to all clients in 'chat' room, including sender
io.in('chat').emit('typing', 'User xy is typing');
// sending to all clients in namespace 'chatNamespace', including sender
io.of('chatNamespace').emit('typing', 'User xy is typing');
// sending to a specific room in a specific namespace, including sender
io.of('chatNamespace').to('chat').emit('typing', 'User xy is typing');
}
Now this of course are just example methods. You would need to wrap this into your own business logic and probably register some socket event listeners to get this going.

Flask-Mail - Any way to request Read Receipt?

I just spent a little time browsing similar questions on here, and it looks like some mail frameworks have a way of sending the proper signals to a mail client for the confirmation of read receipts.
The project on which I am working must have Read-Receipts requested as all the recipients have auto-sent read receipts enabled, and also have images blocked so I'm unable to use image-loading for tracking.
I'm most familiar with Python, Flask, and Flask-Mail, which is why I'm starting here to see if anyone knows a way to request this through these frameworks, or perhaps knows what to add to a to a mail header to request this.
Thanks!
So after a little more research and testing, in the absence of a specific setting in Flask-Mail for read-receipts, it is possible to request them by defining the header Disposition-Notification-To using extra_headers in the Flask-Mail Message() definition in order to trigger a read-receipt request:
sender = 'sender#domain.com'
recipient = 'recipient#anotherdomain.com'
msg = Message(subject='Testing Read Receipt',
recipients=[recipient],
sender = ('Testy McTesterson', sender),
extra_headers={'Disposition-Notification-To': sender})

Is it possible to have Lync communicate with a REST API?

I have created a basic REST API where a user can ask for an acronym, and the web-page will return the meaning of the acronym via a POST call.
The majority of my end-users don't use the Internet as much as they use the Microsoft Lync application.
Is it possible for me to create a Lync account, and have it pass questions to my API, and return the answers to the user? Meaning the user just needs to open a new chat in Lync rather than a new web-page.
I'm sure this is possible, but I can't find any information on Google or on the web. How can this be accomplished?
Thanks very much.
Edit :
Adding a bounty in the hopes of someone creating a simple example as I believe it would be very useful for a large number of devs :).
Yep, absolutely. UCMA (the Unified Communications Managed API) would be my choice of API to use here, and a good place to start - UCMA apps are "normal" .net applications, but also expose an application endpoint, which can be added to a user's contact list. When users send messages, that can trigger events in your application so you can take the incoming IM, do the acronym translation and return the full wording.
I have a bunch of blog posts about UCMA, but as of yet no defined collection of "useful" posts to work through, but coming soon! In the meantime, feel free to browse the list.
-tom
To elaborate on Tom Morgan's answer, it would be easy to create an UCMA application for this.
Create an UCMA application
Now this doesn't have to be complicated. Since all you want is to receive an InstantMessage and reply to it, you don't need the full power of a trusted application. My choice would be to use a simple UserEndpoint. As luck would have it, Tom has a good example of that online: Simplest example using UCMA UserEndpoint to send an IM.
Make it listen to incoming messages
Whereas the sample app sends a message when it is connected, we need to listen to messages. On the UserEndpoint, set a message handler for instant messages:
endpoint.RegisterForIncomingCall<InstantMessagingCall>(HandleInstantMessagingCall);
private void HandleInstantMessagingCall(object sender, CallReceivedEventArgs<InstantMessagingCall> e)
{
// We need the flow to be able to send/receive messages.
e.Call.InstantMessagingFlowConfigurationRequested += HandleInstantMessagingFlowConfigurationRequested;
// And the message should be accepted.
e.Call.BeginAccept(ar => {
e.Call.EndAccept(ar);
// Grab and handle the toast message here.
}, null);
}
Process the message
There is a little complication here, your first message can be in the 'toast' of the new message argument, or arrive later on the message stream (the flow).
Dealing with the Toast message
The toast message is part of the conversation setup, but it can be null or not a text message.
if (e.ToastMessage != null && e.ToastMessage.HasTextMessage)
{
var message = e.ToastMessage.Message;
// Here message is whatever initial text the
// other party send you.
// Send it to your Acronym webservice and
// respond on the message flow, see the flow
// handler below.
}
Dealing with the flow
Your message flow is where the actual data is passed around. Get a handle on the flow and store it, because it's needed later to send messages.
private void HandleHandleInstantMessagingFlowConfigurationRequested(object sender, InstantMessagingFlowConfigurationRequestedEventArgs e)
{
// Grab your flow here, and store it somewhere.
var flow = e.Flow;
// Handle incoming messages
flow.MessageReceived += HandleMessageReceived;
}
And create a message handler to deal with incoming messages:
private void HandleMessageReceived(object sender, InstantMessageReceivedEventArgs e)
{
if (e.HasTextBody)
{
var message = e.TextBody;
// Send it to your Acronym webservice and respond
// on the message flow.
flow.BeginSendInstantMessage(
"Your response",
ar => { flow.EndSendInstantMessage(ar); },
null);
}
}
That would about sum it up for the most basic example of sending/receiving messages. Let me know if any parts of this need more clarification, I can add to the answer where needed.
I created a Gist with a full solution. Sadly it is not tested because I'm currently not near a Lync development environment. See UCMA UserEndpoint replying to IM Example.cs.
I never used Lync but while I was looking at the dev doc, I stumble upon a sample which could be what you're looking for.
Lync 2013: Filter room messages before they are posted
Once you have filtered the messages, you just need to catch the acronym and call your custom code that calls your API.
Unless I'm missing something, I think you could do it with a simple GET request as well. Just call your API like this yoursite.com/api/acronym/[the_acronym_here].
You can use UCWA (Microsoft Unified Communications Web API),is a REST API.For detail , can reference as the following..
https://ucwa.lync.com/documentation/what-is-lync-ucwa-api

How can I get the user jabber Id in a chat room using AnyEvent::XMPP?

There is a way to get the user's nick(roomName#domain.com/nick) in the chatroom according to the document, but how can I get the user's real jid(name#domain.com/resource_name)? is it possible according to XMPP protocol?
You can unless the room is anonymous. The Jabber protocol makes it possible that people in a chat room may be anonymous so that you cannot get back to their real JID. This is also why it provides a private message chat within the rooms, so you can still private message someone who has done this.
I have some code that does this in Bot::Backbone::Service::JabberChat:
# Figure out who sent this message
my $from_user = $room->get_user($xmpp_message->from_nick);
# Prefer the real JID as the username
my $from_username = $from_user->real_jid // $from_user->in_room_jid;
my $from_nickname = $from_user->nick;
See AnyEvent::XMPP::Ext::MUC::User and AnyEvent::XMPP::Ext::MUC::Room for more details.

openfire get online users

I'm using OpenFire server for instant messaging and JSJaC JavaScript library on the client. I'm new in XMPP technology.
What I want is on load I want to send a list of users and receive status for each. Something like
$(function(){
var UserList = ["Isis", "Jackob", "Oybek"];
con.send(UserList, OnComplete);
});
function OnComplete(myList){
for (el in myList)
if (el.IsOnline) {
// Do DOM Stuff
}
}
Is it possible?
I've been looking for the documentation, examples and other similar responses but didn't find anyting.
You can't query for presence. You can subscribe to presence. If you send your own presence in, the server will send you the current presence of everyone you have subscribed to, as well as every change they make to their presence from there on in. There's no way to tell when you're "done" getting presence, because you're never done. Just set up a callback to do something interesting whenever you get a presence change from the person you are subscribed to, and you'll be in good shape:
con.registerHandler('presence_in', function(p) {
var from = p.getFromJID()
// do something interesting with p, from, etc.
});