How to send push notifications form javascript using quickblox - javascript

I am trying to send push notifications messages through Quickblox from my backend server. The code that does this goes like the following:
app.post('/requests', function(req, res) {
var mobileNumber = req.param('mobile_number');
if (typeof mobileNumber === 'undefined') {
return res.badRequest("Parameters missing: [mobile_number]");
}
var query = {
international_number: mobileNumber
}
User.findOne(query, function(err, user) {
if (err) {
return res.dbError(err);
}
if (!user) {
console.log("User not found");
return res.apiError("NOT_FOUND");
}
var request = new Request();
request.sender_id = req.user._id;
request.receiver_id = user._id;
request.status = 'pending';
request.save(function(err) {
if (err) {
return res.dbError(err);
}
var response = {};
response.image_url = user.image_url;
response.id = request._id;
// ¡TODO! Notify the end user -- Quickblox
QB.createSession(function(err, result) {
if (err) {
console.log(err);
return res.apiError();
}
console.log("**** SESSION CREATE ****")
console.log(result);
var params = {
login: req.user.qb_username,
password: req.user.qb_password
}
console.log("LOGIN PARAMS");
console.log(params);
QB.login(params, function(err, result) {
if (err) {
console.log(err);
return res.apiError();
}
console.log("**** USER LOGIN ****")
console.log(result);
var params = {
notification_type: 'push',
environment: 'production',
user : {
ids: user.qb_id
},
message: 'SSBsb3ZlIE0mTSdzISBFc3BlY2lhbGx5IHJlZCBvbmUh',
push_type: user.device.notification_channel
}
console.log("EVENTS CREATE PARAMS");
console.log(params);
QB.messages.events.create(params, function(err, result) {
if (err) {
console.log(err);
return res.apiError();
}
console.log("**** MESSAGE EVENT CREATE ****");
console.log(result);
console.log(result.event.subscribers_selector);
QB.messages.events.list(function(err, result) {
if (err) {
console.log(err);
return res.apiError();
}
console.log(result);
console.log("**** EVENTS LIST ****");
console.log(result.items);
res.apiSend(response);
});
});
});
});
});
});
});
Note that I am logging the response after every single Quickblox request. So the log after QB.messages.events.create() is the following:
**** MESSAGE EVENT CREATE ****
{ event:
{ active: true,
application_id: 18113,
created_at: '2015-01-13T10:32:45Z',
date: null,
end_date: null,
event_type: 'one_shot',
id: 1809320,
message: 'data.message=SStsb3ZlK00lMjZNJTI3cyUyMStFc3BlY2lhbGx5K3JlZCtvbmUlMjE=',
name: null,
occured_count: 0,
period: null,
updated_at: '2015-01-13T10:32:45Z',
user_id: 2185263,
notification_channel: { name: 'gcm' },
subscribers_selector:
{ environment: 'production',
tags_query: null,
user_ids: [Object] } } }
and when i list the events using QB.messages.events.list() i get the following response:
{ current_page: 1,
per_page: 10,
total_entries: 19,
items:
[ { event: [Object] },
{ event: [Object] },
{ event: [Object] },
{ event: [Object] },
{ event: [Object] },
{ event: [Object] },
{ event: [Object] },
{ event: [Object] },
{ event: [Object] },
{ event: [Object] } ] }
Therefore it says that there are 19 entries in the messages queue and everything seems to be OK.
However when I login to my Quickblox account and check the messages queue it is always empty and therefore no messages are scheduled to be sent. Note as well that subscriptions show the users subscribed to push notification services such as 'gcm' and 'apns'. Can anyone help me find out why is this happening please?

