On page unload strophe.js sends request twice! why? - javascript

I'm new to Xmpp server and strophe.js, I implement it into my website for messaging. There is a problem when I am send a message it works fine, but after sending a message if I reload the page immediately then I saw that that message, which I send before reload saved in Xmpp server twice, and when I retrieve message from server obviously it return duplicate message. It is so embarrassing.
Can any one tell me any solutions to stop twice requesting when page load?
I saw a post where one developer told that he face with same problem and contact to strophe team they suggest him to replace the line 2566 of strophe.js file with this code
if (req.sends == 0) {
sendFunc();
}
I have already done it but my problem is still there. :(
Thanks,
biswajitGhosh

You need to create multiple divs/windows, one for each chat. Strophe is meant to be asynchronous so you don't have to reload. Reloading defeats the purpose of strophe. Add a handler to your connection once you attach/connect.
connection.addHandler(onMsg, null, 'message');
In your message handler, you can then determine which conversation the message belongs to and append it to the appropriate div.
var onMsg = function (msg) {
var elems = msg.getElementsByTagName('body');
if (elems.length > 0) {
var type = msg.getAttribute('type');
var from = msg.getAttribute('from');
if (type == "chat") {
//new chat message
}
}
return true;
}

Related

Inline keyboard callback_query setup in Google Apps Script Telegram bot

I've managed to figure out how to attach an inline button to message from my Telegram bot. I'm not sure how to make this button actually do something.
I have a simple invoice table in my Google Spreadsheet. I manually connected a Form to it, through which managers can request some financial transactions.
My perfect scenario: on every new form submit bot sends me a message with all the transaction's data. It already works perfectly (I'm using variables from form responses in combination with sendMessage and UrlFetchApp.fetch).
Now, I want to attach a functional button that will delete the particular message it's connected to and then send me a "Transaction completed" message.
My inline keyboard code excerpt:
'{"inline_keyboard":[[{"text":"Del","callback_data":"delete_message"}]]}'
I use most primitive webhook:
function setWebhook() {
var url = telegramUrl + "/setWebhook?url=" + webAppUrl;
var response = UrlFetchApp.fetch(url);
}
And I have a doPost function for just replying to /start command (if some manager got lost in space and time):
function doPost(e) {
var contents = JSON.parse(e.postData.contents);
var chat_id = contents.message.from.id;
var fname = contents.message.from.first_name;
var text = (""+fname +", this bot is for notification only, fill the form located on our website.");
sendMessage(chat_id,text)
}
I've Googled a lot, and tried some solutions, but it seems like my callback listening still isn't working.

SignalR multi user live chat desynchronisation

I have a live chat in which multiple people would be connected simultaneously. All public messaging works fine, but sometimes private messaging to a specific id doesn't work. I believe i narrowed it down to when people disconnected and reconnected that they connected to a different instance (perhaps IIS had recycled and started a new hub).
I thought I had fixed it, but I haven't and now I'm here because I'm stuck. What I thought would fix it was changing the connection variable within the startChat() function to refresh it with the correct information.
This is a cut down version of the code, as I didnt thing the rest would be necesary.
Issue is that when connected to signalR recipients of a message directly to them doean't come through, even though the chat Id it's being sent to it correct. Possible hub/socket mismatch?
var chat = $.connection.chatHub;
$(document).ready(function () {
// Start the chat connection.
startChat();
//restart chat if disconnected
$.connection.hub.disconnected(function () {
setTimeout(startChat(), 5000);
});
$.connection.hub.error(function (error) {
$('#messagebar').html('Chat ' + error + '. If this message doesn\'t go away, refresh your page.');
});
chat.client.addToChat = function (response) {
$('#chat-' + response.Type).prepend(response.Message);
};
});
function startChat() {
chat = $.connection.chatHub;
$.connection.hub.start().done(function () {
//get recent chat from db and insert to page.
//also saves user's chat id to their user for lookup when private messaging
$.ajax({
method: 'POST',
url: '/api/Chat/SetupChat/'
});
$('#messagebar').html('Connected to chat.');
});
}
Any help appreciated, Thanks.
Not sure exactly how your message is going missing, but you should send messages to a User instead of by connection id. This way you be able to identify on the server that a User has at least one connection, and send messages to all connections for that User. if a given connection id is no longer valid, but another one is (because the client has refreshed the page for example) the message wont be lost.
From the docs https://learn.microsoft.com/en-us/aspnet/core/signalr/groups:
The user identifier for a connection can be accessed by the
Context.UserIdentifier property in the hub.
public Task SendPrivateMessage(string user, string message)
{
return Clients.User(user).SendAsync("ReceiveMessage", message);
}
Not sure how this relates exactly to your server code, but you could add it if you're unclear how to progress.

How to allow JavaScript to receive a message sent to a specific user (or self) using Signal R?

