Files: e6ce43fadfd737b2a52d0225424c5eb186e6e6b3 / server.js
4485 bytesRaw
1 | |
2 | var http = require('http') |
3 | var Stack = require('stack') |
4 | var route = require('tiny-route') |
5 | var db = require('./db') |
6 | var pull = require('pull-stream') |
7 | var toPull = require('stream-to-pull-stream') |
8 | var pl = require('pull-level') |
9 | var stringify = require('pull-stringify') |
10 | var urls = require('./urls') |
11 | var marked = require('marked') |
12 | |
13 | function render(data, format, md) { |
14 | if(format === '.json') |
15 | return JSON.stringify(data, null, 2) + '\n\n' |
16 | if(format === '.md') return md(data) |
17 | return '<div id=content>'+marked(md(data))+'</div>' |
18 | } |
19 | |
20 | function capitalize (n) { |
21 | return n[0].toUpperCase() + n.substring(1).toLowerCase() |
22 | } |
23 | function log (e) { |
24 | console.log(e) |
25 | return e |
26 | } |
27 | |
28 | function sections (text) { |
29 | return log(text.split(/([\w,\s]+):/).map(function (e, i) { |
30 | if(!(i%2)) return e + '\n\n' |
31 | if(/\s/.test(e.trim())) return '### ' + e |
32 | else return '#### ' + e |
33 | })).join('\n') |
34 | } |
35 | |
36 | function renderTides(tides) { |
37 | return tides.map(function (e) { |
38 | return '### ' + capitalize(e.location) + '\n' + |
39 | e.tides.map(function (tide) { |
40 | return '* ' + tide.height + 'm at ' + tide.time |
41 | }).join('\n') |
42 | }).join('\n\n') |
43 | } |
44 | |
45 | function get(key, format, res, next) { |
46 | db.sublevel('raw').get(key, function (err, value) { |
47 | if(err) return next(err) |
48 | |
49 | if(value.forecast) //render a weather forecast |
50 | res.end(render(value, format, function (e) { |
51 | return [ |
52 | '# ' + capitalize(value.name), |
53 | 'issued at: [' + value.issued +'](/ls/'+value.name+')', |
54 | '## Situation', |
55 | e.situation, |
56 | '## Forecast', |
57 | sections(e.forecast), |
58 | '## Outlook', |
59 | sections(e.outlook), |
60 | e.swell ? '## Swell\n\n' + e.swell : '', |
61 | e.tides ? '## Tides\n\n' + renderTides(e.tides) : '', |
62 | //oceanic forecasts |
63 | e.warnings ? '## Warnings\n\n' + |
64 | e.warnings.map(function (e) { |
65 | return '### warning: '+e.name + ' (Analysis ' + e.analysis+')\n\n' + |
66 | e.warning.replace(/<br\/>/g, '\n\n') + '\n\n issued at:' + e.issued |
67 | }).join('\n\n') : '' |
68 | ].join('\n') |
69 | })) |
70 | else if(value.imageData) |
71 | res.end(render(value, format, function (e) { |
72 | return e.imageData.map(function (e) { |
73 | return '## ' + e.description + '\n\n' |
74 | + '![e.description](http://metservice.com' + e.url + ')\n' |
75 | + '\nissued at:' + e.issuedTime + ' valid from:' + e.validFromTime |
76 | }).join('\n\n\n') |
77 | })) |
78 | |
79 | }) |
80 | } |
81 | |
82 | http.createServer(Stack( |
83 | route(/^\/summary.json$/, function (req, res) { |
84 | db.summary(function (err, data) { |
85 | res.end(JSON.stringify(data, null, 2)) |
86 | }) |
87 | }), |
88 | route(/^\/([0-9a-f]{64})(\.\w+)?$/, function (req, res, next) { |
89 | get(req.params[0], req.params[1], res, next) |
90 | }), |
91 | route(/^\/([a-z\-_]+)(\.\w+)?$/, function (req, res, next) { |
92 | db.get(req.params[0], function (err, value) { |
93 | if(err) return next(err) |
94 | get(value, req.params[1], res, next) |
95 | }) |
96 | }), |
97 | route(/^\/ls\/([a-z\-_]+)(\.\w+)?$/, function (req, res, next) { |
98 | var place = req.params[0] |
99 | pull( |
100 | pl.read(db.sublevel('sample'), {gte: [place, null], lt: [place, undefined], reverse: true}), |
101 | pull.collect(function (err, data) { |
102 | res.end(render(data, req.params[1], function (e) { |
103 | return '# history for:' + capitalize(e[0].key[0]) + '\n\n' + |
104 | e.map(function (e) { |
105 | return '* [' + new Date(e.key[1]) + '](/'+e.value+')' |
106 | }).join('\n') |
107 | })) |
108 | }) |
109 | ) |
110 | }), |
111 | route(/^\/_admin\/update$/, function (req, res, next) { |
112 | db.update(function (err, data) { |
113 | if(err) return next(err) |
114 | return res.end(JSON.stringify(data, null, 2)) |
115 | }) |
116 | }), |
117 | route(/^\/(\.\w+)?$/, function (req, res) { |
118 | res.end(render(Object.keys(urls), req.params[0], function (data) { |
119 | return data.map(function (e) { |
120 | return '* ['+e+'](/'+e+')' |
121 | }).join('\n') |
122 | })) |
123 | }) |
124 | )).listen(8000) |
125 | |
126 | //every hour, update. |
127 | var HOUR = 1000*60*60, MIN = 1000*60 |
128 | |
129 | ;(function poll () { |
130 | db.getLast(function (err, ts) { |
131 | if(Date.now() > (+ts || 0) + HOUR) { |
132 | console.log('updating...', Date.now() > ts + HOUR) |
133 | db.update(function (err, data) { |
134 | console.log(err, data) |
135 | setTimeout(poll, MIN) |
136 | }) |
137 | } |
138 | else { |
139 | console.log('last update:', (Date.now() - ts)/MIN) |
140 | console.log('next poll in:', (HOUR - (Date.now() - ts)) / MIN, 'minutes') |
141 | setTimeout(poll, HOUR - (Date.now() - ts)) |
142 | } |
143 | }) |
144 | })() |
145 | |
146 | |
147 | |
148 | |
149 |
Built with git-ssb-web