codecombat/server/lib/utils.coffee
2015-09-25 10:28:27 -07:00

89 lines
3.8 KiB
CoffeeScript

AnalyticsString = require '../analytics/AnalyticsString'
log = require 'winston'
mongoose = require 'mongoose'
config = require '../../server_config'
module.exports =
isID: (id) -> _.isString(id) and id.length is 24 and id.match(/[a-f0-9]/gi)?.length is 24
objectIdFromTimestamp: (timestamp) ->
# mongoDB ObjectId contains creation date in first 4 bytes
# So, it can be used instead of a redundant created field
# http://docs.mongodb.org/manual/reference/object-id/
# http://stackoverflow.com/questions/8749971/can-i-query-mongodb-objectid-by-date
# Convert string date to Date object (otherwise assume timestamp is a date)
timestamp = new Date(timestamp) if typeof(timestamp) == 'string'
# Convert date object to hex seconds since Unix epoch
hexSeconds = Math.floor(timestamp/1000).toString(16)
# Create an ObjectId with that hex timestamp
mongoose.Types.ObjectId(hexSeconds + "0000000000000000")
findStripeSubscription: (customerID, options, done) ->
# Grabs latest subscription (e.g. in case of a resubscribe)
return done() unless customerID?
return done() unless options.subscriptionID? or options.userID?
# Some prepaid tests were calling this in such a way that stripe wasn't defined.
stripe = require('stripe')(config.stripe.secretKey) unless stripe
subscriptionID = options.subscriptionID
userID = options.userID
subscription = null
nextBatch = (starting_after, done) ->
options = limit: 100
options.starting_after = starting_after if starting_after
stripe.customers.listSubscriptions customerID, options, (err, subscriptions) ->
return done(subscription) if err
return done(subscription) unless subscriptions?.data?.length > 0
for sub in subscriptions.data
if subscriptionID? and sub.id is subscriptionID
unless subscription?.cancel_at_period_end is false
subscription = sub
if userID? and sub.metadata?.id is userID
unless subscription?.cancel_at_period_end is false
subscription = sub
# Check for backwards compatible basic subscription search
# Only recipient subscriptions are currently searched for via userID
if userID? and not sub.metadata?.id and sub.plan?.id is 'basic'
subscription ?= sub
return done(subscription) if subscription?.cancel_at_period_end is false
if subscriptions.has_more
nextBatch(subscriptions.data[subscriptions.data.length - 1].id, done)
else
done(subscription)
nextBatch(null, done)
getAnalyticsStringID: (str, callback) ->
unless str?
log.error "getAnalyticsStringID given invalid str param"
return callback -1
@analyticsStringCache ?= {}
return callback @analyticsStringCache[str] if @analyticsStringCache[str]
insertString = =>
# http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/#auto-increment-optimistic-loop
AnalyticsString.find({}, {_id: 1}).sort({_id: -1}).limit(1).exec (err, documents) =>
if err?
log.error "Failed to find next analytics string _id for #{str}"
return callback -1
seq = if documents.length > 0 then documents[0]._id + 1 else 1
doc = new AnalyticsString _id: seq, v: str
doc.save (err) =>
if err?
log.error "Failed to save analytics string ID for #{str}"
return callback -1
@analyticsStringCache[str] = seq
callback seq
# Find existing string
AnalyticsString.findOne(v: str).exec (err, document) =>
if err?
log.error "Failed to lookup analytics string #{str}"
return callback -1
if document
@analyticsStringCache[str] = document._id
return callback @analyticsStringCache[str]
insertString()