I previously asked this question but it was closed for duplication owing to this thread (SignalR - Sending a message to a specific user using (IUserIdProvider) *NEW 2.0.0*) - but this doesn't show the JavaScript as made clear in my title.
I have a WebForm application in ASP.Net that uses SignalR to push live data to the user logged in. The setup works perfectly, but realised I am broadcasting messages to all clients, which whilst it doesn't cause the wrong data to displayed to the logged in user, does cause the JavaScript function to get called for all users when just one has a data push.
I have amended the Hub code to broadcast to a specific user (User) and provided the User ID, and I have also tried Client with a Connection ID. Both fire off fine in the codebehind, but the javascript will not update the front end.
I believe it's because the JavaScript has not been modified to listen for a message sent to the user, but I'm not sure how I need to adapt the code to allow the message to be received.
The 2 tried lines in Hub here:
context.Clients.User(Me.Context.User.Identity.GetUserId()).ReceiveNotification(notifCount)
context.Clients.Client(Me.Context.ConnectionId).ReceiveNotification(notifCount)
JavaScript/jQuery function for the SignalR message here:
$(function () {
var nf = $.connection.notificationHub;
nf.client.receiveNotification = function (notifCount) {
// Update data
}
$.connection.hub.start().done(function () {
nf.server.sendNotifications();
}).fail(function (e) {
alert(e);
});
//$.connection.hub.start();
});
For calling back to the client (or self) you should use:
Clients.Caller.addContosoChatMessageToPage(name, message);
And for calling users you should use:
Clients.Client(Context.ConnectionId).addContosoChatMessageToPage(name, message);
Reference - docs

strophe.js, I use attach() to restore a Bosh session but get 'Status' ATTACHED to CONNFAIL and to DISCONNECTED

I use strophe.js to build a simple IM(web).
I have 2 pages:index.html(for login) and myChat.html(main chat view).
And when I login to openfire server by jid and password in index.html
connection = new Strophe.Connection(BOSH_SERVICE);
connection.connect($("#inputName").val()+"#openfireserver", $("#inputPassword").val(), onConnect);
Then I save jid,sid,rid in COOKIE in callback 'onConnect', and go to myChat.html
if (status == Strophe.Status.CONNECTED) {
console.log("success");
connected = true;
$.cookie('jid', connection.jid);
$.cookie('sid', connection._proto.sid);
$.cookie('rid', connection._proto.rid);
location.href='myChat.html';
}
In myChat.html, I use connection.attach() to restore the BOSH session.
var jid=$.cookie('jid');
var sid=$.cookie('sid');
var rid=$.cookie('rid');
connection = new Strophe.Connection(BOSH_SERVICE);
connection.attach(jid,sid,parseInt(rid,10)+1,onConnectAttach);
At first, in callback 'onConnectAttach', the status==Strophe.Status.ATTACHED,
but wait 1-3 mins, status will turn into Strophe.Status.CONNFAIL and Strophe.Status.CONNECTED!
If I use connection.connect() to re-connect the server, it will keep session all the time.
So I can not understand where I make the mistake? Why the status will change after I use attach()?
Got it.
connection.attach(jid,sid,parseInt(rid,10)+1,onConnectAttach);
It's wrong, because I look through some questions about "attach" function and I find someone say that 'rid' must be added one.
But, by my test, I don't need to do that.just:
connection.attach(jid,sid,rid,onConnectAttach);

How can I pick out a particular server message from a websocket connection?

I have a WebSocket connection set up for a basic web chat server.
Now, whenever a message is received, it is sent to a function which outputs it on the screen.
socket.onmessage = function(msg){output(msg);}
However, there are certain technical commands which the user can send to the server through the connection which elicit a technical response, not meant to be output on the screen.
How can I grab the server response which immediately follows one of these technical messages?
Do I put a separate socket.onmessage right after the block of code which sends the technical message? I imagine that would take all future messages. I just want the next one.
Ideas?
WebSockets is asynchronous so trying to get the 'next' message received is not the right solution. There can be multiple message in flight in both directions at the same time. Also, most actions in Javascript are triggered by asynchronous events (timeout firing, or user clicking on something) which means you don't have synchronous control over when sends will happen. Also, the onmessage handler is a persistent setting: once it is set it receives all messages until it is unset. You need to have some sort of way of distinguishing control messages from data messages in the message it self. And if you need to correlate responses with sent messages then you will also need some kind of message sequence number (or other form of unique message ID).
For example, this sends a control message to the server and has a message handler which can distinguish between control and message and other messages:
var nextSeqNum = 0;
...
msg = {id: nextSeqNum, mtype: "control", data: "some data"};
waitForMsg = nextSeqNum;
nextSeqNum += 1;
ws.send(JSON.stringify(msg));
...
ws.onmessage = function (e) {
msg = JSON.parse(e.data);
if (msg.mtype === "control") {
if (msg.id === waitForMsg) {
// We got a response to our message
} else {
// We got an async control message from the server
}
} else {
output(msg.data);
}
};
You can packetise the data, I mean, by a special character/s, form a string like this :
"DataNotToBeShown"+"$$"+"DataToBeShown"; //if $$ is separating character
And then, you can split the string in javascript like this :
var recv=msg.data.split('$$');
So, the data not be shown is in recv[0] and data to be shown, in recv[1]. Then use however you want.

Categories