mail = require '../commons/mail' map = _.invert mail.MAILCHIMP_GROUP_MAP User = require '../users/User.coffee' errors = require '../commons/errors' #request = require 'request' config = require '../../server_config' LevelSession = require '../levels/sessions/LevelSession.coffee' Level = require '../levels/Level.coffee' log = require 'winston' sendwithus = require '../sendwithus' #badLog = (text) -> # console.log text # request.post 'http://requestb.in/1brdpaz1', { form: {log: text} } module.exports.setup = (app) -> app.all config.mail.mailchimpWebhook, handleMailchimpWebHook app.get '/mail/cron/ladder-update', handleLadderUpdate getAllLadderScores = (next) -> query = Level.find({type: 'ladder'}) .select('levelID') .lean() query.exec (err, levels) -> if err log.error "Couldn't fetch ladder levels. Error: ", err return next [] for level in levels for team in ['humans', 'ogres'] 'I ... am not doing this.' handleLadderUpdate = (req, res) -> log.info("Going to see about sending ladder update emails.") res.send('Great work, Captain Cron! I can take it from here.') res.end() # TODO: somehow fetch the histograms emailDays = [1, 2, 4, 7, 30] now = new Date() getTimeFromDaysAgo = (daysAgo) -> # 2 hours before the date t = now - (86400 * daysAgo + 2 * 3600) * 1000 for daysAgo in emailDays # Get every session that was submitted in a 5-minute window after the time. startTime = getTimeFromDaysAgo daysAgo endTime = startTime + 5 * 60 * 1000 #endTime = startTime + 1.5 * 60 * 60 * 1000 # Debugging: make sure there's something to send findParameters = {submitted: true, submitDate: {$gt: new Date(startTime), $lte: new Date(endTime)}} # TODO: think about putting screenshots in the email selectString = "creator team levelName levelID totalScore matches submitted submitDate" query = LevelSession.find(findParameters) .select(selectString) .lean() do (daysAgo) -> query.exec (err, results) -> if err log.error "Couldn't fetch ladder updates for #{findParameters}\nError: #{err}" return errors.serverError res, "Ladder update email query failed: #{JSON.stringify(err)}" log.info "Found #{results.length} ladder sessions to email updates about for #{daysAgo} day(s) ago." sendLadderUpdateEmail result, daysAgo for result in results sendLadderUpdateEmail = (session, daysAgo) -> User.findOne({_id: session.creator}).select("name email firstName lastName emailSubscriptions preferredLanguage").lean().exec (err, user) -> if err log.error "Couldn't find user for #{session.creator} from session #{session._id}" return unless user.email and ('notification' in user.emailSubscriptions) and not session.unsubscribed log.info "Not sending email to #{user.email} #{user.name} because they only want emails about #{user.emailSubscriptions} - session unsubscribed: #{session.unsubscribed}" return unless session.levelName log.info "Not sending email to #{user.email} #{user.name} because the session had no levelName in it." return name = if user.firstName and user.lastName then "#{user.firstName} #{user.lastName}" else user.name name = "Wizard" if not name or name is "Anoner" # Fetch the most recent defeat and victory, if there are any. # (We could look at strongest/weakest, but we'd have to fetch everyone, or denormalize more.) matches = _.filter session.matches, (match) -> match.date >= (new Date() - 86400 * 1000 * daysAgo) defeats = _.filter matches, (match) -> match.metrics.rank is 1 and match.opponents[0].metrics.rank is 0 victories = _.filter matches, (match) -> match.metrics.rank is 0 defeat = _.last defeats victory = _.last victories sendEmail = (defeatContext, victoryContext) -> # TODO: do something with the preferredLanguage? context = email_id: sendwithus.templates.ladder_update_email recipient: address: user.email #address: 'nick@codecombat.com' # Debugging name: name email_data: name: name days_ago: daysAgo wins: victories.length losses: defeats.length total_score: Math.round(session.totalScore * 100) team: session.team team_name: session.team[0].toUpperCase() + session.team.substr(1) level_name: session.levelName session_id: session._id ladder_url: "http://codecombat.com/play/ladder/#{session.levelID}#my-matches" defeat: defeatContext victory: victoryContext log.info "Sending ladder update email to #{context.recipient.address} with #{context.email_data.wins} wins and #{context.email_data.losses} since #{daysAgo} day(s) ago." sendwithus.api.send context, (err, result) -> log.error "Error sending ladder update email: #{err} with result #{result}" if err urlForMatch = (match) -> "http://codecombat.com/play/level/#{session.levelID}?team=#{session.team}&session=#{session._id}&opponent=#{match.opponents[0].sessionID}" onFetchedDefeatedOpponent = (err, defeatedOpponent) -> if err log.error "Couldn't find defeateded opponent: #{err}" defeatedOpponent = null victoryContext = {opponent_name: defeatedOpponent?.name ? "Anoner", url: urlForMatch(victory)} if victory onFetchedVictoriousOpponent = (err, victoriousOpponent) -> if err log.error "Couldn't find victorious opponent: #{err}" victoriousOpponent = null defeatContext = {opponent_name: victoriousOpponent?.name ? "Anoner", url: urlForMatch(defeat)} if defeat sendEmail defeatContext, victoryContext if defeat User.findOne({_id: defeat.opponents[0].userID}).select("name").lean().exec onFetchedVictoriousOpponent else onFetchedVictoriousOpponent null, null if victory User.findOne({_id: victory.opponents[0].userID}).select("name").lean().exec onFetchedDefeatedOpponent else onFetchedDefeatedOpponent null, null handleMailchimpWebHook = (req, res) -> post = req.body #badLog("Got post data: #{JSON.stringify(post, null, '\t')}") unless post.type in ['unsubscribe', 'profile'] res.send 'Bad post type' return res.end() unless post.data.email res.send 'No email provided' return res.end() query = {'mailChimp.leid':post.data.web_id} User.findOne query, (err, user) -> return errors.serverError(res) if err if not user return errors.notFound(res) handleProfileUpdate(user, post) if post.type is 'profile' handleUnsubscribe(user) if post.type is 'unsubscribe' user.updatedMailChimp = true # so as not to echo back to mailchimp user.save (err) -> return errors.serverError(res) if err res.end('Success') handleProfileUpdate = (user, post) -> groups = post.data.merges.INTERESTS.split(', ') groups = (map[g] for g in groups when map[g]) otherSubscriptions = (g for g in user.get('emailSubscriptions') when not mail.MAILCHIMP_GROUP_MAP[g]) groups = groups.concat otherSubscriptions user.set 'emailSubscriptions', groups fname = post.data.merges.FNAME user.set('firstName', fname) if fname lname = post.data.merges.LNAME user.set('lastName', lname) if lname user.set 'mailChimp.email', post.data.email user.set 'mailChimp.euid', post.data.id # badLog("Updating user object to: #{JSON.stringify(user.toObject(), null, '\t')}") handleUnsubscribe = (user) -> user.set 'emailSubscriptions', [] # badLog("Unsubscribing user object to: #{JSON.stringify(user.toObject(), null, '\t')}")