Created
July 18, 2012 19:19
-
-
Save Calvein/3138232 to your computer and use it in GitHub Desktop.
Node app to receive emails of the Steam sales
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// $ npm install node-phantom nodemailer moment lodash | |
// Modules definitions | |
var phantom = require('node-phantom') | |
, nodemailer = require("nodemailer") | |
, moment = require('moment') | |
, _ = require('lodash') | |
// Email stuff | |
var smtpTransport = nodemailer.createTransport("SMTP",{ | |
service: "Gmail" | |
, auth: { | |
user: "[email protected]" | |
, pass: "password" | |
} | |
}) | |
// The HTML template for the email | |
var template = function(game) { | |
return '<tr><td>'+ | |
'<a href="' + game.link + '"><b>' + game.name + '</b></a>'+ | |
'<td>'+ | |
'<b>' + game.price + '</b> <i>' + game.discount + '</i> fin <b>' + moment(game.timeLeft).fromNow() + '</b>' | |
} | |
// Moment stuff | |
var now = moment() | |
// Today at 20:00 | |
, endSaleDay = moment([2012, 6, now.date(), 20]) | |
// If today at 20:00 is passed, then tomorrow | |
if (now.unix() > endSaleDay.unix()) { | |
endSaleDay = moment([2012, 6, now.date() + 1, 20]) | |
} | |
phantom.create(function(err, ph) { | |
ph.createPage(function(err, page) { | |
var loop = function() { | |
console.log('Loading page...') | |
page.open('http://store.steampowered.com/', function(err, status) { | |
console.log('Page opened.') | |
page.evaluate(function() { | |
var games = [] | |
/** | |
* Return the seconds in a "Steam-time-expression" (hh:mm:ss) | |
* It has to be redeclare each time because page.evaluate() is pretty much a big eval | |
* | |
* @param {string} time the time as hh:mm:ss | |
* @return {int} the seconds | |
*/ | |
, timeToSecond = function(time) { | |
if (time) { | |
var seconds = 0 | |
time.split(':').reverse().forEach(function(t, i) { | |
seconds += Math.pow(60, i) * t * 1000 | |
}) | |
return ~~seconds | |
} | |
} | |
/** | |
* Get the type of saled item | |
* | |
* @param {element} el The element to test | |
* @return {string} The type (top, flash, daily) | |
*/ | |
, getType = function(el) { | |
var type = null; | |
if (el.id) { | |
type = 'top' | |
} else if (el.querySelector('.timeleft')) { | |
type = 'flash' | |
} else { | |
type = 'daily' | |
} | |
return type | |
} | |
, timesLeft = [] | |
, game | |
, type | |
, timeLeft | |
, discount | |
, link | |
// Get the top voted one and the flashes | |
;[].forEach.call(document.querySelectorAll('#ss_topvoted, #ss_flash > .app, #ss_daily > .app'), function(el) { | |
type = getType(el) | |
link = el.querySelector('a') | |
game = link.title | |
fullTime = // The time isn't the same | |
type === 'top' ? document.querySelector('#topvoted_timer') : | |
el.querySelector('.timer') | |
timeLeft = timeToSecond(fullTime ? fullTime.innerText : null) | |
timeLeft && timesLeft.push(timeLeft) | |
discount = el.querySelector('.discount') | |
games.push({ | |
name : game | |
, type : type | |
, price : discount.querySelector('span:not(.was)').innerText.trim() | |
, discount: discount.firstChild.textContent.trim() | |
, link : link.href | |
, timeLeft: timeLeft | |
}) | |
}) | |
return { | |
games : games | |
, timesLeft : timesLeft | |
} | |
}, function(err, data) { | |
// The next refresh will occur at the minimum timeLeft + 5 seconds | |
data.timesLeft.push(endSaleDay / 1000) | |
var nextRefresh = Math.min.apply(null, data.timesLeft) + 5000 | |
console.log('Next refresh in ' + nextRefresh + 's') | |
// Email sending | |
var html = '<h2>Jeux en promos</h2><table>' | |
_.each(_.groupBy(data.games, function(game) { | |
return game.type | |
}), function(typedGames, type) { | |
html += '<tr><td><h3>' + ( | |
type === 'top' ? 'Top' : | |
type === 'flash' ? 'Ventes flash' : | |
'Offres du jour' | |
) + '</h3>' | |
_.each(typedGames, function(game, i) { | |
console.log(game.name + ' | ' + JSON.stringify(game)) | |
game.timeLeft = game.timeLeft ? moment().add(game.timeLeft) : | |
endSaleDay | |
html += template(game) | |
}) | |
}) | |
html += '</table>Prochain refresh <b>' + moment().add(nextRefresh).fromNow() + '</b>.' | |
var mailOptions = { | |
from : 'whateva' | |
, to : '[email protected]' | |
, subject: 'Soldes Steam' | |
, html : html | |
} | |
smtpTransport.sendMail(mailOptions) | |
setTimeout(loop, nextRefresh) | |
}) | |
}) | |
} | |
loop() | |
}) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment