module.exports = Account var debug = require('debug')('snapchat:account') var Promise = require('bluebird') var constants = require('../lib/constants') var SKBlob = require('../models/blob') /** * Snapchat wrapper for account-related API calls. * * @class * @param {Object} opts */ function Account (client, opts) { var self = this if (!(self instanceof Account)) return new Account(client, opts) if (!opts) opts = {} self.client = client } /** * Updates the number of best friends to display. * * @param {number} number A number from 3 to 7. Defaults to 3 and will max out at 7. * @param {function} cb */ Account.prototype.updateBestFriendsCount = function (number, cb) { var self = this return new Promise(function (resolve, reject) { debug('Account.updateBestFriendsCount (%d)', number) if (number < 3) number = 3 if (number > 7) number = 7 self.client.post(constants.endpoints.account.setBestsCount, { 'num_best_friends': number | 0, 'username': self.client.username }, function (err, result) { if (err) { return reject(err) } else if (result) { self.client.session.bestFriendUsernames = result['best_friends'] return resolve() } return reject(new Error('Snapchat.Account.updateBestFriendsCount parse error')) }) }).nodeify(cb) } /** * Updates who can send you snaps. * * @param privacy SnapPrivacy.Friends or SnapPrivacy.Everyone. Defaults to SnapPrivacy.Friends. * @param {function} cb */ Account.prototype.updateSnapPrivacy = function (privacy, cb) { var self = this debug('Account.updateSnapPrivacy (%d)', privacy) privacy = Math.min(privacy, 1) | 0 return self.client.post(constants.endpoints.account.settings, { 'action': 'updatePrivacy', 'privacySetting': privacy, 'username': self.client.username }, cb) } /** * Updates who can see your stories. \e friends is only necessary when using StoryPrivacy.Custom. * * @param {number} privacy StoryPrivacy.Everyone, StoryPrivacy.Friends, StoryPrivacy.Custom. * @param {Array<string>=} friends Optional list of strings of usernames to hide your stories from. Used only when privacy is StoryPrivacy.Custom. * @param {function} cb */ Account.prototype.updateStoryPrivacy = function (privacy, friends, cb) { var self = this debug('Account.updateStoryPrivacy (%d)', privacy) if (typeof friends === 'function') { cb = friends friends = null } var params = { 'action': 'updateStoryPrivacy', 'privacySetting': constants.stringFromStoryPrivacy(privacy | 0), 'username': self.client.username } if (friends) { params.storyFriendsToBlock = friends } return self.client.post(constants.endpoints.account.settings, params, cb) } /** * Updates your account's email address. * * @param {string} address Your new email address. * @param {function} cb */ Account.prototype.updateEmail = function (address, cb) { var self = this debug('Account.updateEmail (%s)', address) return self.client.post(constants.endpoints.account.settings, { 'action': 'updateEmail', 'email': address, 'username': self.client.username }, cb) } /** * Updates whether your account can be found with your phone number. * * @param {boolean} searchable The new value for this preference. * @param {function} cb */ Account.prototype.updateSearchableByNumber = function (searchable, cb) { var self = this debug('Account.updateSearchableByNumber (%d)', searchable) return self.client.post(constants.endpoints.account.settings, { 'action': 'updateSearchableByPhoneNumber', 'searchable': !!searchable, 'username': self.client.username }, cb) } /** * Updates your 'notification sounds' preference. * * @param {boolean} enableSound The new value for this preference. * @param {function} cb */ Account.prototype.updateNotificationSoundSetting = function (enableSound, cb) { var self = this debug('Account.updateNotificationSoundSetting (%d)', enableSound) return self.client.post(constants.endpoints.account.settings, { 'action': 'updateNotificationSoundSetting', 'notificationSoundSetting': enableSound ? 'ON' : 'OFF', 'username': self.client.username }, cb) } /** * Updates your display name. * * Your 'display name' is what your contact name defaults to when someone new adds you, not your username. * @param {string} displayName Your new display name. * @param {function} cb */ Account.prototype.updateDisplayName = function (displayName, cb) { var self = this debug('Account.updateDisplayName (%s)', displayName) return self.client.friends.updateDisplayNameForUser(self.client.username, displayName, cb) } /** * Updates your account's feature settings. * * See constants.Feature for valid keys. Invalid keys will be silently ignored. * @warning Raises an exception if \e settings contains more than 8 key-value pairs. * * @param Object settings A dictionary of string-boolean pairs. Missing keys-value pairs default to the current values. Behavior is undefined for values other than booleans. * @param {function} cb */ Account.prototype.updateFeatureSettings = function (settings, cb) { var self = this debug('Account.updateFeatureSettings') var features = { } features[constants.featureSettings.frontFacingFlash] = settings[constants.featureSettings.frontFacingFlash] || self.client.session.enableFrontFacingFlash features[constants.featureSettings.replaySnaps] = settings[constants.featureSettings.replaySnaps] || self.client.session.enableReplaySnaps features[constants.featureSettings.smartFilters] = settings[constants.featureSettings.smartFilters] || self.client.session.enableSmartFilters features[constants.featureSettings.visualFilters] = settings[constants.featureSettings.visualFilters] || self.client.session.enableVisualFilters features[constants.featureSettings.powerSaveMode] = settings[constants.featureSettings.powerSaveMode] || self.client.session.enablePowerSaveMode features[constants.featureSettings.specialText] = settings[constants.featureSettings.specialText] || self.client.session.enableSpecialText features[constants.featureSettings.swipeCashMode] = settings[constants.featureSettings.swipeCashMode] || self.client.session.enableSwipeCashMode features[constants.featureSettings.travelMode] = settings[constants.featureSettings.travelMode] || self.client.session.enableTravelMode return self.client.post(constants.endpoints.update.featureSettings, { 'settings': JSON.stringify(features), 'username': self.client.username }, cb) } /** * Downloads your account's snaptag, a personal Snapchat QR code. * * @param {function} cb */ Account.prototype.downloadSnaptag = function (cb) { var self = this return new Promise(function (resolve, reject) { debug('Account.downloadSnaptag') self.client.post(constants.endpoints.account.snaptag, { 'image': self.client.session.QRPath, 'type': 'SVG', 'username': self.client.username }, function (err) { if (err) { return reject(err) } // TODO: this returns application/json but it's actually an XML doc: // '<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n<svg height="320" version="1.1" viewBox="0 0 320 320" width="320" xmlns="http://www.w3.org/2000/svg">\n <path d="M162.31,52.4......74" fill="#FFFC00"/>\n</svg>\n' return reject(new Error('downloadSnaptag TODO')) // SKBlob.initWithData(body, cb) }) }).nodeify(cb) } /** * Uploads a new animated avatar. Not working yet. * * @param {Array<Buffer>} images An array of 5 image Buffer objects. * @param {function} cb */ Account.prototype.uploadAvatar = function (images, cb) { return new Promise(function (resolve, reject) { debug('Account.uploadAvatar') // SKEPAccount.avatar.set // multipart/form-data; takes a single 'data' parameter in addition to the usual 'username' param return reject(new Error('Account.uploadAvatar TODO')) }).nodeify(cb) } /** * Downloads the animated avatar for user. Currently encrypted, or something. * * @param {string} username The username tied to the avatar to download. * @param {function} cb */ Account.prototype.downloadAvatar = function (username, cb) { var self = this return new Promise(function (resolve, reject) { debug('Account.downloadAvatar') self.client.post(constants.endpoints.account.avatar.get, { 'username_image': username, 'username': self.client.username, 'size': 'MEDIUM' }, function (err, body) { if (err) { return reject(err) } else { SKBlob.initWithData(body, function (err, blob) { if (err) { return reject(err) } return resolve(blob) }) } }) }).nodeify(cb) } /** * Updates your TOS agreement status for each of the three Terms of Service. * * @param {boolean} snapcash * @param {boolean} snapcashV2 * @param {boolean} square * @param {function} cb */ Account.prototype.updateTOSAgreementStatus = function (snapcash, snapcashV2, square, cb) { var self = this debug('Account.updateTOSAgreementStatus') var agreements = { 'snapcash_new_tos_accepted': snapcash ? 'true' : 'false', 'snapcash_tos_v2_accepted': snapcashV2 ? 'true' : 'false', 'square_tos_accepted': square ? 'true' : 'false' } return self.client.post(constants.endpoints.update.user, { 'username': self.client.username, 'agreements': JSON.stringify(agreements) }, cb) }