var http = require('http') var Stack = require('stack') var route = require('tiny-route') var db = require('./db') var pull = require('pull-stream') var toPull = require('stream-to-pull-stream') var pl = require('pull-level') var stringify = require('pull-stringify') var urls = require('./urls') var marked = require('marked') function render(data, format, md) { if(format === '.json') return JSON.stringify(data, null, 2) + '\n\n' if(format === '.md') return md(data) return '
'+marked(md(data))+'
' } function capitalize (n) { return n[0].toUpperCase() + n.substring(1).toLowerCase() } function log (e) { console.log(e) return e } function sections (text) { return log(text.split(/([\w,\s]+):/).map(function (e, i) { if(!(i%2)) return e + '\n\n' if(/\s/.test(e.trim())) return '### ' + e else return '#### ' + e })).join('\n') } function renderTides(tides) { return tides.map(function (e) { return '### ' + capitalize(e.location) + '\n' + e.tides.map(function (tide) { return '* ' + tide.height + 'm at ' + tide.time }).join('\n') }).join('\n\n') } function get(key, format, res, next) { db.sublevel('raw').get(key, function (err, value) { if(err) return next(err) if(value.forecast) //render a weather forecast res.end(render(value, format, function (e) { return [ '# ' + capitalize(value.name), 'issued at: [' + value.issued +'](/ls/'+value.name+')', '## Situation', e.situation, '## Forecast', sections(e.forecast), '## Outlook', sections(e.outlook), e.swell ? '## Swell\n\n' + e.swell : '', e.tides ? '## Tides\n\n' + renderTides(e.tides) : '', //oceanic forecasts e.warnings ? '## Warnings\n\n' + e.warnings.map(function (e) { return '### warning: '+e.name + ' (Analysis ' + e.analysis+')\n\n' + e.warning.replace(//g, '\n\n') + '\n\n issued at:' + e.issued }).join('\n\n') : '' ].join('\n') })) else if(value.imageData) res.end(render(value, format, function (e) { return e.imageData.map(function (e) { return '## ' + e.description + '\n\n' + '![e.description](http://metservice.com' + e.url + ')\n' + '\nissued at:' + e.issuedTime + ' valid from:' + e.validFromTime }).join('\n\n\n') })) }) } http.createServer(Stack( route(/^\/summary.json$/, function (req, res) { db.summary(function (err, data) { res.end(JSON.stringify(data, null, 2)) }) }), route(/^\/([0-9a-f]{64})(\.\w+)?$/, function (req, res, next) { get(req.params[0], req.params[1], res, next) }), route(/^\/([a-z\-_]+)(\.\w+)?$/, function (req, res, next) { db.get(req.params[0], function (err, value) { if(err) return next(err) get(value, req.params[1], res, next) }) }), route(/^\/ls\/([a-z\-_]+)(\.\w+)?$/, function (req, res, next) { var place = req.params[0] pull( pl.read(db.sublevel('sample'), {gte: [place, null], lt: [place, undefined], reverse: true}), pull.collect(function (err, data) { res.end(render(data, req.params[1], function (e) { return '# history for:' + capitalize(e[0].key[0]) + '\n\n' + e.map(function (e) { return '* [' + new Date(e.key[1]) + '](/'+e.value+')' }).join('\n') })) }) ) }), route(/^\/_admin\/update$/, function (req, res, next) { db.update(function (err, data) { if(err) return next(err) return res.end(JSON.stringify(data, null, 2)) }) }), route(/^\/(\.\w+)?$/, function (req, res) { res.end(render(Object.keys(urls), req.params[0], function (data) { return data.map(function (e) { return '* ['+e+'](/'+e+')' }).join('\n') })) }) )).listen(8000) //every hour, update. var HOUR = 1000*60*60, MIN = 1000*60 ;(function poll () { db.getLast(function (err, ts) { if(Date.now() > (+ts || 0) + HOUR) { console.log('updating...', Date.now() > ts + HOUR) db.update(function (err, data) { console.log(err, data) setTimeout(poll, MIN) }) } else { console.log('last update:', (Date.now() - ts)/MIN) console.log('next poll in:', (HOUR - (Date.now() - ts)) / MIN, 'minutes') setTimeout(poll, HOUR - (Date.now() - ts)) } }) })()