I'm trying to send push notifications to my users via Parse Background Job if they are in proximity of the pet that was created.
Every user in range gets crosschecked with the pets (confirmed via log) but the push notifications are sent to the wrong user or most of the time not even sent at all. I'm pretty sure I messed the promises up but can't the problem here.
Any help would be much appreciated, thanks!
Parse.Cloud.job("locationPush", function(request, status) {
Parse.Cloud.useMasterKey();
var Pet = Parse.Object.extend("Pet");
var petQuery = new Parse.Query(Pet);
petQuery.equalTo("initialPushSent", false);
petQuery.equalTo("status", "missing");
petQuery.equalTo("deleted", false);
petQuery.find().then(function(pets) {
var petPromises = [];
_.each(pets, function(pet) {
console.log("checking pet: " + pet.id);
var petLocation = pet.get("lastSeenLocation");
var query = new Parse.Query(Parse.User);
query.withinKilometers("lastLocation", petLocation, 50);
query.find().then(function(users) {
var userPromises = [];
_.each(users, function(user) {
var userPromise = new Parse.Promise();
userPromises.push(userPromise);
console.log("check user " + user.id + " with pet: " + pet.id);
var pushPromises = [];
if(petLocation.kilometersTo(user.get("lastLocation")) <= user.get("pushRadius")){
console.log("send push to" + user.id);
var promise = new Parse.Promise();
pushPromises.push(promise);
Parse.Push.send({
channels: [ "user_" + user.id ],
data: {
alert : "Neues vermisstes Tier im Umkreis"
}},
{ success: function() {
console.log("push sent to: " + user.id)
},
error: function(error) {
console.log("error sending push: " + error)
}}).then (function(result){
promise.resolve();
}, function(error) {
promise.reject();
});
}
return Parse.Promise.when(pushPromises);
});
return Parse.Promise.when(userPromises);
});
petPromises.push(pet.save());
});
return Parse.Promise.when(petPromises);
}).then(function() {
status.success("location Send complete");
}, function(error) {
status.error("location Send Error");
});
You need to return a promise from really absolutely every function that does something asynchronous. In your case, you dropped the promise that was returned by query.find(), and called pet.save() immediately. I guess you wanted to chain them.
Also, your userPromises were never resolved, which likely is the reason that your chain failed. And your pushPromises array is quite unnecessary, as it only will contain at most one promise.
Also, I've used _.map instead of pushing to arrays, and removed the deferred antipattern that you had used. It makes the returns more prominent, so that it's easier to spot if you forgot one.
Parse.Cloud.job("locationPush", function(request, status) {
Parse.Cloud.useMasterKey();
var Pet = Parse.Object.extend("Pet");
var petQuery = new Parse.Query(Pet);
petQuery.equalTo("initialPushSent", false);
petQuery.equalTo("status", "missing");
petQuery.equalTo("deleted", false);
return petQuery.find().then(function(pets) {
return Parse.Promise.when(_.map(pets, function(pet) {
console.log("checking pet: " + pet.id);
var petLocation = pet.get("lastSeenLocation");
var query = new Parse.Query(Parse.User);
query.withinKilometers("lastLocation", petLocation, 50);
query.find().then(function(users) {
return Parse.Promise.when(_.map(users, function(user) {
console.log("check user " + user.id + " with pet: " + pet.id);
if (petLocation.kilometersTo(user.get("lastLocation")) <= user.get("pushRadius")) {
console.log("send push to" + user.id);
return Parse.Push.send({
channels: ["user_" + user.id],
data: {
alert: "Neues vermisstes Tier im Umkreis"
}
}, {
success: function() {
console.log("push sent to: " + user.id)
},
error: function(error) {
console.log("error sending push: " + error)
}
}); // we already got a promise here!
} else
return null;
}));
}).then(function() {
return pet.save();
});
}));
}).then(function() {
status.success("location Send complete");
}, function(error) {
status.error("location Send Error");
});
});
Related
I am new to JS.
I am trying to build API server, this server must received data from other server using socket.
Currently I am using net library, I am facing a problem.
I should get data to check whether hardware worked or not, but I only get
undefiend(empty array).
I found some sources making async function to get called, but still I can't get it.
here is my code.
router.post("/Updated", async function(req, res, next) {
.....
//connect to station server for locking
var data = {
cmd: "lockStationQuery",
stationId: STATION_ID,
powerBankId: POWER_BANK_ID,
userId: USER_ID,
number: channelValue
};
var stringData = JSON.stringify(data);
var jsonData = JSON.parse(stringData);
var [client, recvData] = await getConnectionSocket(
USER_ID,
res,
merchant_uid,
amount
);
let successToWriteData = await writeData(client, stringData);
//Fail to send data to lock the Station
if (!successToWriteData) {
res.status(500).json({
RESULT: "FAIL",
REASON:
"error code 504"
});
res.end();
return;
}
console.log("received data", recvData); //this is empty array
jsonData = JSON.parse(recvData[0]);
Here is my getConnectionSocket function.
async function getConnectionSocket(USER_ID, res, merchant_uid, amount) {
//서버에 해당 포트로 접속
var client = "";
var recvData = [];
var local_port = "";
let status = {};
client = net.connect({ port: 8999, host: "localhost" }, function() {
console.log(
"connect log======================================================================"
);
console.log("connect success");
console.log("local = " + this.localAddress + ":" + this.localPort);
console.log("remote = " + this.remoteAddress + ":" + this.remotePort);
local_port = this.localPort;
this.setEncoding("utf8");
this.setTimeout(300000); // timeout : 10분
console.log("client setting Encoding:binary, timeout:300000");
console.log("client connect localport : " + local_port);
});
// 접속 종료 시 처리
client.on("close", function() {
console.log("client Socket Closed : " + " localport : " + local_port);
});
// 데이터 수신 후 처리
await client.on("data", function(data) {
console.log(
"data recv log======================================================================"
);
recvData.push(data);
console.log(recvData); //I want this data
console.log("data.length : " + data.length);
console.log("data recv : " + data);
let jsonData = JSON.parse(data);
if (jsonData.cmd === "removedPowerBank") {
if (jsonData.errorCode !== 0) {
//환불
console.log("환불 시작");
let cancel = cancelOrder(merchant_uid, USER_ID, res);
//여기서 환불 purchase db에 쓰기
} else {
console.log("PURCHASE 성공후 디비에 씀");
//구매 purchase db에 쓰기(getRentId에 썼음)
let purchased = writePurchaseDataInDB(
USER_ID,
res,
merchant_uid,
amount
);
console.log(purchased);
}
}
client.end();
});
client.on("end", function() {
console.log("client Socket End");
});
client.on("error", function(err) {
console.log("client Socket Error: " + JSON.stringify(err));
});
client.on("timeout", function() {
console.log("client Socket timeout: ");
});
client.on("drain", function() {
console.log("client Socket drain: ");
});
client.on("lookup", function() {
console.log("client Socket lookup: ");
});
return [client, recvData]; //recvData is always empty array
}
which way is best to address to resolve this?
Need some clarification on below point
are you getting correct value(s) in below log ? Or you undefined in them too.
console.log("data.length : " + data.length);
console.log("data recv : " + data);
also add this one
console.log("data type : " + typeof(data));
My Parse cloud code is not responding with an error or success. It just times out, I don't know what I'm doing wrong. It should save multiple values in different tables, and finish with sending a push message to a user.
The push message and user table are adjusted and send, but the street and the ledger objects are not being saved correctly. Also the response is not being called.
I did work in the past (or I was just lucky). Any thought on what I'm doing wrong?
var buyerId = request.params.buyerid;
var sellerName = request.params.sellername;
var streetId = request.params.streetid;
var amount = request.params.amount;
var pushMessageTemplate = request.params.pushMessage;
var log = request ? request.log : console;
var Streets = Parse.Object.extend('SHStreets');
var streetQuery = new Parse.Query(Streets);
streetQuery.equalTo("objectId", streetId);
streetQuery.first({
useMasterKey: true,
success: function (street) {
var streetName = street.get("name");
var query = new Parse.Query(Parse.User);
query.equalTo("objectId", buyerId);
query.first({
useMasterKey: true,
success: function (user) {
var promises = [];
var now = new Date();
var buyerName = user.get("username");
// Set and save the change
user.set("balance", user.get("balance") - amount);
user.set("streets", user.get("streets") + 1);
street.set("current_owner", user);
street.set("owned_since", now);
street.set("for_sale", false);
street.set("price_bought", amount);
var acl = new Parse.ACL();
acl.setPublicReadAccess(true);
acl.setWriteAccess(user, true);
street.setACL(acl);
//update ledger
var Ledger = Parse.Object.extend("Ledger");
var ledger = new Ledger();
ledger.set("type", "buy");
ledger.set("amount", amount);
ledger.set('ledger_time', now);
ledger.set("user", user);
ledger.set("description", "x");
promises.push(Parse.Object.saveAll([street, user, ledger], { useMasterKey: true }));
// Find users with a given email
var userQuery = new Parse.Query(Parse.User);
userQuery.equalTo("objectId", user.id);
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.exists("user"); // filter out installations without users
pushQuery.include('user'); // expand the user pointer
pushQuery.matchesQuery("user", userQuery);
// Send push notification to query
promises.push(Parse.Push.send({
where: pushQuery, // Set our installation query
data: {
alert: _.template(pushMessageTemplate)({
sellername: sellerName,
streetname: streetName,
amount: amount
})
}
}, {
useMasterKey: true,
}));
return Parse.Promise.when(promises).then(function () {
response.success("success");
});
},
error: function (error) {
log.error('buy-street error', error.message);
response.error("Uh oh, buy request success failed." + error.message);
}
});
},
error: function (error) {
log.error('buy-street error', error.message);
response.error("Uh oh, buy request success failed." + error.message);
}
});
It looks like your first query's success function doesn't return anything:
streetQuery.first({
useMasterKey: true,
success: function (street) { // this function doesn't return anything
// ...
query.first({ // You probably want to return this promise
useMasterKey: true,
success: function (user) { // this is the function that you're returning to
// ...
return Parse.Promise.when(promises).then(function () {
response.success("success");
});
},
});
}
});
Javascript will return undefined by default if you don't have a return statement.
I was missing a function error for the return of the promises.
return Parse.Promise.when(promises).then(function () {
// Set the job's sucess status
response.success('success');
},function(error) {
response.error(error);
});
I tried setting up cloud code on my new parse server (on AWS EB) to send push notifications with the following code:
Parse.Cloud.define("sendPush", function(request, response) {
var currentUser = request.user;
var recipient = request.params.recipient;
if (!currentUser) {
response.error("Must be logged in.");
return;
}
if (!recipient) {
response.error("Must specify recipient.");
return;
}
var userQuery = new Parse.Query(Parse.User);
userQuery.equalTo('objectId', recipient);
response.success(userQuery.get('name'))
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.matchesQuery('user', userQuery);
Parse.Push.send({
where: pushQuery,
data: {
alert: "Hello, World",
badge: "Increment"
}
}, {
success: function() {
response.success("Push sent to " + recipient + " from " + request.user.get("username"));
},
error: function(error) {
response.error('Not working')
}
});
});
It doesn't return back an error but the notification doesn't go through either. Instead, I get the following error:
Optional({
"_rejected" = 0;
"_rejectedCallbacks" = (
);
"_resolved" = 0;
"_resolvedCallbacks" = (
);
})
Any idea why this is happening?
EDIT
I decided to change the code to see if the function is even retrieving results, but looks like it doesn't. Here's the new code:
Parse.Cloud.define("sendPush", function(request, response) {
var currentUser = request.user;
var recipient = request.params.recipient;
if (!currentUser) {
response.error("Must be logged in.");
return;
}
if (!recipient) {
response.error("Must specify recipient.");
return;
}
var userQuery = new Parse.Query(Parse.User);
userQuery.equalTo('objectId', recipient);
userQuery.find
({
success: function(results)
{
if (results.length > 0)
{
var objectId = results[0].id;
var gate = results[0].get("name");
response.success(JSON.stringify(results[0]));
}
else
{
response.error("wont work");
};
}
})
});
and get the following error:
Optional(Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 3840.)" (No value.) UserInfo=0x7ff163c587d0 {NSDebugDescription=No value.})
I have a NodeJS script that I have been working on, but the biggest problem I have is that chaining all of these promises is not only ugly to look at, but difficult to maintain as time goes on.
I want to convert these individual promises into one, using the Promise.all() method, but am not sure how I can get the same functionality and assign variables from one promise to another using this method.
For example, my second promise: methods.login() returns a sessionId that is used in almost every other promise. How would I assign that variable and pass it to further dependent promises using Promise.all()??
Here is my current code:
var zabbixApi = require('./zabbixapi.js');
var methods = require('./methods.js');
var fs = require('fs');
var SESSIONID;
function main() {
var apiVersion, loggedOut, numTemplates, numHosts, numHostGroups, numItems;
var templates = []
, hostGroups = []
, hosts = [];
/*var promises = [];
promises.push(zabbixApi(methods.getApiVersion()));
promises.push(zabbixApi(methods.login(SESSIONID)));
promises.push(zabbixApi(methods.getHostGroups(SESSIONID)));
promises.push(zabbixApi(methods.getTemplates(SESSIONID)));
promises.push(zabbixApi(methods.getHosts(SESSIONID)));
// promises.push(zabbixApi(methods.configExport(hostIds, templateIds, groupIds, SESSIONID)));
promises.push(zabbixApi(methods.logout(SESSIONID)));
Promise.all(promises).then(function (values) {
console.log('All promises completed.');
}, function (reason) {
console.log('Error completing promises: ' + reason);
});*/
// Get API version
zabbixApi(methods.getApiVersion())
// If successful, login to the API
.then(function (version) {
apiVersion = version.result;
// Verify that the API version returned is correct
if (apiVersion.length < 5 || !apiVersion) {
console.log('Error occurred retrieving API version: ' + version.error.data);
return 1;
} else {
return zabbixApi(methods.login(SESSIONID));
}
}, function (error) {
console.log('Error occurred retrieving API version: ' + error);
return 1;
// If login successful, continue operations until logged out or error
}).then(function (auth) {
SESSIONID = auth.result;
if (!SESSIONID) {
console.log('Error retrieving session id: ' + auth.error.data);
return 1;
} else {
console.log('Logged in successfully!');
return zabbixApi(methods.getHostGroups(SESSIONID));
}
}, function (error) {
console.log('Error occurred authenticating: ' + error);
return 1;
// Attempt to retrieve all hostgroup information
}).then(function (hostgroups) {
numHostGroups = hostgroups.result.length;
hostGroups = hostgroups.result;
if (!numHostGroups) {
console.log('Error occurred retrieving host groups: ' + hostgroups.error.data);
return 1;
} else {
return zabbixApi(methods.getTemplates(SESSIONID));
}
}, function (error) {
console.log('Error occurred retrieving host groups: ' + error);
return 1;
// Attempt to retrieve host information
}).then(function (template) {
numTemplates = template.result.length;
templates = template.result;
if (!numTemplates) {
console.log('Error occurred retrieving templates: ' + template.error.data);
return 1;
} else {
return zabbixApi(methods.getHosts(SESSIONID));
}
}, function (error) {
console.log('Error occurred retrieving templates: ' + error);
return 1;
// Attempt to retrieve host information
}).then(function (hosts) {
numHosts = hosts.result.length;
hosts = hosts.result;
if (!numHosts) {
console.log('Error occurred retrieving host groups: ' + hosts.error.data);
return 1;
} else {
var groupIds = []
, hostIds = []
, templateIds = [];
// Extract all groupIds for host groups
for (var i = 0; i < numHostGroups; i++) {
groupIds[i] = hostGroups[i].groupid;
}
// Extract all hostIds for hosts
for (var i = 0; i < numHosts; i++) {
hostIds[i] = hosts[i].hostid;
}
// Extract all templateIds for templates
for (var i = 0; i < numTemplates; i++) {
templateIds[i] = templates[i].templateid;
}
return zabbixApi(methods.configExport(hostIds, templateIds, groupIds, SESSIONID));
}
}, function (error) {
console.log('Error occurred retrieving host groups: ' + error);
return 1;
// Attempt to retrieve configuration information
}).then(function (config) {
//console.log(config);
if (config.error) {
console.log('Error occurred retrieving configuration: ' + config.error.message + ': ' + config.error.data);
return 1;
} else {
if (!writeToFile(config)) {
return 1;
} else {
console.log('Configuration details exported successfully.');
}
return zabbixApi(methods.logout(SESSIONID));
}
}, function (error) {
console.log('Error occurred retrieving configuration: ' + error);
return 1;
// Attempt to logout of API, if logout successful exit safely
}).then(function (logout) {
loggedOut = logout.result;
if (!loggedOut) {
console.log('Error logging out: ' + logout.error.data);
return 1;
} else {
console.log('Logged out successfully!');
return 0;
}
}, function (error) {
console.log('Error occurred logging out: ' + error);
return 1;
});
}
function writeToFile (config) {
fs.writeFile('zabbix_config_export.json', JSON.stringify(config), function (err) {
if (err) {
return console.log('Error writing configuration to file: ' + err);
}
});
return true;
}
main();
You can use Promise.all() on operations that can run in parallel, but not on operations that must be performed in a specific sequence.
In looking at your code, it appears that you do have a couple places where you can do some operations in parallel, but not all your operations can be done that way. It appears you can do things in this general sequence:
getApiVersion
Login to session
In parallel (getHostGroups, getTemplates, getHosts)
configExport previous results
In parallel (logout, writeToFile)
That can be achieved like this:
var zabbixApi = require('./zabbixapi.js');
var methods = require('./methods.js');
var fs = require('fs');
var SESSIONID;
function logout() {
if (SESSIONID) {
var p = zabbixApi(methods.logout(SESSIONID));
// clear SESSIONID to show that we've already launched a logout attempt, no need to try again
SESSIONID = null;
return p;
} else {
return Promise.resolve();
}
}
function main() {
var apiVersion, hostGroups, templates, hosts;
// Get API version
zabbixApi(methods.getApiVersion())
// If successful, login to the API
.then(function (version) {
apiVersion = version.result;
// Verify that the API version returned is correct
if (!apiVersion || apiVersion.length < 5) {
throw new Error('Error occurred retrieving API version: ' + version.error.data);
} else {
return zabbixApi(methods.login(SESSIONID));
}
}, function (error) {
throw new Error('Error occurred retrieving API version: ' + error);
// If login successful, continue operations until logged out or error
}).then(function (auth) {
SESSIONID = auth.result;
if (!SESSIONID) {
throw new Error('Error retrieving session id: ' + auth.error.data);
} else {
console.log('Logged in successfully!');
// now that we are logged in, a number of operations can be launched in parallel
return Promise.all([
zabbixApi(methods.getHostGroups(SESSIONID),
zabbixApi(methods.getTemplates(SESSIONID),
zabbixApi(methods.getHosts(SESSIONID)
]);
}
}, function (error) {
throw new Error('Error occurred authenticating: ' + error);
// we have hostGroups, templates and hosts here
}).then(function(r) {
// r[0] = hostGroups, r[1] = templates, r[2] = hosts
// check hostGroups
hostGroups = r[0].result;
if (!hostGroups.length) {
throw new Error('Error occurred retrieving host groups: ' + hostgroups.error.data);
}
// check templates
templates = r[1].result;
if (!templates.length) {
throw new Error('Error occurred retrieving templates: ' + template.error.data);
}
// check host information
hosts = r[2].result;
if (!hosts.length) {
throw new Error('Error occurred retrieving host groups: ' + hosts.error.data);
}
// utility function for retrieving a specific property from each array of objects
function getIds(array, prop) {
return array.map(function(item) {
return item[prop];
});
}
var groupIds = getIds(hostGroups, "groupid");
var hostIds = getIds(hosts, "hostid");
var templateIds = getIds(templates, "templateid");
return zabbixApi(methods.configExport(hostIds, templateIds, groupIds, SESSIONID));
}).then(function(config) {
if (config.error) {
throw new Error('Error occurred retrieving configuration: ' + config.error.message + ': ' + config.error.data);
}
// simultaneously write to file and logout (since these are not dependent upon one another)
return Promise.all(logout(), writeToFile(config));
}).then(function() {
// success here, everything done
}, function(err) {
// upon error, try to logout and rethrow earlier error
return logout().then(function() {
throw err;
}, function() {
throw err;
});
}).then(null, function(err) {
// error here
console.log(err);
});
}
function writeToFile (config) {
return new Promise(function(resolve, reject) {
fs.writeFile('zabbix_config_export.json', JSON.stringify(config), function (err) {
if (err) {
return Promise.reject(new Error('Error writing configuration to file: ' + err));
}
resolve();
});
});
}
main();
This also makes some other important structural changes/fixes:
Any time you have a reject/catch handler, if you don't either return a rejected promise or throw from that handler, then the promise chain will continue which is not what you want and you were doing that in almost every reject handler you had.
No need to have a reject handler for every single promise. If you just intend for any reject to stop the chain anyway, then you can just make sure that the reject reason is descriptive and do all failure logging one place at the end of the chain.
This uses Promise.all() in two places where operations can run in parallel because they are not dependent upon one another, but the code logic wants to know when they are all done.
writeToFile() is changed to return a promise.
Create a logout() function that can be safely called in several error paths so all error and success paths at least attempt the logout (if login succeeded)
Swap the two conditions when checking apiVersion because you should check !apiVersion first.
Promises.all is intended to handle asynchronous functions when they run in parallel and you need to wait until they all are finished. The promises in the code you shared are not independent so you can't use Promises.all here. Check out this reference to see the Promises.all usage.
Having difficulty with this working at seemingly random times. When I go into the chat page, the controller activates, and immediately after that the before addlistener and after addlistener console.logs fire, and then sometimes when I send a message, it is received with a console printout of the package contents, but more often it isn't. And sometimes, it is printed on the console of the computer that fires off the send message instead of the receiving end.
At the very least, though, whenever I send a message, even if I don't get a console printout of the package, I get a corresponding [QBChat RECV]:, [object Object] - hit the button ten times, get ten QBChat RECVs.
.controller('ChatCtrl', function($scope, $stateParams, $timeout, $rootScope, $ionicLoading) {
console.log("Inside ChatCtrl");
QB.createSession(function(err,result){
console.log('Session create callback', err, result);
console.log('Session create callback' + JSON.stringify(result));
});
$scope.settings = {};
$scope.user = {};
$scope.error = {};
$scope.signInClick = function() {
console.log('Login was clicked');
$scope.loading = $ionicLoading.show({
content: 'Logging in',
animation: 'fade-in',
showBackdrop: true,
maxWidth: 200,
showDelay: 0
});
var params = {'login': ($scope.user.username), 'password': ($scope.user.password)}
console.log("params... " + JSON.stringify(params));
QB.users.create(params, function(err, user){
if (user) {
console.log("successful user.create... " + JSON.stringify(user));
var jid = user.id + "-#####" + "#chat.quickblox.com";
var chatparams = {'jid': jid, 'password': ($scope.user.password)};
QB.chat.connect(chatparams, function(err, roster) {
console.log("err from qb.chat.connect... " + JSON.stringify(err));
console.log("roster from qb.chat.connect .... " + JSON.stringify(roster));
});
} else {
if (err.message == "Unprocessable Entity"){
QB.login(params, function(err, user){
if (user) {
console.log("Logged into QB with " + JSON.stringify(user));
var jid = user.id + "-#####" + "#chat.quickblox.com";
console.log(user.login + "'s jid is......" + jid);
var chatparams = {'jid': jid, 'password': ($scope.user.password)};
QB.chat.connect(chatparams, function(err, roster) {
console.log("stringifying the roster... " + JSON.stringify(roster));
});
}
else {
console.log(JSON.stringify(err));
}
});
}
}
});
// var chatparams = {'jid': jid, 'password': ($scope.user.password)};
// console.log("the jid is......" + jid);
// console.log("chatparams is ......" + JSON.stringify)
Parse.User.logIn(($scope.user.username) , $scope.user.password, {
success: function(_user) {
console.log('Login Success');
console.log('user = ' + _user.attributes.username);
console.log('email = ' + _user.attributes.email);
$ionicLoading.hide();
$rootScope.user = _user;
$rootScope.isLoggedIn = true;
// $state.go('tab.home');
},
error: function(user, err) {
$ionicLoading.hide();
// The login failed. Check error to see why.
if (err.code === 101) {
$scope.error.message = 'Invalid login credentials';
} else {
$scope.error.message = 'An unexpected error has ' +
'occurred, please try again.';
}
$scope.$apply();
}
});
// $state.go('tab.profile');
};
$scope.sendMessageClick = function() {
var user = $rootScope.user.attributes.username;
console.log("user = " + user);
console.log('sendMessageclick');
var countchew = "3354163-######chat.quickblox.com"; //countchew
var starshipenterprise = "3354099-######chat.quickblox.com"; //starshipenterprise
QB.chat.roster.get(function(roster) {
console.log("roster.get before if block " + JSON.stringify(roster));
});
if (user == "countchew"){
QB.chat.roster.confirm(starshipenterprise, function(){
console.log("roster.confirm called");
});
QB.chat.roster.add(starshipenterprise, function() {
console.log("roster.add called");
});
QB.chat.send(starshipenterprise, {
type: 'chat',
name: 'testmessage',
body: 'Hello world!',
extension: {save_to_history: 1}
});
// QB.chat.roster.remove(starshipenterprise, function() {
// console.log("roster.remove starship ... ");
// });
QB.chat.roster.get(function(roster) {
console.log("end of if statement " + JSON.stringify(roster));
});
} else if (user == "starshipenterprise"){
QB.chat.roster.confirm(countchew, function() {
console.log("roster.confirm called");
});
QB.chat.roster.add(countchew, function() {
console.log("roster.add called");
});
QB.chat.send(countchew, {
type: 'chat',
body: 'Hello world!'
});
}
};
console.log("before addlistener");
QB.chat.addListener({from: '3354163-######chat.quickblox.com'}, function() {
QB.chat.onMessageListener = function(userId, message) {
console.log('userId ..... ' + userId);
console.log('message .... ' + JSON.stringify(message));
};
});
console.log("after addlistener");
var chatparams1 = {from: '3354099-######chat.quickblox.com'};
console.log("before addlistener");
QB.chat.addListener(chatparams1, function() {
QB.chat.onMessageListener = function(userId, message) {
console.log('userId ..... ' + userId);
console.log('message .... ' + JSON.stringify(message));
};
});
console.log("after addlistener");
})
Great! Figured it out.
You need to pay attention to the XML packages that it sends. What was happening is that somehow, when it first got up and running and was working well with the corresponding QB chat addresses for the account, after that, at some point it started appending a string of numbers-quickblox-numbers (35896363-quickblox-20942 or whatever) in the 'from' field for the address, which is what I had my listener listening to. The confusing thing is that this worked sporadically.
You can't hardcode the addresses because this string of numbers at the end changes with every login.
Instead, it is working for the time being to just listen for messages with the parameters {name: 'message', type: 'chat'}.
A better way could be:
QB.chat.addListener( {name: 'message'}, function() {
$log.debug(" main: QB listener by filter was triggered");
});
Or just:
QB.chat.onMessageListener = showMessage;
That code has to be run once (at first init, on system loading).
onMessageListener will be triggered every time.
addListener will be triggered only if msg is with name'message'. (filter of listener)
Then you need a function with such a signature:
function showMessage(userId, msg) {
console.log('main.showMessage:: on message', msg)
}