2012-09-24 20:45:37 +00:00
derby = require ' derby '
2013-03-23 20:03:12 +00:00
2013-04-26 21:27:20 +00:00
# Include library components
2013-03-17 04:48:00 +00:00
derby . use require ( ' derby-ui-boot ' ) , { styles: [ ] }
2013-08-26 23:09:03 +00:00
derby . use require ' ../. '
2013-02-12 00:27:35 +00:00
derby . use require ' derby-auth/components '
2012-07-27 23:38:28 +00:00
2013-04-26 21:27:20 +00:00
# Init app & reference its functions
app = derby . createApp module
{ get , view , ready } = app
2013-03-23 20:03:12 +00:00
# Translations
i18n = require ' ./i18n '
i18n . localize app ,
2013-05-12 17:58:50 +00:00
availableLocales: [ ' en ' , ' he ' , ' bg ' , ' nl ' ]
2013-03-23 20:03:12 +00:00
defaultLocale: ' en '
2013-05-09 17:07:54 +00:00
urlScheme: false
checkHeader: true
2013-03-23 20:03:12 +00:00
2013-08-21 04:19:05 +00:00
misc = require ' ./misc '
2013-05-22 10:07:56 +00:00
misc . viewHelpers view
2013-02-08 07:01:48 +00:00
2013-05-19 23:53:18 +00:00
_ = require ( ' lodash ' )
algos = require ' habitrpg-shared/script/algos '
2013-08-21 03:55:43 +00:00
async = require ' async '
2013-04-10 22:32:38 +00:00
2013-04-11 15:33:50 +00:00
2013-08-21 03:55:43 +00:00
# ========== ROUTES ==========
get ' / ' , (page, model, params, next) ->
return page . redirect ' / ' if page . params ? . query ? . play ?
# removed force-ssl (handled in nginx), see git for code
# ##
2013-05-08 14:04:10 +00:00
Subscribe to the user , the users ' s party (meta info like party name, member ids, etc), and the party ' s members . 3 subscriptions .
2013-08-21 03:55:43 +00:00
# ##
2013-05-08 14:04:10 +00:00
uuid = model . get ( ' _userId ' ) or model . session . userId # see http://goo.gl/TPYIt
2013-08-21 03:55:43 +00:00
async . waterfall [
(cb) ->
2013-08-21 04:19:05 +00:00
publicGroupsQuery = model . query ( ' groups ' ) . publicGroups ( )
myGroupsQuery = model . query ( ' groups ' ) . withMember ( uuid )
2013-08-21 03:55:43 +00:00
model . fetch publicGroupsQuery , myGroupsQuery , cb
(publicGroups, groups, cb) ->
# Get public groups first, order most-to-least # subscribers
model . set ' _publicGroups ' , _ . sortBy ( publicGroups . get ( ) , (g) -> - _ . size ( g . members ) )
groupsObj = groups . get ( )
# (1) Solo player
return cb ( true ) if _ . isEmpty ( groupsObj ) # passing in `true` breaks out of async.waterfall
## (2) Party or Guild has members, fetch those users too
# Subscribe to the groups themselves. We separate them by _party, _guilds, and _habitRPG (the "global" guild).
groupsInfo = _ . reduce groupsObj , ( (m,g)->
if g . type is ' guild ' then m . guildIds . push ( g . id ) else m.partyId = g . id
m.members = m . members . concat ( g . members )
m
) , { guildIds : [ ] , partyId : null , members : [ ] }
2013-08-21 04:19:05 +00:00
# Parallel fetch of members, party, & guilds, not subscribe - cut back on some data
2013-08-21 05:00:13 +00:00
membersQ = model . query ( ' users ' ) . publicInfo ( groupsInfo . members )
partyQ = model . query ( ' groups ' ) . withIds ( groupsInfo . partyId )
guildsQ = model . query ( ' groups ' ) . withIds ( groupsInfo . guildIds )
model . fetch membersQ , partyQ , guildsQ , cb
] , (err, members, party, guilds) ->
2013-08-21 03:55:43 +00:00
return next ( err ) if ( err and err isnt true ) #FIXME page.render err somehow?
2013-05-08 14:04:10 +00:00
2013-08-21 05:00:13 +00:00
# we need _members as an object in the view, so we can iterate over _party.members as :id, and access _members[:id] for the info
if members
mObj = members . get ( )
model . set " _members " , _ . object ( _ . pluck ( mObj , ' id ' ) , mObj )
model . set " _membersArray " , mObj
model . ref ' _party ' , party if party
model . ref ' _guilds ' , guilds if guilds
2013-08-21 04:19:05 +00:00
# Note: due to https://github.com/codeparty/racer/issues/57, this has to come at the very beginning. The more limited
# the returned fields in motifs, the sooner they must come in fetch / subscribes.
# selfQ *must* come after membersQ in subscribe, otherwise _user will only get the fields restricted by party-members in store.coffee. Strang bug, but easy to get around
2013-05-08 14:04:10 +00:00
2013-08-21 04:19:05 +00:00
model . subscribe " users. #{ uuid } " , ' groups.habitrpg ' , (err, user, tavern) ->
2013-08-21 03:55:43 +00:00
return next ( err ) if err
2013-08-21 04:19:05 +00:00
model . ref ' _user ' , user
model . ref ' _habitRPG ' , tavern
unless user . get ( )
2013-08-21 03:55:43 +00:00
console . error " User not found - this shouldn ' t be happening! "
return page . redirect ( ' /logout ' ) #delete model.session.userId
2013-08-23 00:09:06 +00:00
require ( ' ./items ' ) . server ( model )
2013-08-21 03:55:43 +00:00
#refLists
_ . each [ ' habit ' , ' daily ' , ' todo ' , ' reward ' ] , (type) ->
model . refList " _ #{ type } List " , " _user.tasks " , " _user. #{ type } Ids "
true
page . render ( )
2013-02-21 18:40:03 +00:00
2012-04-27 02:19:31 +00:00
2012-07-28 01:11:53 +00:00
# ========== CONTROLLER FUNCTIONS ==========
2012-04-27 02:19:31 +00:00
ready (model) ->
2013-05-30 22:43:39 +00:00
user = model . at ( ' _user ' )
misc . fixCorruptUser ( model ) # https://github.com/lefnire/habitrpg/issues/634
browser = require ' ./browser '
2013-04-04 20:44:54 +00:00
require ( ' ./tasks ' ) . app ( exports , model )
2013-08-23 00:09:06 +00:00
require ( ' ./items ' ) . app ( exports , model )
2013-05-26 19:25:15 +00:00
require ( ' ./groups ' ) . app ( exports , model , app )
2013-04-04 20:44:54 +00:00
require ( ' ./profile ' ) . app ( exports , model )
require ( ' ./pets ' ) . app ( exports , model )
2013-01-15 19:35:10 +00:00
require ( ' ../server/private ' ) . app ( exports , model )
2013-04-08 15:24:45 +00:00
require ( ' ./debug ' ) . app ( exports , model ) if model . flags . nodeEnv != ' production '
2013-05-20 09:56:38 +00:00
browser . app ( exports , model , app )
2013-04-16 17:46:44 +00:00
require ( ' ./unlock ' ) . app ( exports , model )
2013-08-26 23:09:03 +00:00
require ( ' ./../. ' ) . app ( exports , model )
2013-05-11 23:05:13 +00:00
require ( ' ./challenges ' ) . app ( exports , model )
2013-05-19 23:53:18 +00:00
2013-06-05 15:55:09 +00:00
# used for things like remove website, chat, etc
exports.removeAt = (e, el) ->
if ( confirmMessage = $ ( el ) . attr ' data-confirm ' ) ?
return unless confirm ( confirmMessage ) is true
e . at ( ) . remove ( )
browser . resetDom ( model ) if $ ( el ) . attr ( ' data-refresh ' )
2013-08-21 02:17:36 +00:00
tz = user . get ( " preferences.timezoneOffset " )
unless tz and tz is ( new Date ( ) ) . getTimezoneOffset ( )
user . set ' preferences.timezoneOffset ' , ( new Date ( ) ) . getTimezoneOffset ( )
2013-05-27 13:37:57 +00:00
# ##
Cron
# ##
2013-05-29 09:23:23 +00:00
misc . batchTxn model , (uObj, paths) ->
# habitrpg-shared/algos requires uObj.habits, uObj.dailys etc instead of uObj.tasks
_ . each [ ' habit ' , ' daily ' , ' todo ' , ' reward ' ] , (type) -> uObj [ " #{ type } s " ] = _ . where ( uObj . tasks , { type } ) ; true
algos . cron uObj , { paths }
2013-06-03 18:20:22 +00:00
# for new user, just set lastCron - no need to reset dom.
# remember that the properties are set from uObj & paths AFTER the return of this callback
2013-05-29 09:23:23 +00:00
return if _ . isEmpty ( paths ) or ( paths [ ' lastCron ' ] and _ . size ( paths ) is 1 )
2013-06-03 18:20:22 +00:00
# for everyone else, we need to reset dom - too many changes have been made and won't it breaks dom listeners.
2013-07-24 19:29:03 +00:00
if paths [ ' stats.hp ' ]
delete paths [ ' stats.hp ' ] # we'll set this manually so we can get a cool animation
2013-05-29 09:23:23 +00:00
setTimeout ->
2013-05-27 13:37:57 +00:00
browser . resetDom ( model )
2013-05-29 09:23:23 +00:00
user . set ' stats.hp ' , uObj . stats . hp
, 750
, { cron : true }