quickblox for web - create 1 to 1 chat - quickblox

I am trying to create 1 to 1 chat from a web client.
I downloaded the SDK and the group chat example.
There seem to be really good examples for all platforms except the web.
(for example: http://quickblox.com/developers/Android_XMPP_Chat_Sample)
Can anyone provide code/example/directions?
Am i missing something or is the documentation for the web is really lacking?
Thanks

The WebSDK is enough new. And we work on its documentation.
But,here, I will show you some code snippets how you can create one to one chat.
As you know QuickBlox uses XMPP-server as a Chat service.
WebSDK doesn't have a wrapper around XMPP API, so you should include additional XMPP JS library.
For our examples, we recommended to use Strophe.js (http://strophe.im/strophejs/)
Let's begin:
1) Include your xmpp js library and WebSDK
<script src="quickblox.js"></script>
<script src="strophe.js"></script>
2) Describe your QB credentials
var QBAPP = {
app_id: '<your QuickBlox id>',
auth_key: '<your QuickBlox key>',
auth_secret: '<your QuickBlox secret>'
};
// our parameters to connect to QuickBlox Chat service
var CHAT = {
server: 'chat.quickblox.com',
bosh_server: 'http://chat.quickblox.com:5280'
};
3) Create QB session with user authentication
var params, connection;
params = {
login: '<your QB login>',
password: '<your QB password>'
};
QB.init(QBAPP.app_id, QBAPP.auth_key, QBAPP.auth_secret);
QB.createSession(params, function(err, res) {
if (err) {
console.log(err.detail);
} else {
connectChat(res.user_id, params.password);
}
});
4) Connect to QuickBlox Chat server with your user JID and password (http://quickblox.com/developers/Chat#Connecting_to_server)
function connectChat(user_id, password) {
var userJID = user_id + "-" + QBAPP.app_id + "#" + CHAT.server;
var userPass = password;
connection = new Strophe.Connection(CHAT.bosh_server);
connection.rawInput = rawInput;
connection.rawOutput = rawOutput;
connection.connect(userJID, userPass, function (status) {
switch (status) {
case Strophe.Status.ERROR:
console.log('[Connection] Error');
break;
case Strophe.Status.CONNECTING:
console.log('[Connection] Connecting');
break;
case Strophe.Status.CONNFAIL:
console.log('[Connection] Failed to connect');
break;
case Strophe.Status.AUTHENTICATING:
console.log('[Connection] Authenticating');
break;
case Strophe.Status.AUTHFAIL:
console.log('[Connection] Unauthorized');
break;
case Strophe.Status.CONNECTED:
console.log('[Connection] Connected');
// Create an event handler for getting messages
connection.addHandler(onMessage, null, 'message', null, null, null);
// send a presence message
connection.send($pres().tree());
break;
case Strophe.Status.DISCONNECTING:
console.log('[Connection] Disconnecting');
break;
case Strophe.Status.DISCONNECTED:
console.log('[Connection] Disconnected');
break;
case Strophe.Status.ATTACHED:
console.log('[Connection] Attached');
break;
}
});
}
// logs
function rawInput(data) {console.log('RECV: ' + data);}
function rawOutput(data) {console.log('SENT: ' + data);}
5) Function for receive messages
function onMessage(msg) {
console.log(msg);
var to = msg.getAttribute('to');
var from = msg.getAttribute('from');
var type = msg.getAttribute('type');
var elems = msg.getElementsByTagName('body');
// we must return true to keep the handler alive.
// returning false would remove it after it finishes.
return true;
}
6) Function for send messages
function sendMessage() {
params = {
to: '<some JID>', // JID of recipient QB User
from: connection.jid, // JID of sender QB user
type: 'chat' // type of the message
}
var msg = $msg(params).c('body').t('Hello world!');
connection.send(msg.tree());
}
I'm sure, that it helps you to create one to one chat with QuickBlox using Javascript.
If you want to use the group chat, you can look at 'Chat module code' from develop branch of Web XMPP chat sample:
https://github.com/QuickBlox/sample-chat-xmpp-web/blob/develop/qbchatroom.js
Today we finished new sample's design http://i.imgur.com/r8CSdNV.png and very soon will deploy that to production.

I suggest that you might see the 405 error because you have put the call of sendMessage function immediately after the call of connectChat function.
To connect to the chat needs some time, so you can not send the message until your client (browser) hasn't finished the connecting to the chat server at first. You need to put the call of sendMessage function in callback from function connectChat where a status is "Connected". Or you can perform sendMessage function on an onclick event to the tag <button> or something else. For your example, insert sendMessage like here:
case Strophe.Status.CONNECTED:
console.log('[Connection] Connected');
connection.addHandler(onMessage, null, 'message', null, null, null);
connection.send($pres().tree());
sendMessage();
break;

Starting from today QuickBlox has a own Web XMPP Chat plugin for WebSDK.
You can look here the new example for 1:1 Chat which uses this library:
http://quickblox.com/developers/Web_XMPP_Chat_Sample

Related

How to securely store phone numbers in Twilio Functions?

I am using Twilio Functions. I wonder if the phone numbers stored in the Function's code are secure?
I am using code similar to that found here: https://support.twilio.com/hc/en-us/articles/223180548-How-Can-I-Stop-Receiving-or-Block-Incoming-Phone-Calls-#blacklistNumbers
Basically, it rejects numbers that on a blacklist of your choosing. The blacklist is in the Function's code itself.
Perhaps this is already secure. Forgive my misunderstanding.
The aforementioned code:
exports.handler = function(context, event, callback) {
// Listing all the blocked phone numbers, at the moment "+1(212)555-1234" and "+1(702)555-6789"
let blacklist = event.blacklist || [ "+12125551234", "+17025556789" ];
let twiml = new Twilio.twiml.VoiceResponse();
let blocked = true;
if (blacklist.length > 0) {
if (blacklist.indexOf(event.From) === -1) {
blocked = false;
}
}
if (blocked) {
twiml.reject();
}
else {
// if the caller's number is not blocked, redirecting to another TwiML which includes instructions for what to do
twiml.redirect("https://demo.twilio.com/docs/voice.xml");
}
callback(null, twiml);
};
Heyooo. Twilio Developer Evangelist here. 👋
I don't think you have to worry about the security of these numbers. But what you could do it to add the blacklist to the function configuration instead. This way you wouldn't have to change the function code whenever you want to add a new number to the blacklist.
These values below will be available in the context object that is passed into your function.
exports.handler = async function(context, event, callback) {
console.log(context.BLACKLIST); // 1212...
}

Videocall from Web SDK to iOS SDK

