forked from JulianNorton/weather-10kb-wxkb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathweather10kb.js
160 lines (134 loc) · 5.22 KB
/
weather10kb.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/* Opbeat has to be on top */
/* ~100 bytes additional on requests */
var opbeat = require('opbeat').start()
var express = require('express');
var forecastIo = require('./forecast-io.js')
var nodeFreegeoip = require('node-freegeoip')
var nodeGeocoder = require('node-geocoder')
var moment = require('moment-timezone')
var objectMerge = require('object-merge')
var timezone = require('google-timezone-api')
var router = express.Router();
function Weather10kbRequest(request) {
this.geocode = function() {
return new Promise(function(resolve, reject) {
if (typeof request.params.location === 'string') {
var geocoder = nodeGeocoder({
provider: 'google',
// Optional depending on the providers
httpAdapter: 'https', // Default
apiKey: process.env.GOOGLE_API_KEY,
formatter: null // 'gpx', 'string', ...
});
geocoder.geocode(request.params.location)
.then(function(res) {
if (res.length) {
request.params.latitude = res[0].latitude
request.params.longitude = res[0].longitude
request.params.formatted_location = res[0].formattedAddress
} else {
// TODO throw exception?
request.params.latitude = 0;
request.params.longitude = 0;
}
resolve();
})
.catch(function(err) {
return reject(err);
})
} else {
var ip = request.headers['x-forwarded-for'] ? request.headers['x-forwarded-for'].split(',')[0] : request.connection.remoteAddress
nodeFreegeoip.getLocation(ip, function(err, location) {
if (err) {
return reject(err);
}
if (location.latitude == 0 && location.longitude == 0) {
return reject(new Error("Unable to determine location based on IP address."));
}
request.params.latitude = location.latitude
request.params.longitude = location.longitude
// set the location to coordinates since that's all we have
request.params.location = request.params.latitude + ',' + request.params.longitude;
// something readable to display to the user
request.params.formatted_location = location.city + ', ' + location.region_code
resolve();
})
}
});
}
this.setTimeZone = function() {
return new Promise(function(resolve, reject) {
timezone({location: request.params.latitude + ',' + request.params.longitude})
.then(function(res) {
request.params.tz = res.timeZoneId
moment.tz.setDefault(request.params.tz)
resolve();
})
.catch(function(err) {
return reject(err);
});
});
}
this.getForecast = function() {
return new Promise(function(resolve, reject) {
var forecast = new forecastIo(process.env.FORECAST_IO_API_KEY);
var units = (typeof request.params.scale === 'string' && request.params.scale === 'C') ? 'si' : 'us'
forecast
.latitude(request.params.latitude)
.longitude(request.params.longitude)
.units(units)
.exclude('minutely,alerts,flags')
.get()
.then(function(res) {
resolve(res);
})
.catch(function(err) {
return reject(err);
});
});
}
}
router.get('/:location?/:scale?', function(request, response) {
// validate
(function() {
// check for & handle a querystring variable in case the user submitted the location form rather than passing a url param
if (typeof request.query.location === 'string') {
response.redirect('/' + request.query.location);
}
// if we got a scale and not a location for the first param, adjust params accordingly
if (typeof request.params.location === 'string' && request.params.location.toUpperCase() in ['C', 'F']) {
request.params.scale = request.params.location;
delete request.params.location;
}
if (typeof request.params.scale === 'string') {
request.params.scale = request.params.scale.toUpperCase();
} else {
request.params.scale = 'F';
}
request.params.units = (typeof request.params.scale === 'string' && request.params.scale === 'C') ? 'si' : 'us'
})();
var wr = new Weather10kbRequest(request);
wr.geocode()
.then(wr.setTimeZone)
.then(wr.getForecast)
.then(function(data) {
if (typeof request.params.formatted_location === 'undefined' || request.params.formatted_location == ', ') {
request.params.formatted_location = request.params.location;
}
// remove extraneous country info if present
request.params.formatted_location = request.params.formatted_location.replace(/, USA/, '')
if (request.params.longitude == 0 && request.params.latitude == 0) {
throw 'Undetermined location.';
}
response.render('pages/index', objectMerge(JSON.parse(data), {params: request.params}));
})
.catch(function(err){
if (err instanceof Error) {
var err_msg = err.toString();
} else {
var err_msg = JSON.stringify(err);
}
response.render('pages/error', {error: err_msg});
});
});
module.exports = router;