This repository has been archived by the owner on Mar 17, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 32
/
index.js
124 lines (99 loc) · 4.78 KB
/
index.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
/*
* Weather
* For the full copyright and license information, please view the LICENSE.txt file.
*/
/* jslint node: true, sub: true */
'use strict';
var request = require('request'),
qs = require('querystring'),
xml2JS = require('xml2js');
// Init the module
module.exports = (function() {
var xmlParser = new xml2JS.Parser({charkey: 'C$', attrkey: 'A$', explicitArray: true}),
defLang = 'en-US',
defDegreeType = 'F',
defTimeout = 10000,
findUrl = 'http://weather.service.msn.com/find.aspx';
var find = function find(options, callback) {
if(typeof callback !== 'function')
callback = function callback(err, result) { return err || result; };
if(!options || typeof options !== 'object')
return callback('invalid options');
if(!options.search)
return callback('missing search input');
var result = [],
lang = options.lang || defLang,
degreeType = options.degreeType || defDegreeType,
timeout = options.timeout || defTimeout,
search = qs.escape(''+options.search),
reqUrl = findUrl + '?src=outlook&weadegreetype=' + (''+degreeType) + '&culture=' + (''+lang) + '&weasearchstr=' + search;
request.get({url: reqUrl, timeout: timeout}, function(err, res, body) {
if(err) return callback(err);
if(res.statusCode !== 200) return callback(new Error('request failed (' + res.statusCode + ')'));
if(!body) return callback(new Error('failed to get body content'));
// Check body content
if(body.indexOf('<') !== 0) {
if(body.search(/not found/i) !== -1) {
return callback(null, result);
}
return callback(new Error('invalid body content'));
}
// Parse body
xmlParser.parseString(body, function(err, resultJSON) {
if(err) return callback(err);
if(!resultJSON || !resultJSON.weatherdata || !resultJSON.weatherdata.weather)
return callback(new Error('failed to parse weather data'));
if(resultJSON.weatherdata.weather['A$'] && resultJSON.weatherdata.weather['A$'].errormessage)
return callback(resultJSON.weatherdata.weather['A$'].errormessage);
if(!(resultJSON.weatherdata.weather instanceof Array)) {
return callback(new Error('missing weather info'));
}
// Iterate over weather data
var weatherLen = resultJSON.weatherdata.weather.length,
weatherItem;
for(var i = 0; i < weatherLen; i++) {
if(typeof resultJSON.weatherdata.weather[i]['A$'] !== 'object')
continue;
// Init weather item
weatherItem = {
location: {
name: resultJSON.weatherdata.weather[i]['A$']['weatherlocationname'],
zipcode: resultJSON.weatherdata.weather[i]['A$']['zipcode'],
lat: resultJSON.weatherdata.weather[i]['A$']['lat'],
long: resultJSON.weatherdata.weather[i]['A$']['long'],
timezone: resultJSON.weatherdata.weather[i]['A$']['timezone'],
alert: resultJSON.weatherdata.weather[i]['A$']['alert'],
degreetype: resultJSON.weatherdata.weather[i]['A$']['degreetype'],
imagerelativeurl: resultJSON.weatherdata.weather[i]['A$']['imagerelativeurl']
//url: resultJSON.weatherdata.weather[i]['A$']['url'],
//code: resultJSON.weatherdata.weather[i]['A$']['weatherlocationcode'],
//entityid: resultJSON.weatherdata.weather[i]['A$']['entityid'],
//encodedlocationname: resultJSON.weatherdata.weather[i]['A$']['encodedlocationname']
},
current: null,
forecast: null
};
if(resultJSON.weatherdata.weather[i]['current'] instanceof Array && resultJSON.weatherdata.weather[i]['current'].length > 0) {
if(typeof resultJSON.weatherdata.weather[i]['current'][0]['A$'] === 'object') {
weatherItem.current = resultJSON.weatherdata.weather[i]['current'][0]['A$'];
weatherItem.current.imageUrl = weatherItem.location.imagerelativeurl + 'law/' + weatherItem.current.skycode + '.gif';
}
}
if(resultJSON.weatherdata.weather[i]['forecast'] instanceof Array) {
weatherItem.forecast = [];
for(var k = 0; k < resultJSON.weatherdata.weather[i]['forecast'].length; k++) {
if(typeof resultJSON.weatherdata.weather[i]['forecast'][k]['A$'] === 'object')
weatherItem.forecast.push(resultJSON.weatherdata.weather[i]['forecast'][k]['A$']);
}
}
// Push weather item into result
result.push(weatherItem);
}
return callback(null, result);
});
});
};
return {
find: find
};
})();