WebSDK doesn't receive published stream from iOS SDK
Currenty, I've completed WebSDK based videocall. User1 joins to the chatX and publishes his stream. User2 receives this stream via "stream-added" event in the chatX and successfully subscribes for it.
But "stream-added" event doesn't fire when user1 joins to videochat from iOS App.
client.on('stream-added', function (evt) {
var stream = evt.stream;
console.log("New stream added: " + stream.getId());
console.log("Subscribe ", stream);
client.subscribe(stream, function (err) {
console.log("Subscribe stream failed", err);
});
});
client.on('stream-subscribed', function (evt) {
var stream = evt.stream;
console.log("Subscribe remote stream successfully: " + stream.getId());
if ($('#videochat-remoteVideo #agora_remote'+stream.getId()).length === 0) {
$('#videochat-remoteVideo').append('<div id="agora_remote'+stream.getId()+'"></div>');
}
remoteBigLocalSmall();
stream.play('agora_remote' + stream.getId());
});
iOS app reveives the stream published from Web, whereas Web client doesn't receives the stream from iOS client.
What can be wrong with my implementation? How to receive stream from iOS client?
UPD:
Join chat code:
user_id = '111';
client.join(channel_key, videochat_id, user_id, function(uid) {
...
I've changed user_id type from string to int and now it works. I can't understand why, because documentation allows string uid:
join(tokenOrKey: string | null, channel: string, uid: number | string
| null, onSuccess?: function, onFailure?: function): void
The issue you are facing is related to your use of the wrong API Method. You are using joinChannelByToken which only works with Integer values when you should be using joinChannel(byUserAccount: ...) because that takes a String uid as a parameter.
let myStringId = "someStringId"
agoraKit.joinChannel(byUserAccount: myStringId, token: nil, channelId: "demoChannel1") { (sid, uid, elapsed) in
// Did join channel "demoChannel1"
}
Changing client.join method parameter uid from string to integer resolved the issue

Limit Google Sign-In to .edu accounts in Meteor

I'm trying to limit my Google + Sign-In Button to only allow #something.edu accounts to sign in. How would I go about doing this. This is my code so far:
Template.googleLogin.events({
'click #gLogin': function(event) {
Meteor.loginWithGoogle({}, function(err){
if (err) {
throw new Meteor.Error("Google login didn't work!");
}
else {
Router.go('/home')
}
});
}
})
Template.primaryLayout.events({
'click #gLogout': function(event) {
Meteor.logout(function(err){
if (err) {
throw new Meteor.Error("Hmm looks like your logout failed. ");
}
else {
Router.go('/')
}
})
}
})
You can accomplish this using Accounts.config (in the root directory, so it runs on both the client and server)
Accounts.config({ restrictCreationByEmailDomain: 'something.edu' })
If you need something more custom, you can replace something.edu with a method if you need to fine grain your requirement, i.e for any .edu domain:
Accounts.config({ restrictCreationByEmailDomain: function(address) {
return new RegExp('\\.edu$', 'i')).test(address)
}
});
The accounts package allows configuring account creation domain through:
Accounts.config({
restrictCreationByEmailDomain: 'something.edu'
})
But this has some limitations in case of google:
This is only client side and only allows for the login form to get properly styled to represent the domain's logo etc. But it can be very easily overcome by crafting the google oauth signin url by hand
In case you need to configure extra options like allowing multiple domains or a domain and some outside users (perhaps third party contractors or support from a software company etc) this does not work. In case of accounts-google, the package checks if restrictCreationByEmailDomain is a String and if it is instead a function, it just discards it.
Therefore, to be able to properly and securely utilize such functionality, you need to use the official Accounts.validateNewUser callback:
Accounts.validateNewUser(function(newUser) {
var newUserEmail = newUser.services.google.email;
if (!newUserEmail) throw new Meteor.Error(403,'You need a valid email address to sign up.');
if (!checkEmailAgainstAllowed(newUserEmail)) throw new Meteor.Error(403,'You need an accepted organization email address to sign up.');
return true;
});
var checkEmailAgainstAllowed = function(email) {
var allowedDomains = ['something.edu'];
var allowedEmails = ['someone#example.com'];
var domain = email.replace(/.*#/,'').toLowerCase();
return _.contains(allowedEmails, email) || _.contains(allowedDomains, domain);
};
If you want to be extra cautious, you can implement the same for the Accounts.validateLoginAttempt and Accounts.onCreateUser callbacks as well.

getting user info google plus api

How can I get public info of a user from google plus login button integrated on the site, here is the code which is giving me email, I need more info which is provide by google plus :
<div id="signin-button" class="show">
<div class="g-signin" data-callback="loginFinishedCallback"
data-approvalprompt="force"
data-clientid="9076269517.apps.googleusercontent.com"
data-scope="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email"
data-height="short"
data-cookiepolicy="single_host_origin">
</div>
java script :
function loginFinishedCallback(authResult) {
if (authResult) {
if (authResult['error'] == undefined){
gapi.auth.setToken(authResult); // Store the returned token.
toggleElement('signin-button'); // Hide the sign-in button after successfully signing in the user.
getEmail(); // Trigger request to get the email address.
} else {
console.log('An error occurred');
}
} else {
console.log('Empty authResult'); // Something went wrong
}
}
function getEmail(){
// Load the oauth2 libraries to enable the userinfo methods.
gapi.client.load('oauth2', 'v2', function() {
var request = gapi.client.oauth2.userinfo.get();
request.execute(getEmailCallback);
});
}
function getEmailCallback(obj){
var el = document.getElementById('email');
var email = '';
if (obj['email']) {
email = 'Email: ' + obj['email'];
}
//console.log(obj); // Uncomment to inspect the full object.
el.innerHTML = email;
toggleElement('email');
}
function toggleElement(id) {
var el = document.getElementById(id);
if (el.getAttribute('class') == 'hide') {
el.setAttribute('class', 'show');
} else {
el.setAttribute('class', 'hide');
}
}
I tried replacing email with name, userId but getting nothing from these variables.
How can I get basic information of a user when he is logged in through google plus.
Similar to how you have loaded the oauth2 v2 client package using gapi.client.load, you will use this again to load the plus v1 client package. This will give you a number of packages and methods under the gapi.client.plus namespace.
The Plus API includes a package to load information about People, including getting them by their User ID or, since they have authenticated with you, you can use the special identifier "me".
Full details and an example are given at https://developers.google.com/+/api/latest/people/get, but here is an (untested) similar function to your getEmail() method that would get their full name:
function getFullName(){
// Load the Plus library to get the People package and methods
gapi.client.load('plus', 'v1', function() {
var request = gapi.client.plus.people.get('me');
request.execute(getFullNameCallback);
});
};
function getFullNameCallback(obj){
var el = document.getElementById('email');
var name = '';
if (obj['displayName']) {
name = 'Name: '+obj.displayName;
}
el.innerHTML = name;
toggleElement('name');
};
The above code snippet no longer seems to work.
Once again we are chasing our tails over something
google now changed......
error "Access Not Configured. Please use Google Developers Console to activate the API for your project."
I assumed it it might be the "Google+ API" so it is switched on in the developer console,
still no working however.
Yet api explorer shows promisingly that some sort of code can work,
however its a dogs breakfast trying to discern what javascript code is working there.
So so useful api explorer...., but how about google show a simple WORKING example in code that we can look at for this same request?

Meteor.http.get issue with Twitter API

I am using Meteor and the Twitter API for a project. I want to get information on a user from Twitter. I wrote a function that for example returns only the location of a user from Twitter. I believe this is the proper way to do a request on Meteor. Here it is :
Meteor.methods({getTwitterLocation: function (username) {
Meteor.http.get("https://api.twitter.com/1/users/show.json?screen_name="+ username +"&include_entities=true", function(error, result) {
if (result.statusCode === 200) {
var respJson = JSON.parse(result.content);
console.log(respJson.location);
console.log("location works");
return (respJson.location)
}else {
return ( "Unknown user ")
}
});
}});
Now this function will log what's in the console on my Git Bash. I get someones Location by doing a Meteor.call. But I want to post what that function returns on a page. In my case, I want to post in on a user's profile. This doesn't work. But the console.log(respJson.location) returns the location in my Git Bash but it won't display anything on the profile page. This is what I did on my profile page:
profile.js :
Template.profile.getLocation= function(){
return Meteor.call("getTwitterLocation","BillGates");
}
profile.html :
<template name="profile">
from {{getLocation}}
</template>
With that I get "Seattle, WA" and " "location works" on my Git Bash but nothing on the profile page. If anyone knows what I can do, that'd be really appreciated. Thanks.
Firstly when data is returned from the server you need to use a synchronous call, as the callback will return the data when the server already thinks the meteor method has completed. (the callback will be fired at a later time, when the data is returned from the server, by which time the meteor client would have already got a response)
var result = Meteor.http.get("https://api.twitter.com/1/users/show.json?screen_name="+ username +"&include_entities=true");
if (result.statusCode === 200) {
var respJson = JSON.parse(result.content);
console.log(respJson.location);
console.log("location works");
return (respJson.location)
}else {
return ( "Unknown user ")
}
The second is you need to use a Session hash to return the data from the template. This is because it will take time to get the response and the getLocation would expect an instant result (without a callback). At the moment client side javascript can't use synchronous api calls like on the server.
Template.profile.getLocation= function(){
return Session.get("twitterlocation");
}
Use the template created event to fire the meteor call:
Template.profile.created = function() {
Meteor.call("getTwitterLocation","BillGates", function(err,result) {
if(result && !err) {
Session.set("twitterlocation", result);
}
else
{
Session.set("twitterlocation", "Error");
}
});
});
Update:
Twitter has since updated its API to 1.1 a few modifications are required:
You now need to swap over to the 1.1 api by using 1.1 instead of 1. In addition you need to OAuth your requests. See https://dev.twitter.com/docs/auth/authorizing-request. Below contains sample data but you need to get proper keys
var authkey = "OAuth oauth_consumer_key="xvz1evFS4wEEPTGEFPHBog",
oauth_nonce="kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg",
oauth_signature="tnnArxj06cWHq44gCs1OSKk%2FjLY%3D",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp=""+(new Date().getTime()/1000).toFixed(0)+"",
oauth_token="370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb",
oauth_version="1.0"";
Be sure to remove the newlines, I've wrapped it to make it easy to read.
var result = Meteor.http.get("https://api.twitter.com/1.1/users/show.json?screen_name="+ username +"&include_entities=true",{headers:{Authorization : authkey});
If you find this a bit troublesome it might be easier to just use a package like https://github.com/Sewdn/meteor-twitter-api via meteorite to OAuth your requests for you.