You need encode the message to base64.
You need to make sure your mobile app would know to understand the decoded message.
For example,
sending push notification to android qb_user_id: 20290
(and from me - my qb_user_id: 12121):
function b64EncodeUnicode(str) {
return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) {
return String.fromCharCode('0x' + p1);
}));
}
function send_push() {
var params = {
notification_type: 'push',
push_type: 'gcm',
user: {ids: [20290]},
environment: "production",
message: b64EncodeUnicode('{"message":"HELLO WORLD","user_id":12121,"device_type":"WEB","message_qb_id":"563a55a44cedaa83885724cf","message_type":"Text","send_status":"BeingProcessed","send_time":1446663588607}')
};
QB.messages.events.create(params, function(err, response) {
if (err) {
console.log("QB.messages.events.create::error:" +err);
} else {
console.log("QB.messages.events.create::response:" + response);
}
});
}
In this example, the mobile app is looking for a message in this format:
{"message","user_id","device_type","message_qb_id","message_type","send_status","send_time"}

Related

Using Multiple FindOne in Mongodb

I am trying to extend the amount of fields that our API is returning. Right now the API is returning the student info by using find, as well as adding some information of the projects by getting the student info and using findOne to get the info about the project that the student is currently registered to.
I am trying to add some information about the course by using the same logic that I used to get the project information.
So I used the same findOne function that I was using for Projects and my logic is the following.
I created a variable where I can save the courseID and then I will put the contents of that variable in the temp object that sending in a json file.
If I comment out the what I added, the code works perfectly and it returns all the students that I require. However, when I make the additional findOne to get information about the course, it stops returning anything but "{}"
I am going to put a comment on the lines of code that I added, to make it easier to find.
Any sort of help will be highly appreciated!
User.find({
isEnrolled: true,
course: {
$ne: null
}
},
'email pantherID firstName lastName project course',
function(err, users) {
console.log("err, users", err, users);
if (err) {
return res.send(err);
} else if (users) {
var userPromises = [];
users.map(function(user) {
userPromises.push(new Promise(function(resolve, reject) {
///////// Added Code START///////
var courseID;
Course.findOne({
fullName: user.course
}, function(err, course) {
console.log("err, course", err, course);
if (err) {
reject('')
}
courseID = course ? course._id : null
//console.log(tempObj)
resolve(tempObj)
}),
///// ADDED CODE END //////
Project.findOne({
title: user.project
}, function(err, proj) {
console.log("err, proj", err, proj);
if (err) {
reject('')
}
//Course ID, Semester, Semester ID
//map to custom object for MJ
var tempObj = {
email: user.email,
id: user.pantherID,
firstName: user.firstName,
lastName: user.lastName,
middle: null,
valid: true,
projectTitle: user.project,
projectId: proj ? proj._id : null,
course: user.course,
courseId: courseID
}
//console.log(tempObj)
resolve(tempObj)
})
}))
})
//async wait and set
Promise.all(userPromises).then(function(results) {
res.json(results)
}).catch(function(err) {
res.send(err)
})
}
})
using promise could be bit tedious, try using async, this is how i would have done it.
// Make sure User, Course & Project models are required.
const async = require('async');
let getUsers = (cb) => {
Users.find({
isEnrolled: true,
course: {
$ne: null
}
}, 'email pantherID firstName lastName project course', (err, users) => {
if (!err) {
cb(null, users);
} else {
cb(err);
}
});
};
let findCourse = (users, cb) => {
async.each(users, (user, ecb) => {
Project.findOne({title: user.project})
.exec((err, project) => {
if (!err) {
users[users.indexOf(user)].projectId = project._id;
ecb();
} else {
ecb(err);
}
});
}, (err) => {
if (!err) {
cb(null, users);
} else {
cb(err);
}
});
};
let findProject = (users, cb) => {
async.each(users, (user, ecb) => {
Course.findOne({fullName: user.course})
.exec((err, course) => {
if (!err) {
users[users.indexOf(user)].courseId = course._id;
ecb();
} else {
ecb(err);
}
});
}, (err) => {
if (!err) {
cb(null, users);
} else {
cb(err);
}
});
};
// This part of the code belongs at the route scope
async.waterfall([
getUsers,
findCourse,
findProject
], (err, result) => {
if (!err) {
res.send(result);
} else {
return res.send(err);
}
});
Hope this gives better insight on how you could go about with multiple IO transactions on the same request.

