UNPKG

jpush-sdk

Version:

JPush's officially supported Node.js client library.

356 lines (316 loc) 11.6 kB
var debug = require('debug')('jpush') var pkg = require('../../package') var JError = require('./JPushError') var Request = require('request').defaults({ headers: { 'User-Agent': 'JPush-API-NodeJS-Client ' + pkg.version, 'Connection': 'Keep-Alive', 'Charset': 'UTF-8', 'Content-Type': 'application/json' } }) var JModel = require('./PushPayload') var PUSH_API_URL = 'https://api.jpush.cn/v3/push' var REPORT_API_URL = 'https://report.jpush.cn/v3' var SCHEDULE_API_URL = 'https://api.jpush.cn/v3/schedules' // 定时任务 var REPORT_RECEIVED = '/received' var REPORT_USER = '/users' var REPORT_MESSAGE = '/messages' var HOST_NAME_SSL = 'https://device.jpush.cn' var DEVICE_PATH = '/v3/devices' var TAG_PATH = '/v3/tags' var ALIAS_PATH = '/v3/aliases' var VALIDATE = '/validate' var DEFAULT_MAX_RETRY_TIMES = 3 var READ_TIMEOUT = 30 * 1000 // Pattern var PUSH_PATTERNS = /^[a-zA-Z0-9]{24}/ var MSG_IDS_PATTERNS = /[^\d,]/ exports.buildClient = function (appKey, masterSecret, retryTimes, isDebug, readTimeOut, proxy) { if (arguments.length === 1 && typeof arguments[0] === 'object') { var options = arguments[0] return new JPushClient(options.appKey, options.masterSecret, options.retryTimes, options.isDebug, options.readTimeOut, options.proxy ) } else { return new JPushClient(appKey, masterSecret, retryTimes, isDebug, readTimeOut, proxy) } } function JPushClient (appKey, masterSecret, retryTimes, isDebug, readTimeOut, proxy) { if (!appKey || !masterSecret) { throw JError.InvalidArgumentError('appKey and masterSecret are both required.') } if (typeof appKey !== 'string' || typeof masterSecret !== 'string' || !PUSH_PATTERNS.test(appKey) || !PUSH_PATTERNS.test(masterSecret)) { throw new JError.InvalidArgumentError('appKey and masterSecret format is incorrect. ' + 'They should be 24 size, and be composed with alphabet and numbers. ' + 'Please confirm that they are coming from JPush Web Portal.') } this.appkey = appKey this.masterSecret = masterSecret if (retryTimes) { if (typeof retryTimes !== 'number') { throw JError.InvalidArgumentError('Invalid retryTimes.') } this.retryTimes = retryTimes } else { this.retryTimes = DEFAULT_MAX_RETRY_TIMES } this.isDebug = isDebug ? isDebug : true this.readTimeOut = readTimeOut ? readTimeOut : READ_TIMEOUT this.proxy = proxy ? proxy : null } /** * create a push payload * @returns {exports.PushPayload} */ function push () { return new JModel.PushPayload(this) } function sendPush (payload, callback) { return _request(this, PUSH_API_URL, payload, 'POST', callback) } function getReportReceiveds (msgIds, callback) { if (MSG_IDS_PATTERNS.test(msgIds)) { throw new JError.InvalidArgumentError( 'Invalid msg_ids, msg_ids should be composed with alphabet and comma.') } var url = REPORT_API_URL + REPORT_RECEIVED + '?msg_ids=' + msgIds return _request(this, url, null, 'GET', callback) } function getReportMessages (msgIds, callback) { if (MSG_IDS_PATTERNS.test(msgIds)) { throw new JError.InvalidArgumentError( 'Invalid msg_ids, msg_ids should be composed with alphabet and comma.') } var url = REPORT_API_URL + REPORT_MESSAGE + '?msg_ids=' + msgIds return _request(this, url, null, 'GET', callback) } function getReportUsers (timeUnit, start, duration, callback) { var url = REPORT_API_URL + REPORT_USER + '?time_unit=' + timeUnit + '&start=' + start + '&duration=' + duration return _request(this, url, null, 'GET', callback) } /** * device api * * @param registrationId */ function getDeviceTagAlias (registrationId, callback) { var url = HOST_NAME_SSL + DEVICE_PATH + '/' + registrationId return _request(this, url, null, 'GET', callback) } // 结合短信业务使用,需要先调用该方法将用户的手机号码与设备的 registration id 匹配。 function setMobile (registrationId, mobileNumber, callback) { var json = {} json['mobile'] = mobileNumber var url = HOST_NAME_SSL + DEVICE_PATH + '/' + registrationId return _request(this, url, JSON.stringify(json), 'POST', callback) } function updateDeviceTagAlias (registrationId, alias, clearTag, tagsToAdd, tagsToRemove, callback) { var url = HOST_NAME_SSL + DEVICE_PATH + '/' + registrationId if (tagsToAdd instanceof Array && tagsToRemove instanceof Array) { var json = {} var tags = {} if (alias != null) { json['alias'] = alias } if (clearTag) { json['tags'] = '' } else { if (tagsToAdd != null && tagsToAdd.length > 0) { tags['add'] = tagsToAdd } if (tagsToRemove != null && tagsToRemove.length > 0) { tags['remove'] = tagsToRemove } json['tags'] = tags debug(json) } } else { throw new JError.InvalidArgumentError('tagsToAdd or tagsToRemove type should be array') } return _request(this, url, JSON.stringify(json), 'POST', callback) } function getTagList (callback) { var url = HOST_NAME_SSL + TAG_PATH return _request(this, url, null, 'GET', callback) } function isDeviceInTag (theTag, registrationID, callback) { var url = HOST_NAME_SSL + TAG_PATH + '/' + theTag + '/registration_ids/' + registrationID return _request(this, url, null, 'GET', callback) } function addRemoveDevicesFromTag (theTag, toAddUsers, toRemoveUsers, callback) { var url = HOST_NAME_SSL + TAG_PATH + '/' + theTag var registrationIds = {} if (toAddUsers != null && toAddUsers.length > 0) { registrationIds['add'] = toAddUsers } if (toRemoveUsers != null && toRemoveUsers.length > 0) { registrationIds['remove'] = toRemoveUsers } var json = {} json['registration_ids'] = registrationIds debug(json['registration_ids']) return _request(this, url, JSON.stringify(json), 'POST', callback) } function deleteTag (theTag, platform, callback) { var url = HOST_NAME_SSL + TAG_PATH + '/' + theTag if (platform != null) { url += ('/?platform=' + platform) } return _request(this, url, null, 'delete', callback) } function getAliasDeviceList (alias, platform, callback) { var url = HOST_NAME_SSL + ALIAS_PATH + '/' + alias if (platform != null) { url += '/?platform=' + platform } return _request(this, url, null, 'GET', callback) } function deleteAlias (alias, platform, callback) { var url = HOST_NAME_SSL + ALIAS_PATH + '/' + alias if (platform != null) { url += '/?platform=' + platform } return _request(this, url, null, 'delete', callback) } function validate (payload, callback) { return _request(this, PUSH_API_URL + VALIDATE, payload, 'POST', callback) } // 定时任务 start function setSchedule (payload, callback) { return _request(this, SCHEDULE_API_URL, payload, 'POST', callback) } function updateSchedule (scheduleId, payload, callback) { var url = SCHEDULE_API_URL + '/' + scheduleId return _request(this, url, payload, 'PUT', callback) } // 获取有效的定时任务列表。 function getScheduleList (page, callback) { if (typeof page !== 'number') { throw new JError.InvalidArgumentError('Invalid argument, it can only be set to the Number.') } var url = SCHEDULE_API_URL + '?page=' + page return _request(this, url, null, 'GET', callback) } // 获取指定的定时任务。 function getSchedule (scheduleId, callback) { if (typeof scheduleId !== 'string') { throw new JError.InvalidArgumentError('Invalid argument, it can only be set to the String.') } var url = SCHEDULE_API_URL + '/' + scheduleId return _request(this, url, null, 'GET', callback) } // 删除指定的定时任务。 function delSchedule (scheduleId, callback) { if (typeof scheduleId !== 'string') { throw new JError.InvalidArgumentError('Invalid argument, it can only be set to the String.') } var url = SCHEDULE_API_URL + '/' + scheduleId return _request(this, url, null, 'DELETE', callback) } // 定时任务 end // Proxy start // Proxy end function _request (client, url, body, method, callback, times) { if (times) { times = 1 } if (client.isDebug) { debug('Push URL :' + url) if (body) { debug('Body :' + body) } // debug("Auth :" + JSON.stringify(auth)) debug('Method :' + method) debug('Times/MaxTryTimes : ' + times + '/' + client.maxTryTimes) } var _callback = function (err, res, body) { if (err) { if (err.code === 'ETIMEDOUT' && err.syscall !== 'connect') { // response timeout return callback(new JError.APIConnectionError( 'Response timeout. Your request to the server may have already received, please check whether or not to push', true)) } else if (err.code === 'ENOTFOUND') { // unknown host return callback(new JError.APIConnectionError('Known host : ' + url)) } // other connection error if (times < client.maxTryTimes) { return _request(client, url, body, method, callback, times + 1) } else { return callback(new JError.APIConnectionError('Connect timeout. Please retry later.')) } } if (res.statusCode === 200) { if (body.length !== 0) { if (client.isDebug) { debug('Success, response : ' + body) } try { callback(null, JSON.parse(body)) } catch (e) { callback(e) } } else { if (client.isDebug) { debug('Success, response : ' + body) } callback(null, 200) } } else { if (client.isDebug) { debug('Fail, HttpStatusCode: ' + res.statusCode + ' result: ' + body.toString()) } callback(new JError.APIRequestError(res.statusCode, body)) } } Request[method.toLowerCase()]({ url: url, body: body, auth: { user: client.appkey, pass: client.masterSecret }, timeout: client.readTimeOut, proxy: client.proxy }, _callback) } JPushClient.prototype.sendPush = sendPush JPushClient.prototype.getReportReceiveds = getReportReceiveds JPushClient.prototype.push = push JPushClient.prototype.setMobile = setMobile JPushClient.prototype.getDeviceTagAlias = getDeviceTagAlias JPushClient.prototype.updateDeviceTagAlias = updateDeviceTagAlias JPushClient.prototype.getTagList = getTagList JPushClient.prototype.isDeviceInTag = isDeviceInTag JPushClient.prototype.addRemoveDevicesFromTag = addRemoveDevicesFromTag JPushClient.prototype.deleteTag = deleteTag JPushClient.prototype.getAliasDeviceList = getAliasDeviceList JPushClient.prototype.deleteAlias = deleteAlias JPushClient.prototype.validate = validate JPushClient.prototype.getReportMessages = getReportMessages JPushClient.prototype.getReportUsers = getReportUsers JPushClient.prototype.getScheduleList = getScheduleList JPushClient.prototype.getSchedule = getSchedule JPushClient.prototype.delSchedule = delSchedule JPushClient.prototype.setSchedule = setSchedule JPushClient.prototype.updateSchedule = updateSchedule // exports constants and methods exports.ALL = JModel.ALL exports.tag = JModel.tag exports.tag_and = JModel.tag_and exports.alias = JModel.alias exports.registration_id = JModel.registration_id exports.ios = JModel.ios exports.android = JModel.android exports.winphone = JModel.winphone // error exports.APIConnectionError = JError.APIConnectionError exports.APIRequestError = JError.APIRequestError exports.InvalidArgumentError = JError.InvalidArgumentError