From dfd2a17ef906603dfcdbeec86ead974e2d508c42 Mon Sep 17 00:00:00 2001 From: Tyler Renelle Date: Sat, 28 Dec 2013 11:31:21 -0700 Subject: [PATCH] APIv2: instead of passing `req` to callback, passing response object so API can return the object when wrapped on the server --- dist/habitrpg-shared.js | 144 +++++++++++++++++++++------------------- script/index.coffee | 102 ++++++++++++++-------------- script/userServices.js | 30 +++++---- 3 files changed, 147 insertions(+), 129 deletions(-) diff --git a/dist/habitrpg-shared.js b/dist/habitrpg-shared.js index 199719754d..0c5fc94831 100644 --- a/dist/habitrpg-shared.js +++ b/dist/habitrpg-shared.js @@ -10619,7 +10619,7 @@ var global=self;/** },{"lodash":3,"moment":4}],6:[function(require,module,exports){ var process=require("__browserify_process");(function() { - var api, content, dayMapping, moment, preenHistory, sanitizeOptions, _, + var $w, api, content, dayMapping, moment, preenHistory, sanitizeOptions, _, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; moment = require('moment'); @@ -10630,6 +10630,10 @@ var process=require("__browserify_process");(function() { api = module.exports = {}; + $w = function(s) { + return s.split(' '); + }; + /* ------------------------------------------------------ Time / Day @@ -10880,6 +10884,9 @@ var process=require("__browserify_process");(function() { api.taskDefaults = function(task) { var defaults, _ref, _ref1, _ref2; + if (task == null) { + task = {}; + } if (!(task.type && ((_ref = task.type) === 'habit' || _ref === 'daily' || _ref === 'todo' || _ref === 'reward'))) { task.type = 'habit'; } @@ -11168,11 +11175,11 @@ var process=require("__browserify_process");(function() { user.fns.dotSet(k, v); return true; }); - return typeof cb === "function" ? cb(null, req) : void 0; + return typeof cb === "function" ? cb(null, user) : void 0; }, sleep: function(req, cb) { user.preferences.sleep = !user.preferences.sleep; - return cb(null, req); + return typeof cb === "function" ? cb(null, {}) : void 0; }, revive: function(req, cb) { var item, lostItem, lostStat; @@ -11214,7 +11221,7 @@ var process=require("__browserify_process");(function() { return typeof cb === "function" ? cb((item ? { code: 200, message: "Your " + item.text + " broke." - } : null), req) : void 0; + } : null), user) : void 0; }, reset: function(req, cb) { var gear; @@ -11240,77 +11247,78 @@ var process=require("__browserify_process");(function() { user.markModified('items.gear.owned'); } user.preferences.costume = false; - return cb(null, req); + return typeof cb === "function" ? cb(null, user) : void 0; }, reroll: function(req, cb) { if (user.balance < 1) { - return cb({ + return typeof cb === "function" ? cb({ code: 401, message: "Not enough gems." - }, req); + }, req) : void 0; } user.balance--; _.each(user.tasks, function(task) { return task.value = 0; }); user.stats.hp = 50; - return cb(null, req); + return typeof cb === "function" ? cb(null, user) : void 0; }, clearCompleted: function(req, cb) { user.todos = _.where(user.todos, { completed: false }); - return cb(null, req); + return typeof cb === "function" ? cb(null, user.todos) : void 0; }, sortTask: function(req, cb) { - var from, id, task, to, _ref; + var from, id, task, tasks, to, _ref; id = req.params.id; _ref = req.query, to = _ref.to, from = _ref.from; task = user.tasks[id]; if (!task) { - return cb({ + return typeof cb === "function" ? cb({ code: 404, message: "Task not found." - }); + }) : void 0; } if (!((to != null) && (from != null))) { - return cb('?to=__&from=__ are required'); + return typeof cb === "function" ? cb('?to=__&from=__ are required') : void 0; } - user["" + task.type + "s"].splice(to, 0, user["" + task.type + "s"].splice(from, 1)[0]); - return cb(null, req); + tasks = user["" + task.type + "s"]; + tasks.splice(to, 0, tasks.splice(from, 1)[0]); + return typeof cb === "function" ? cb(null, tasks) : void 0; }, updateTask: function(req, cb) { - var _base, _ref; - if (!user.tasks[(_ref = req.params) != null ? _ref.id : void 0]) { + var task, _ref; + if (!(task = user.tasks[(_ref = req.params) != null ? _ref.id : void 0])) { return typeof cb === "function" ? cb("Task not found") : void 0; } - _.merge(user.tasks[req.params.id], req.body); - if (typeof (_base = user.tasks[req.params.id]).markModified === "function") { - _base.markModified('tags'); + _.merge(task, req.body); + if (typeof task.markModified === "function") { + task.markModified('tags'); } - return typeof cb === "function" ? cb(null, req) : void 0; + return typeof cb === "function" ? cb(null, task) : void 0; }, deleteTask: function(req, cb) { var i, task, _ref; task = user.tasks[(_ref = req.params) != null ? _ref.id : void 0]; if (!task) { - return cb({ + return typeof cb === "function" ? cb({ code: 404, message: 'Task not found' - }); + }) : void 0; } i = user[task.type + "s"].indexOf(task); if (~i) { user[task.type + "s"].splice(i, 1); } - return cb(null, req); + return typeof cb === "function" ? cb(null, {}) : void 0; }, addTask: function(req, cb) { var task; task = api.taskDefaults(req.body); user["" + task.type + "s"].unshift(task); if (typeof cb === "function") { - cb(null, req); + cb(null, task); } return task; }, @@ -11323,7 +11331,7 @@ var process=require("__browserify_process");(function() { user.tags.push({ name: name }); - return typeof cb === "function" ? cb(null, req) : void 0; + return typeof cb === "function" ? cb(null, user.tags) : void 0; }, updateTag: function(req, cb) { var i, tid; @@ -11332,10 +11340,10 @@ var process=require("__browserify_process");(function() { id: tid }); if (!~i) { - return cb('Tag not found', req); + return typeof cb === "function" ? cb('Tag not found', req) : void 0; } user.tags[i].name = req.body.name; - return typeof cb === "function" ? cb(null, req) : void 0; + return typeof cb === "function" ? cb(null, user.tags[i]) : void 0; }, deleteTag: function(req, cb) { var i, tag, tid; @@ -11344,7 +11352,7 @@ var process=require("__browserify_process");(function() { id: tid }); if (!~i) { - return cb('Tag not found', req); + return typeof cb === "function" ? cb('Tag not found', req) : void 0; } tag = user.tags[i]; delete user.filters[tag.id]; @@ -11355,7 +11363,7 @@ var process=require("__browserify_process");(function() { _.each(['habits', 'dailys', 'todos', 'rewards'], function(type) { return typeof user.markModified === "function" ? user.markModified(type) : void 0; }); - return cb(null, req); + return typeof cb === "function" ? cb(null, user.tags) : void 0; }, feed: function(req, cb) { var egg, evolve, food, message, pet, potion, userPets, _ref, _ref1, _ref2; @@ -11364,28 +11372,28 @@ var process=require("__browserify_process");(function() { _ref1 = pet.split('-'), egg = _ref1[0], potion = _ref1[1]; userPets = user.items.pets; if (!userPets[pet]) { - return cb({ + return typeof cb === "function" ? cb({ code: 404, message: ":pet not found in user.items.pets" - }); + }) : void 0; } if (!((_ref2 = user.items.food) != null ? _ref2[food.key] : void 0)) { - return cb({ + return typeof cb === "function" ? cb({ code: 404, message: ":food not found in user.items.food" - }); + }) : void 0; } if (content.specialPets[pet]) { - return cb({ + return typeof cb === "function" ? cb({ code: 401, message: "Can't feed this pet." - }); + }) : void 0; } if (user.items.mounts[pet] && (userPets[pet] >= 50 || food.key === 'Saddle')) { - return cb({ + return typeof cb === "function" ? cb({ code: 401, message: "You already have that mount" - }); + }) : void 0; } message = ''; evolve = function() { @@ -11411,33 +11419,33 @@ var process=require("__browserify_process");(function() { } } user.items.food[food.key]--; - return cb({ + return typeof cb === "function" ? cb({ code: 200, message: message - }, req); + }, userPets[pet]) : void 0; }, purchase: function(req, cb) { var item, key, type, _ref; _ref = req.params, type = _ref.type, key = _ref.key; if (type !== 'eggs' && type !== 'hatchingPotions' && type !== 'food' && type !== 'quests' && type !== 'special') { - return cb({ + return typeof cb === "function" ? cb({ code: 404, message: ":type must be in [hatchingPotions,eggs,food,quests,special]" - }, req); + }, req) : void 0; } item = content[type][key]; if (!item) { - return cb({ + return typeof cb === "function" ? cb({ code: 404, message: ":key not found for Content." + type - }, req); + }, req) : void 0; } if (!user.items[type][key]) { user.items[type][key] = 0; } user.items[type][key]++; user.balance -= item.value / 4; - return cb(null, req); + return typeof cb === "function" ? cb(null, _.pick(user, $w('items balance'))) : void 0; }, buy: function(req, cb) { var item, key, message, _ref; @@ -11475,26 +11483,26 @@ var process=require("__browserify_process");(function() { return typeof cb === "function" ? cb({ code: 200, message: message - }, req) : void 0; + }, _.pick(user, $w('items achievements stats'))) : void 0; }, sell: function(req, cb) { var key, type, _ref; _ref = req.params, key = _ref.key, type = _ref.type; if (type !== 'eggs' && type !== 'hatchingPotions' && type !== 'food') { - return cb({ + return typeof cb === "function" ? cb({ code: 404, message: ":type not found. Must bes in [eggs, hatchingPotions, food]" - }); + }) : void 0; } if (!user.items[type][key]) { - return cb({ + return typeof cb === "function" ? cb({ code: 404, message: ":key not found for user.items." + type - }); + }) : void 0; } user.items[type][key]--; user.stats.gp += content[type][key].value; - return typeof cb === "function" ? cb(null, req) : void 0; + return typeof cb === "function" ? cb(null, _.pick(user, $w('stats items'))) : void 0; }, equip: function(req, cb) { var item, key, message, type, _ref; @@ -11512,29 +11520,29 @@ var process=require("__browserify_process");(function() { user.items.gear[type][item.type] = item.key; message = user.fns.handleTwoHanded(item, type); } - return cb({ + return typeof cb === "function" ? cb({ code: 200, message: message - }, req); + }, user.items) : void 0; }, hatch: function(req, cb) { var egg, hatchingPotion, pet, _ref; _ref = req.params, egg = _ref.egg, hatchingPotion = _ref.hatchingPotion; if (!(egg && hatchingPotion)) { - return cb({ + return typeof cb === "function" ? cb({ code: 404, message: "Please specify query.egg & query.hatchingPotion" - }); + }) : void 0; } if (!(user.items.eggs[egg] > 0 && user.items.hatchingPotions[hatchingPotion] > 0)) { - return cb({ + return typeof cb === "function" ? cb({ code: 401, message: "You're missing either that egg or that potion" - }); + }) : void 0; } pet = "" + egg + "-" + hatchingPotion; if (user.items.pets[pet]) { - return cb("You already have that pet. Try hatching a different combination!"); + return typeof cb === "function" ? cb("You already have that pet. Try hatching a different combination!") : void 0; } user.items.pets[pet] = 5; user.items.eggs[egg]--; @@ -11542,7 +11550,7 @@ var process=require("__browserify_process");(function() { return typeof cb === "function" ? cb({ code: 200, message: "Your egg hatched! Visit your stable to equip your pet." - }, req) : void 0; + }, user.items) : void 0; }, unlock: function(req, cb) { var alreadyOwns, cost, fullSet, k, path, split, v; @@ -11575,7 +11583,7 @@ var process=require("__browserify_process");(function() { if (typeof user.markModified === "function") { user.markModified('purchased'); } - return typeof cb === "function" ? cb(null, req) : void 0; + return typeof cb === "function" ? cb(null, _.pick(user, $w('purchased preferences'))) : void 0; }, changeClass: function(req, cb) { var klass, _ref; @@ -11600,13 +11608,13 @@ var process=require("__browserify_process");(function() { } else { if (user.preferences.disableClasses) { user.preferences.disableClasses = false; - user.autoAllocate = false; + user.preferences.autoAllocate = false; } else { if (!(user.balance >= .75)) { - return cb({ + return typeof cb === "function" ? cb({ code: 401, message: "Not enough gems" - }); + }) : void 0; } user.balance -= .75; } @@ -11619,7 +11627,7 @@ var process=require("__browserify_process");(function() { }); user.flags.classSelected = false; } - return typeof cb === "function" ? cb(null, req) : void 0; + return typeof cb === "function" ? cb(null, _.pick(user, $w('stats flags items preferences'))) : void 0; }, disableClasses: function(req, cb) { user.stats["class"] = 'warrior'; @@ -11628,7 +11636,7 @@ var process=require("__browserify_process");(function() { user.preferences.autoAllocate = true; user.stats.str = user.stats.lvl; user.stats.points = 0; - return cb(null, req); + return typeof cb === "function" ? cb(null, _.pick(user, $w('stats flags preferences'))) : void 0; }, allocate: function(req, cb) { var stat; @@ -11640,7 +11648,7 @@ var process=require("__browserify_process");(function() { user.stats.mp++; } } - return typeof cb === "function" ? cb(null, req) : void 0; + return typeof cb === "function" ? cb(null, _.pick(user, $w('stats'))) : void 0; }, score: function(req, cb) { var addPoints, calculateDelta, delta, direction, id, num, options, stats, subtractPoints, task, th, _ref; @@ -11663,7 +11671,7 @@ var process=require("__browserify_process");(function() { task.priority = 1; } if (task.value > stats.gp && task.type === 'reward') { - return cb('Not enough Gold'); + return typeof cb === "function" ? cb('Not enough Gold') : void 0; } delta = 0; calculateDelta = function() { @@ -11779,7 +11787,7 @@ var process=require("__browserify_process");(function() { } } if (typeof cb === "function") { - cb(null, req); + cb(null, user); } return delta; } diff --git a/script/index.coffee b/script/index.coffee index 2c9932b219..d39f0a0a6f 100644 --- a/script/index.coffee +++ b/script/index.coffee @@ -4,6 +4,9 @@ content = require('./content.coffee') api = module.exports = {} +# little helper for large arrays of strings. %w"this that another" equivalent from Rails, I really miss that function +$w = (s)->s.split(' ') + ### ------------------------------------------------------ Time / Day @@ -163,7 +166,7 @@ api.uuid = -> Even though Mongoose handles task defaults, we want to make sure defaults are set on the client-side before sending up to the server for performance ### -api.taskDefaults = (task) -> +api.taskDefaults = (task={}) -> task.type = 'habit' unless task.type and task.type in ['habit','daily','todo','reward'] defaults = id: api.uuid() @@ -347,11 +350,11 @@ api.wrap = (user) -> update: (req, cb) -> _.each req.body, (v,k) -> user.fns.dotSet(k,v);true - cb? null, req + cb? null, user sleep: (req, cb) -> user.preferences.sleep = !user.preferences.sleep - cb null, req + cb? null, {} revive: (req, cb) -> # Reset stats @@ -371,7 +374,7 @@ api.wrap = (user) -> user.items.gear.equipped[item.type] = "#{item.type}_base_0" if user.items.gear.equipped[item.type] is lostItem user.items.gear.costume[item.type] = "#{item.type}_base_0" if user.items.gear.costume[item.type] is lostItem user.markModified? 'items.gear' - cb? (if item then {code:200,message:"Your #{item.text} broke."} else null), req + cb? (if item then {code:200,message:"Your #{item.text} broke."} else null), user reset: (req, cb) -> user.habits = [] @@ -392,16 +395,16 @@ api.wrap = (user) -> user.items.gear.owned = {weapon_warrior_0:true} user.markModified? 'items.gear.owned' user.preferences.costume = false - cb null, req + cb? null, user reroll: (req, cb) -> if user.balance < 1 - return cb {code:401,message: "Not enough gems."}, req + return cb? {code:401,message: "Not enough gems."}, req user.balance-- _.each user.tasks, (task) -> task.value = 0 user.stats.hp = 50 - cb null, req + cb? null, user # ------ # Tasks @@ -409,34 +412,35 @@ api.wrap = (user) -> clearCompleted: (req, cb) -> user.todos = _.where(user.todos, {completed: false}) - cb null, req + cb? null, user.todos sortTask: (req, cb) -> {id} = req.params {to, from} = req.query task = user.tasks[id] - return cb({code:404, message: "Task not found."}) unless task - return cb('?to=__&from=__ are required') unless to? and from? - user["#{task.type}s"].splice to, 0, user["#{task.type}s"].splice(from, 1)[0] - cb null, req + return cb?({code:404, message: "Task not found."}) unless task + return cb?('?to=__&from=__ are required') unless to? and from? + tasks = user["#{task.type}s"] + tasks.splice to, 0, tasks.splice(from, 1)[0] + cb? null, tasks updateTask: (req, cb) -> - return cb?("Task not found") unless user.tasks[req.params?.id] - _.merge user.tasks[req.params.id], req.body - user.tasks[req.params.id].markModified? 'tags' - cb? null, req + return cb?("Task not found") unless task = user.tasks[req.params?.id] + _.merge task, req.body + user.markModified? 'tags' + cb? null, task deleteTask: (req, cb) -> task = user.tasks[req.params?.id] - return cb({code:404,message:'Task not found'}) unless task + return cb?({code:404,message:'Task not found'}) unless task i = user[task.type + "s"].indexOf(task) user[task.type + "s"].splice(i, 1) if ~i - cb null, req + cb? null, {} addTask: (req, cb) -> task = api.taskDefaults(req.body) user["#{task.type}s"].unshift(task) - cb? null, req + cb? null, task task # ------ @@ -447,19 +451,19 @@ api.wrap = (user) -> {name} = req.body user.tags ?= [] user.tags.push({name}) - cb? null, req + cb? null, user.tags updateTag: (req, cb) -> tid = req.params.id i = _.findIndex user.tags, {id: tid} - return cb('Tag not found', req) if !~i + return cb?('Tag not found', req) if !~i user.tags[i].name = req.body.name - cb? null, req + cb? null, user.tags[i] deleteTag: (req, cb) -> tid = req.params.id i = _.findIndex user.tags, {id: tid} - return cb('Tag not found', req) if !~i + return cb?('Tag not found', req) if !~i tag = user.tags[i] delete user.filters[tag.id] user.tags.splice i, 1 @@ -470,7 +474,7 @@ api.wrap = (user) -> _.each ['habits','dailys','todos','rewards'], (type) -> user.markModified? type - cb null, req + cb? null, user.tags # ------ # Inventory @@ -482,10 +486,10 @@ api.wrap = (user) -> [egg, potion] = pet.split('-') userPets = user.items.pets - return cb({code:404, message:":pet not found in user.items.pets"}) unless userPets[pet] - return cb({code:404, message:":food not found in user.items.food"}) unless user.items.food?[food.key] - return cb({code:401, message:"Can't feed this pet."}) if content.specialPets[pet] - return cb({code:401, message:"You already have that mount"}) if user.items.mounts[pet] and (userPets[pet] >= 50 or food.key is 'Saddle') + return cb?({code:404, message:":pet not found in user.items.pets"}) unless userPets[pet] + return cb?({code:404, message:":food not found in user.items.food"}) unless user.items.food?[food.key] + return cb?({code:401, message:"Can't feed this pet."}) if content.specialPets[pet] + return cb?({code:401, message:"You already have that mount"}) if user.items.mounts[pet] and (userPets[pet] >= 50 or food.key is 'Saddle') message = '' evolve = -> @@ -506,18 +510,18 @@ api.wrap = (user) -> if userPets[pet] >= 50 and !user.items.mounts[pet] evolve() user.items.food[food.key]-- - cb {code:200, message}, req + cb? {code:200, message}, userPets[pet] # buy is for gear, purchase is for gem-purchaseables (i know, I know...) purchase: (req, cb) -> {type,key} = req.params - return cb({code:404,message:":type must be in [hatchingPotions,eggs,food,quests,special]"},req) unless type in ['eggs','hatchingPotions','food','quests','special'] + return cb?({code:404,message:":type must be in [hatchingPotions,eggs,food,quests,special]"},req) unless type in ['eggs','hatchingPotions','food','quests','special'] item = content[type][key] - return cb({code:404,message:":key not found for Content.#{type}"},req) unless item + return cb?({code:404,message:":key not found for Content.#{type}"},req) unless item user.items[type][key] = 0 unless user.items[type][key] user.items[type][key]++ user.balance -= (item.value / 4) - cb null, req + cb? null, _.pick(user,$w 'items balance') # buy is for gear, purchase is for gem-purchaseables (i know, I know...) buy: (req, cb) -> @@ -536,15 +540,15 @@ api.wrap = (user) -> if item.klass in ['warrior','wizard','healer','rogue'] and user.fns.getItem('weapon').last and user.fns.getItem('armor').last and user.fns.getItem('head').last and (user.fns.getItem('shield').last or user.fns.getItem('weapon').twoHanded) user.achievements.ultimateGear = true user.stats.gp -= item.value - cb? {code:200, message}, req + cb? {code:200, message}, _.pick(user,$w 'items achievements stats') sell: (req, cb) -> {key, type} = req.params - return cb({code:404,message:":type not found. Must bes in [eggs, hatchingPotions, food]"}) unless type in ['eggs','hatchingPotions', 'food'] - return cb({code:404,message:":key not found for user.items.#{type}"}) unless user.items[type][key] + return cb?({code:404,message:":type not found. Must bes in [eggs, hatchingPotions, food]"}) unless type in ['eggs','hatchingPotions', 'food'] + return cb?({code:404,message:":key not found for user.items.#{type}"}) unless user.items[type][key] user.items[type][key]-- user.stats.gp += content[type][key].value - cb? null, req + cb? null, _.pick(user,$w 'stats items') equip: (req, cb) -> [type, key] = [req.params.type || 'equipped', req.params.key] @@ -557,18 +561,18 @@ api.wrap = (user) -> item = content.gear.flat[key] user.items.gear[type][item.type] = item.key message = user.fns.handleTwoHanded(item,type) - cb {code:200,message}, req + cb? {code:200,message}, user.items hatch: (req, cb) -> {egg, hatchingPotion} = req.params - return cb({code:404,message:"Please specify query.egg & query.hatchingPotion"}) unless egg and hatchingPotion - return cb({code:401,message:"You're missing either that egg or that potion"}) unless user.items.eggs[egg] > 0 and user.items.hatchingPotions[hatchingPotion] > 0 + return cb?({code:404,message:"Please specify query.egg & query.hatchingPotion"}) unless egg and hatchingPotion + return cb?({code:401,message:"You're missing either that egg or that potion"}) unless user.items.eggs[egg] > 0 and user.items.hatchingPotions[hatchingPotion] > 0 pet = "#{egg}-#{hatchingPotion}" - return cb("You already have that pet. Try hatching a different combination!") if user.items.pets[pet] + return cb?("You already have that pet. Try hatching a different combination!") if user.items.pets[pet] user.items.pets[pet] = 5 user.items.eggs[egg]-- user.items.hatchingPotions[hatchingPotion]-- - cb? {code:200, message:"Your egg hatched! Visit your stable to equip your pet."}, req + cb? {code:200, message:"Your egg hatched! Visit your stable to equip your pet."}, user.items unlock: (req, cb) -> {path} = req.query @@ -587,7 +591,7 @@ api.wrap = (user) -> user.fns.dotSet "purchased." + path, true user.balance -= cost user.markModified? 'purchased' - cb? null, req + cb? null, _.pick(user,$w 'purchased preferences') # ------ # Classes @@ -620,14 +624,14 @@ api.wrap = (user) -> # Null ?class value means "reset class" if user.preferences.disableClasses user.preferences.disableClasses = false - user.autoAllocate = false + user.preferences.autoAllocate = false else - return cb({code:401,message:"Not enough gems"}) unless user.balance >= .75 + return cb?({code:401,message:"Not enough gems"}) unless user.balance >= .75 user.balance -= .75 _.merge user.stats, {str: 0, con: 0, per: 0, int: 0, points: user.stats.lvl} user.flags.classSelected = false #'stats.points': this is handled on the server - cb? null, req + cb? null, _.pick(user,$w 'stats flags items preferences') disableClasses: (req, cb) -> user.stats.class = 'warrior' @@ -636,7 +640,7 @@ api.wrap = (user) -> user.preferences.autoAllocate = true user.stats.str = user.stats.lvl user.stats.points = 0 - cb null, req + cb? null, _.pick(user,$w 'stats flags preferences') allocate: (req, cb) -> stat = req.query.stat or 'str' @@ -644,7 +648,7 @@ api.wrap = (user) -> user.stats[stat]++ user.stats.points-- user.stats.mp++ if stat is 'int' #increase their MP along with their max MP - cb? null, req + cb? null, _.pick(user,$w 'stats') # ------ # Score @@ -665,7 +669,7 @@ api.wrap = (user) -> # If they're trying to purhcase a too-expensive reward, don't allow them to do that. if task.value > stats.gp and task.type is 'reward' - return cb('Not enough Gold'); + return cb? 'Not enough Gold' delta = 0 @@ -787,7 +791,7 @@ api.wrap = (user) -> if typeof window is 'undefined' user.fns.randomDrop({task, delta}) if direction is 'up' - cb? null, req + cb? null, user return delta # ---------------------------------------------------------------------- diff --git a/script/userServices.js b/script/userServices.js index b6d63c0311..44abd33324 100644 --- a/script/userServices.js +++ b/script/userServices.js @@ -71,20 +71,26 @@ angular.module('userServices', []). // Update user _.extend(user, data); if (!user._wrapped){ + + // This wraps user with `ops`, which are functions shared both on client and mobile. When performed on client, + // they update the user in the browser and then send the request to the server, where the same operation is + // replicated. We need to wrap each op to provide a callback to send that operation $window.habitrpgShared.wrap(user); _.each(user.ops, function(op,k){ - user.ops[k] = _.partialRight(op, function(err, req){ - if (err) { - var message = err.code ? err.message : err; - console.log(message); - if (MOBILE_APP) Notification.push({type:'text',text:message}); - else Notification.text(message); - // In the case of 200s, they're friendly alert messages like "You're pet has hatched!" - still send the op - if ((err.code && err.code >= 400) || !err.code) return; - - } - userServices.log({op:k, params: req.params, query:req.query, body:req.body}); - }); + user.ops[k] = function(req,cb){ + if (cb) return op(req,cb); + op(req,function(err,response){ + if (err) { + var message = err.code ? err.message : err; + console.log(message); + if (MOBILE_APP) Notification.push({type:'text',text:message}); + else Notification.text(message); + // In the case of 200s, they're friendly alert messages like "You're pet has hatched!" - still send the op + if ((err.code && err.code >= 400) || !err.code) return; + } + userServices.log({op:k, params: req.params, query:req.query, body:req.body}); + }); + } }); }