Using async.js for deep populating sails.js

I have a big issue with my function in sails.js (v12). I'm trying to get all userDetail using async (v2.3) for deep populating my user info:
UserController.js:
userDetail: function (req, res) {
var currentUserID = authToken.getUserIDFromToken(req);
async.auto({
//Find the User
user: function (cb) {
User
.findOne({ id: req.params.id })
.populate('userFollowing')
.populate('userFollower')
.populate('trips', { sort: 'createdAt DESC' })
.exec(function (err, foundedUser) {
if (err) {
return res.negotiate(err);
}
if (!foundedUser) {
return res.badRequest();
}
// console.log('foundedUser :', foundedUser);
cb(null, foundedUser);
});
},
//Find me
me: function (cb) {
User
.findOne({ id: currentUserID })
.populate('myLikedTrips')
.populate('userFollowing')
.exec(function (err, user) {
var likedTripIDs = _.pluck(user.myLikedTrips, 'id');
var followingUserIDs = _.pluck(user.userFollowing, 'id');
cb(null, { likedTripIDs, followingUserIDs });
});
},
populatedTrip: ['user', function (results, cb) {
Trip.find({ id: _.pluck(results.user.trips, 'id') })
.populate('comments')
.populate('likes')
.exec(function (err, tripsResults) {
if (err) {
return res.negotiate(err);
}
if (!tripsResults) {
return res.badRequest();
}
cb(null, _.indexBy(tripsResults, 'id'));
});
}],
isLiked: ['populatedTrip', 'me', 'user', function (results, cb) {
var me = results.me;
async.map(results.user.trips, function (trip, callback) {
trip = results.populatedTrip[trip.id];
if (_.contains(me.likedTripIDs, trip.id)) {
trip.hasLiked = true;
} else {
trip.hasLiked = false;
}
callback(null, trip);
}, function (err, isLikedTrip) {
if (err) {
return res.negotiate(err);
}
cb(null, isLikedTrip);
});
}]
},
function finish(err, data) {
if (err) {
console.log('err = ', err);
return res.serverError(err);
}
var userFinal = data.user;
//userFinal.trips = data.isLiked;
userFinal.trips = "test";
return res.json(userFinal);
}
);
},
I tried almost everthing to get this fix but nothing is working...
I am able to get my array of trips(data.isLiked) but I couldn't get my userFInal trips.
I try to set string value on the userFinal.trips:
JSON response
{
"trips": [], // <-- my pb is here !!
"userFollower": [
{
"user": "5777fce1eeef472a1d69bafb",
"follower": "57e44a8997974abc646b29ca",
"id": "57efa5cf605b94666aca0f11"
}
],
"userFollowing": [
{
"user": "57e44a8997974abc646b29ca",
"follower": "5777fce1eeef472a1d69bafb",
"id": "5882099b9c0c9543706d74f6"
}
],
"email": "test2#test.com",
"userName": "dany",
"isPrivate": false,
"bio": "Hello",
"id": "5777fce1eeef472a1d69bafb"
}
Question
How should I do to get my array of trips (isLiked) paste to my user trips array?
Why my results is not what I'm expecting to have?
Thank you for your answers.
Use .toJSON() before overwriting any association in model.
Otherwise default toJSON implementation overrides any changes made to model associated data.
var userFinal = data.user.toJSON(); // Use of toJSON
userFinal.trips = data.isLiked;
return res.json(userFinal);
On another note, use JS .map or _.map in place of async.map as there is not asynchronous operation in inside function. Otherwise you may face RangeError: Maximum call stack size exceeded issue.
Also, it might be better to return any response from final callback only. (Remove res.negotiate, res.badRequest from async.auto's first argument). It allows to make response method terminal

Telegram bot and CouchDB insert new user to DB

How Can I insert New Telegram Bot user to CouchDB?
I inserted a Sample Data jack johnsin db and was ok, But I Don't Know How Should I Take Telegram users Username and Put That in Db.
This is My Code:
import 'babel-polyfill';
import './env';
import TelegramBot from 'node-telegram-bot-api';
const bot = new TelegramBot(process.env.BOT_TOKEN, {polling: true});
/////////////////////////////////// Sample Data
var server = require('couch-db')('http://localhost:5984');
var db = server.database('users');
db.destroy(function(err) {
// create a new database
db.create(function(err) {
// insert a document with id 'jack johns'
db.insert({ _id: 'jack johns', name: 'jack' }, function(err, body) {
if (err) {
console.log('insertion failed ', err.message);
return;
}
console.log(body);
// body will like following:
// { ok: true,
// id: 'jack johns',
// rev: '1-610953b93b8bf1bae12427e2de181307' }
});
});
});
//////////////////////////////
bot.onText(/^[\/!#]start$/, msg => {
const opts = {
reply_to_message_id: msg.message_id,
reply_markup: JSON.stringify({
keyboard: [['Store username']],
resize_keyboard:true,
one_time_keyboard: true
})
};
bot.sendMessage(msg.chat.id, 'You Are Exist in DB', opts);
});
Solved By Myselfe,
For User ID You Can Use User_ID: msg.from.id
This is My Code:
bot.onText(/^[\/!#]start$/, msg => {
db.insert({ _id: msg.from.username }, function(err, body) {
if (err) {
console.log('insertion failed ', err.message);
return;
}
console.log(body);
});
const opts = {
reply_to_message_id: msg.message_id,
reply_markup: JSON.stringify({
keyboard: [['Store username']],
resize_keyboard:true,
one_time_keyboard: true
})
};
bot.sendMessage(msg.chat.id, 'You Are Exist in DB', opts);
});

What's the proper use of Bluebird or Q Promises in this situation?

I'm using a node machines package (machinepack-wepay) to communicate with Wepay and I'd like to be able to chain it properly.
Take the following example where we will be registering a user, creating an account and sending the email confirm. Along the way we will be storing some of the result info in mongo.
var WePay = require('machinepack-wepay');
// ... extraneous code removed for brevity
var member = req.session.member;
if( !_.has( member, 'wepay' ) ) {
WePay.userRegister({
clientId: config.wepay_client_id,
clientSecret: config.wepay_client_secret,
email: member.email,
scope: 'manage_accounts,collect_payments,view_user,send_money',
firstName: member.firstName,
lastName: member.lastName,
originalIp: req.headers['x-forwarded-for'],
originalDevice: req.headers['user-agent'],
tosAcceptanceTime: Math.floor(new Date() / 1000),
callbackUri: config.site_url + '/wepay/user?member=' + member.id,
useProduction: isProd
}).exec({
error: function (err) {
yourErrorHandler(err);
},
success: function (result) {
Member.update({id: member.id}, {wepay: result}, function (err, updated) {
if (err) {
yourErrorHandler(err);
}
else {
member = updated[0];
WePay.accountCreate({
accessToken: member.wepay.access_token,
name: 'Account Name',
description: 'My new account'
}).exec({
error: function (err) {
yourErrorHandler(err);
},
success: function (result) {
Member.update({id: member.id}, {wepay_account: result}, function (err, updated) {
if (err) {
sails.log.error("error updating page:", err);
}
req.session.member = updated[0];
// PATTERN CONTINUES HERE
});
}
});
}
});
}
});
}
else{
WePay.userDetails({
accessToken: member.wepay.access_token,
useProduction: false,
}).exec({
error: function (err){
yourErrorHandler(err);
},
success: function (result){
_.extend( member.wepay, result );
Member.update({id: req.session.current_page.id}, member, function (err, updated) {
if (err) {
sails.log.error("error updating page:", err);
}
req.session.member = updated[0];
// PATTERN CONTINUES HERE
});
},
});
}

How to confirm if update succeeds using mongoose and bluebird promise

I'm using bluebird and mongoose for a node page.
I want to check if the update is successful before sending data back to clients via socket.js.Here's the part of the code that I can't figure out:
.then(function(a) {
var g = collection3.update({
_id: a.one[0]._id
}, {
$set: {
avg: a.one[0].avg
}
}).function(err, d) {
if (!err) {
return 1; // Here's the problem
}
}) return {
updated: g,
info: a
};
}).then(function(c) {
console.log(c.updated); // I can't get the `1` value
if (c == 1) {
io.sockets.in('index|1').emit("estimate", c.three);
}
})
Does mongoose return a success message after update? I can't return 1 from the update query and pass it to the next then function, instead, I'm getting this object:
{ _mongooseOptions: {},
mongooseCollection:
{ collection:
{ db: [Object],
collectionName: 'table',
internalHint: null,
opts: {},
slaveOk: false,
serializeFunctions: false,
raw: false,
pkFactory: [Object],
serverCapabilities: undefined },
opts: { bufferCommands: true, capped: false },
name: 'table',
conn:....
Here's the full code:
socket.on("input",function(d){
Promise.props({
one: collection2.aggregate([
{
$match:{post_id:mongoose.Types.ObjectId(d.id)}
},
{
$group:{
_id:"$post_id",
avg:{$avg:"$rating"}
}
}
]).exec();
}).then(function(a){
var g = collection3.update({_id:a.one[0]._id},{$set:{avg:a.one[0].avg}}).function(err,d){
if(!err){
return 1; // Here's the problem
}
})
return {updated:g,info:a};
}).then(function(c){
console.log(c.updated); // I can't get the `1` value
if(c.updated == 1){
io.sockets.in('index|1').emit("estimate",c.three);
}
}).catch(function (error) {
console.log(error);
})
I'm assuming you're using Mongoose here, update() is an asynchronous function, your code is written in a synchronous style.
Try:
socket.on("input",function(d){
Promise.props({
one: collection2.aggregate([
{
$match:{post_id:mongoose.Types.ObjectId(d.id)}
},
{
$group:{
_id:"$post_id",
avg:{$avg:"$rating"}
}
}
]).exec()
}).then(function(a){
return collection3.update({_id:a.one[0]._id},{$set:{avg:a.one[0].avg}})
.then(function(updatedDoc){
// if update is successful, this function will execute
}, function(err){
// if an error occured, this function will execute
})
}).catch(function (error) {
console.log(error);
})
Mongoose docs says
Mongoose async operations, like .save() and queries, return
Promises/A+ conformant promises. This means that you can do things
like MyModel.findOne({}).then() and yield MyModel.findOne({}).exec()
(if you're using co).
Also
Mongoose Update returns the updated document.
So this should look something like this.
function runBarryRun(d) {
Promise.props({
one: aggregateCollection2(d)
})
.then(updateCollection3)
.then(updatedDoc => {
// if update is successful, do some magic here
io.sockets.in('index|1').emit("estimate", updatedDoc.something);
}, err => {
// if update is unsuccessful, find out why, throw an error maybe
}).catch(function(error) {
// do something here
console.log(error);
});
}
function aggregateCollection2(d) {
return collection2.aggregate([{
$match: { post_id: mongoose.Types.ObjectId(d.id) }
}, {
$group: {
_id: "$post_id",
avg: { $avg: "$rating" }
}
}]).exec();
}
function updateCollection3(a) {
return collection3.update({ _id: a.one[0]._id }, { $set: { avg: a.one[0].avg } }).exec();
}
socket.on("input", runBarryRun);

Categories

Resources