Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add user to topic #211

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ var Constants = {

'GCM_SEND_URI' : 'https://gcm-http.googleapis.com:443/gcm/send',

'GCM_IID_ENDPOINT' : 'https://iid.googleapis.com',

'GCM_INFO_ENDPATH' : '/iid/info/',

'GCM_SUBSCRIPTION_ENDPATH_1' : '/iid/v1/',

'GCM_SUBSCRIPTION_ENDPATH_2' : '/rel/topics/',

'GCM_IID_SUBSCRIBE_URI' : 'https://iid.googleapis.com/iid/v1:batchAdd',

'GCM_IID_UNSUBSCRIBE_URI' : 'https://iid.googleapis.com/iid/v1:batchAdd',

'ERROR_QUOTA_EXCEEDED' : 'QuotaExceeded',

'ERROR_DEVICE_QUOTA_EXCEEDED' : 'DeviceQuotaExceeded',
Expand Down
195 changes: 195 additions & 0 deletions lib/instance-id.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
var Constants = require('./constants');
var req = require('request');
var Sender = require('./sender');
var debug = require('debug')('node-gcm');

//Set the name Instance Id from the google API docs
function InstanceId(key, options) {
if (!(this instanceof InstanceId)) {
return new InstanceId(key, options);
}

this.key = key;
// Will be useful when implementing retries
this.options = options;
}

// This function will add a user or a list of users to a topic.
InstanceId.prototype.addToTopicNoRetry = function(topic, subscriber, callback) {
console.log(' addToTopicNoRetry of instance id inside node-gcm');
if(!callback) {
callback = function() {};
}

if(typeof topic != "string" || topic == "" ) {
debug('Incorrect topic provided!');
return process.nextTick(callback.bind(this, 'Incorrect topic provided!', null));
}

var singleSubscriber;
var subscriberList;

//TODO: create a separate function for this piece of code & use in sender.js as well
if(typeof subscriber == "string") {
console.log(' subscriber passed is a string. ');
singleSubscriber = subscriber;
}
else if (!Array.isArray(subscriber) && typeof subscriber == "object") {
console.log('subscriber is not a list but an object. ');
var o = Sender.extractRecipient(subscriber);
var theRecipient;

if (o.err) {
return callback(o.err);
}
else {
theRecipient = o.recipient;
}

if (Array.isArray(theRecipient)) {
subscriberList = theRecipient;
}
else {
singleSubscriber = theRecipient;
}
}
else {
console.log('subscriber is a list');
if (Array.isArray(subscriber) && subscriber.length == 1) {
singleSubscriber = subscriber[0];
}
else {
subscriberList = subscriber;
}
}

if(singleSubscriber != null){
console.log('subscriber not null ,initiating a post request to the IID endpoint.');

var post_options = {
method: 'POST',
headers: {
'Authorization': 'key=' + this.key
},
uri: Constants.GCM_IID_ENDPOINT+Constants.GCM_SUBSCRIPTION_ENDPATH_1+singleSubscriber+Constants.GCM_SUBSCRIPTION_ENDPATH_2+topic
};
var resBodyJSON;
var post_req = req(post_options, function (err, res, resBodyJSON) {
if (err) {
return callback(err, null);
}

if (!res) {
return callback('response is null', null);
}

if (res.statusCode >= 500) {
debug('GCM service is unavailable (500)');
return callback(res.statusCode, null);
} else if (res.statusCode === 401) {
debug('Unauthorized (401). Check that your API token is correct.');
return callback(res.statusCode, null);
} else if (res.statusCode !== 200) {
debug('Invalid request (' + res.statusCode + '): ' + resBodyJSON);
return callback(res.statusCode, null);
}

callback(null, resBodyJSON);
});


}
else if (subscriberList != null){
var body = {};
// Gcm documentation is currently incorrect, http://stackoverflow.com/questions/35177152/topic-name-format-is-invalid-when-trying-to-subscribe-to-gcm-topic
body.to='/topics/'+topic;
body.registration_tokens=subscriberList;

var post_options = {
method: 'POST',
headers: {
'Authorization': 'key=' + this.key
},
uri: Constants.GCM_IID_SUBSCRIBE_URI,
json: body
};

var post_req = req(post_options, function (err, res, resBodyJSON) {
if (err) {
return callback(err, null);
}

if (!res) {
return callback('response is null', null);
}

if (res.statusCode >= 500) {
debug('GCM service is unavailable (500)');
return callback(res.statusCode, null);
} else if (res.statusCode === 401) {
debug('Unauthorized (401). Check that your API token is correct.');
return callback(res.statusCode, null);
} else if (res.statusCode !== 200) {
debug('Invalid request (' + res.statusCode + '): ' + resBodyJSON);
return callback(res.statusCode, null);
}

callback(null, resBodyJSON);
});

}
else{
debug('No subscribers provided!');
return process.nextTick(callback.bind(this, 'No subscribers provided!', null));
}


};

//TODO: implement batch unsubscription
//TODO: implement a funciton which returs list of subscribed groups using info and setting details as true.

InstanceId.prototype.info = function(token, callback) {
if(typeof token != "string") {
debug('Incorrect Instance ID token passed!');
return process.nextTick(callback.bind(this, 'Incorrect Instance ID token passed!', null));
}

//TODO: letting users pass details=true and pass on in the url
var post_options = {
method: 'POST',
headers: {
'Authorization': 'key=' + this.key
},
uri: Constants.GCM_IID_ENDPOINT+Constants.GCM_INFO_ENDPATH+token
};

//TODO: create in a separate function, as this part of code is used twice in this file & once in sender.js
var post_req = req(post_options, function (err, res, resBodyJSON) {
if (err) {
return callback(err, null);
}

if (!res) {
return callback('response is null', null);
}

if (res.statusCode >= 500) {
debug('GCM service is unavailable (500)');
return callback(res.statusCode, null);
} else if (res.statusCode === 401) {
debug('Unauthorized (401). Check that your API token is correct.');
return callback(res.statusCode, null);
} else if (res.statusCode !== 200) {
debug('Invalid request (' + res.statusCode + '): ' + resBodyJSON);
return callback(res.statusCode, null);
}

callback(null, resBodyJSON);
});



}

module.exports = InstanceId;
1 change: 1 addition & 0 deletions lib/node-gcm.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ exports.Message = require('./message');
exports.Result = require('./result');
exports.MulitcastResult = require('./multicastresult');
exports.Sender = require('./sender');
exports.InstanceId = require('./instance-id');
62 changes: 62 additions & 0 deletions test/unit/instanceIdSpec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"use strict";

var chai = require('chai'),
expect = chai.expect,
sinon = require('sinon'),
proxyquire = require('proxyquire'),
instanceIdPath = '../../lib/instance-id',
Constants = require('../../lib/constants');

describe('UNIT InstanceId', function () {
// Use object to set arguments passed into callback
var args = {};
var requestStub = function (options, callback) {
args.options = options;
return callback( args.err, args.res, args.resBody );
};

var InstanceId = proxyquire(instanceIdPath, { 'request': requestStub });

describe('constructor', function () {
var InstanceId = require(instanceIdPath);

it('should call new on constructor if user does not', function () {
var instanceId = InstanceId();
expect(instanceId).to.not.be.undefined;
expect(instanceId).to.be.instanceOf(InstanceId);
});

it('should create a InstanceId with key and options passed in', function () {
var options = {
proxy: 'http://myproxy.com',
maxSockets: 100,
timeout: 100
};
var key = 'myAPIKey',
instanceId = new InstanceId(key, options);
expect(instanceId).to.be.instanceOf(InstanceId);
expect(instanceId.key).to.equal(key);
expect(instanceId.options).to.deep.equal(options);
});

it.skip('should do something if not passed a valid key');
});


describe('addToTopicNoRetry()', function () {
// Set arguments passed in request proxy
function setArgs(err, res, resBody) {
args = {
err: err,
res: res,
resBody: resBody
};
};





});

});