@@ -4,7 +4,6 @@ var xml2js = require('xml2js'),
4
4
request = require ( 'request' ) ,
5
5
URL = require ( 'url' ) ,
6
6
iconv = require ( 'iconv-lite' ) ;
7
-
8
7
/**
9
8
All you need to do is send a feed URL that can be opened via fs
10
9
Options are optional, see xml2js for extensive list
@@ -17,13 +16,19 @@ function parseURL(feedURL, options, callback) {
17
16
callback = options ;
18
17
options = { } ;
19
18
}
20
- var defaults = { uri : feedURL , jar : false , proxy : false , followRedirect : true , timeout : 1000 * 30 } ;
19
+ var defaults = {
20
+ uri : feedURL ,
21
+ jar : false ,
22
+ proxy : false ,
23
+ followRedirect : true ,
24
+ timeout : 1000 * 30
25
+ } ;
21
26
options = _ . extend ( defaults , options ) ;
22
27
//check that the protocal is either http or https
23
28
var u = URL . parse ( feedURL ) ;
24
29
if ( u . protocol === 'http:' || u . protocol === 'https:' ) {
25
30
//make sure to have a 30 second timeout
26
- var req = request ( options , function ( err , response , xml ) {
31
+ var req = request ( options , function ( err , response , xml ) {
27
32
if ( err || xml === null ) {
28
33
if ( err ) {
29
34
callback ( err , null ) ;
@@ -32,29 +37,35 @@ function parseURL(feedURL, options, callback) {
32
37
}
33
38
} else {
34
39
if ( ( typeof response !== "undefined" && response !== null ? response . statusCode : void 0 ) != null ) {
35
- if ( response . statusCode >= 400 ) {
36
- callback ( "Failed to retrieve source! Invalid response code (" + response . statusCode + ")!" , null ) ;
37
- } else {
38
- var encodedXml = iconv . decode ( new Buffer ( xml ) , 'ISO-8859-1' ) ;
39
- parseString ( encodedXml , options , callback ) ;
40
- //issues22
41
- }
40
+ if ( response . statusCode >= 400 ) {
41
+ callback ( "Failed to retrieve source! Invalid response code (" + response . statusCode + ")!" , null ) ;
42
+ } else {
43
+ var encodedXml = iconv . decode ( new Buffer ( xml ) , 'ISO-8859-1' ) ;
44
+ parseString ( encodedXml , options , callback ) ;
45
+ //issues22
46
+ }
42
47
} else {
43
- callback ( "Failed to retrieve source! No response code!!" , null ) ;
48
+ callback ( "Failed to retrieve source! No response code!!" , null ) ;
44
49
}
45
50
}
46
51
} ) ;
47
52
} else {
48
- callback ( { error : "Only http or https protocols are accepted" } , null ) ;
53
+ callback ( {
54
+ error : "Only http or https protocols are accepted"
55
+ } , null ) ;
49
56
}
50
57
}
51
58
module . exports . parseURL = parseURL ;
52
59
53
60
function parseString ( xml , options , callback ) {
54
61
// we need to check that the input in not a null input
55
62
if ( xml . split ( '<' ) . length >= 3 ) {
56
- var parser = new xml2js . Parser ( { trim : false , normalize : true , mergeAttrs : true } ) ;
57
- parser . addListener ( 'end' , function ( jsonDOM ) {
63
+ var parser = new xml2js . Parser ( {
64
+ trim : false ,
65
+ normalize : true ,
66
+ mergeAttrs : true
67
+ } ) ;
68
+ parser . addListener ( 'end' , function ( jsonDOM ) {
58
69
if ( jsonDOM ) {
59
70
//console.log(jsonDOM.rss.channel[0]);
60
71
jsonDOM = normalize ( jsonDOM ) ;
@@ -69,7 +80,7 @@ function parseString(xml, options, callback) {
69
80
callback ( "failed to parse xml" , null ) ;
70
81
}
71
82
} ) ;
72
- parser . addListener ( "error" , function ( err ) {
83
+ parser . addListener ( "error" , function ( err ) {
73
84
callback ( err , null ) ;
74
85
} ) ;
75
86
parser . parseString ( xml ) ;
@@ -78,20 +89,17 @@ function parseString(xml, options, callback) {
78
89
}
79
90
}
80
91
module . exports . parseString = parseString ;
81
-
82
92
//detects if RSS, otherwise assume atom
83
93
function isRSS ( json ) {
84
94
return ( json . channel != null ) ;
85
95
}
86
-
87
96
// normalizes input to make feed burner work
88
97
function normalize ( json ) {
89
98
if ( json . rss ) {
90
99
return json . rss ;
91
100
}
92
101
return json ;
93
102
}
94
-
95
103
//xml2js will return commented material in a # tag which can be a pain
96
104
//this will remove the # tag and set its child text in it's place
97
105
//ment to work on a feed item, so will iterate over json's and check
@@ -103,17 +111,17 @@ function flattenComments(json) {
103
111
}
104
112
return json ;
105
113
}
106
-
107
114
//formats the RSS feed to the needed outpu
108
115
//also parses FeedBurner
109
116
function formatRSS ( json ) {
110
- var output = { 'type' : 'rss' , items : [ ] } ;
117
+ var output = {
118
+ 'type' : 'rss' ,
119
+ items : [ ]
120
+ } ;
111
121
var channel = json . channel ;
112
-
113
122
if ( _ . isArray ( json . channel ) ) {
114
123
channel = json . channel [ 0 ] ;
115
124
}
116
-
117
125
if ( channel . title ) {
118
126
output . title = channel . title [ 0 ] ;
119
127
}
@@ -138,21 +146,18 @@ function formatRSS(json) {
138
146
if ( ! _ . isArray ( channel . item ) ) {
139
147
channel . item = [ channel . item ] ;
140
148
}
141
- _ . each ( channel . item , function ( val , index ) {
149
+ _ . each ( channel . item , function ( val , index ) {
142
150
val = flattenComments ( val ) ;
143
151
var obj = { } , _ref ;
144
152
//Tx PaulFreund
145
- obj . title = ( _ref = val . title ) != undefined && _ref . length > 0 ? _ref [ 0 ] : void 0 ;
146
- obj . summary = ( _ref = val . description ) != undefined && _ref . length > 0 ? _ref [ 0 ] : void 0 ;
147
- obj . url = ( _ref = val . link ) != undefined && _ref . length > 0 ? _ref [ 0 ] : void 0 ;
148
- obj . categories = ( _ref = val . category ) != undefined && _ref . length > 0 ? _ref [ 0 ] : void 0 ;
149
-
150
-
153
+ obj . title = ( _ref = val . title ) != undefined && _ref . length > 0 ? _ref [ 0 ] : void 0 ;
154
+ obj . summary = ( _ref = val . description ) != undefined && _ref . length > 0 ? _ref [ 0 ] : void 0 ;
155
+ obj . url = ( _ref = val . link ) != undefined && _ref . length > 0 ? _ref [ 0 ] : void 0 ;
156
+ obj . categories = ( _ref = val . category ) != undefined && _ref . length > 0 ? _ref [ 0 ] : void 0 ;
151
157
// Put the comments instead of the description if there is no description
152
158
if ( ! ( obj . summary != null ) || obj . summary === '' ) {
153
- obj . summary = val . comments [ 0 ] != null ? val . comments [ 0 ] : '' ;
159
+ obj . summary = ( _ref = val . comments [ 0 ] ) ? _ref : '' ;
154
160
}
155
-
156
161
//since we are going to format the date, we want to make sure it exists
157
162
if ( val . pubDate ) {
158
163
//lets try basis js date parsing for now
@@ -163,20 +168,20 @@ function formatRSS(json) {
163
168
if ( val [ 'dc:creator' ] ) {
164
169
obj . author = val [ 'dc:creator' ] [ 0 ] ;
165
170
}
166
-
167
171
if ( val . author ) {
168
172
obj . author = val . author [ 0 ] ;
169
173
}
170
-
171
174
//now lets handle the GUID
172
175
if ( val . guid ) {
173
176
//xml2js parses this kina odd...
174
177
var link = val . guid [ 0 ] . _ ;
175
178
var param = val . guid [ 0 ] . isPermaLink ;
176
179
var isPermaLink = true ;
177
- obj . guid = { 'link' : link , isPermaLink : param } ;
180
+ obj . guid = {
181
+ 'link' : link ,
182
+ isPermaLink : param
183
+ } ;
178
184
}
179
-
180
185
if ( val [ 'media:content' ] ) {
181
186
obj . media = val . media || { } ;
182
187
obj . media . content = val [ 'media:content' ] ;
@@ -185,19 +190,19 @@ function formatRSS(json) {
185
190
obj . media = val . media || { } ;
186
191
obj . media . thumbnail = val [ 'media:thumbnail' ] ;
187
192
}
188
-
189
193
//now push the obj onto the stack
190
194
output . items . push ( obj ) ;
191
195
} ) ;
192
196
}
193
197
return output ;
194
198
}
195
-
196
199
//formats the ATOM feed to the needed output
197
200
function formatATOM ( json ) {
198
- var output = { 'type' : 'atom' , items : [ ] } ;
201
+ var output = {
202
+ 'type' : 'atom' ,
203
+ items : [ ]
204
+ } ;
199
205
var channel = json . feed || json ;
200
-
201
206
if ( channel . title ) {
202
207
output . title = channel . title [ 0 ] . _ ;
203
208
}
@@ -209,11 +214,9 @@ function formatATOM(json) {
209
214
} else {
210
215
output . desc = channel . subtitle ;
211
216
}
212
-
213
217
if ( channel . link )
214
218
if ( _ . isArray ( channel . link ) ) {
215
- _ . each ( channel . link , function ( val , index ) {
216
-
219
+ _ . each ( channel . link , function ( val , index ) {
217
220
if ( val . type && val . type . indexOf ( "html" ) > 0 ) {
218
221
output . link = val . href ;
219
222
}
@@ -222,36 +225,31 @@ function formatATOM(json) {
222
225
}
223
226
} ) ;
224
227
}
225
-
226
228
if ( channel . id ) {
227
229
output . id = channel . id [ 0 ] ;
228
230
}
229
-
230
231
if ( channel . updated ) {
231
232
output . last_modified = new Date ( channel . updated [ 0 ] ) . toString ( ) ;
232
233
}
233
-
234
234
if ( channel . author ) {
235
235
output . author = channel . author [ 0 ] . name [ 0 ] ;
236
236
}
237
-
238
237
//just double check that it exists and that it is an array
239
238
if ( channel . entry ) {
240
239
if ( ! _ . isArray ( channel . entry ) ) {
241
240
channel . entry = [ channel . entry ] ;
242
241
}
243
- _ . each ( channel . entry , function ( val , index ) {
242
+ _ . each ( channel . entry , function ( val , index ) {
244
243
val = flattenComments ( val ) ;
245
244
var obj = { } , _ref ;
246
245
obj . id = val . id [ 0 ] ;
247
- obj . title = ( _ref = val . title ) != undefined && _ref . length > 0 ? _ref [ 0 ] . _ : void 0 ;
248
- obj . summary = ( _ref = val . content [ 0 ] ) != undefined && _ref . length > 0 ? _ref [ 0 ] . _ : void 0 ;
249
-
246
+ obj . title = ( _ref = val . title ) != undefined && _ref . length > 0 ? _ref [ 0 ] . _ : void 0 ;
247
+ obj . summary = ( _ref = val . content [ 0 ] ) != undefined && _ref . length > 0 ? _ref [ 0 ] . _ : void 0 ;
250
248
var categories = [ ] ;
251
249
//just grab the category text
252
250
if ( val . category ) {
253
251
if ( _ . isArray ( val . category ) ) {
254
- _ . each ( val . category , function ( val , i ) {
252
+ _ . each ( val . category , function ( val , i ) {
255
253
categories . push ( val [ 'term' ] ) ;
256
254
} ) ;
257
255
} else {
@@ -263,7 +261,7 @@ function formatATOM(json) {
263
261
//just get the alternate link
264
262
if ( val . link ) {
265
263
if ( _ . isArray ( val . link ) ) {
266
- _ . each ( val . link , function ( val , i ) {
264
+ _ . each ( val . link , function ( val , i ) {
267
265
if ( val . rel === 'self' ) {
268
266
link = val . href ;
269
267
}
@@ -279,7 +277,6 @@ function formatATOM(json) {
279
277
obj . published_at = Date . parse ( val . published [ 0 ] ) ;
280
278
obj . time_ago = DateHelper . time_ago_in_words ( obj . published_at ) ;
281
279
}
282
-
283
280
if ( val [ 'media:content' ] ) {
284
281
obj . media = val . media || { } ;
285
282
obj . media . content = val [ 'media:content' ] ;
@@ -294,22 +291,20 @@ function formatATOM(json) {
294
291
}
295
292
return output ;
296
293
}
297
-
298
294
var DateHelper = {
299
295
// Takes the format of "Jan 15, 2007 15:45:00 GMT" and converts it to a relative time
300
296
// Ruby strftime: %b %d, %Y %H:%M:%S GMT
301
- time_ago_in_words_with_parsing : function ( from ) {
297
+ time_ago_in_words_with_parsing : function ( from ) {
302
298
var date = new Date ( ) ;
303
299
date . setTime ( Date . parse ( from ) ) ;
304
300
return this . time_ago_in_words ( date ) ;
305
301
} ,
306
302
// Takes a timestamp and converts it to a relative time
307
303
// DateHelper.time_ago_in_words(1331079503000)
308
- time_ago_in_words : function ( from ) {
304
+ time_ago_in_words : function ( from ) {
309
305
return this . distance_of_time_in_words ( new Date ( ) , from ) ;
310
306
} ,
311
-
312
- distance_of_time_in_words : function ( to , from ) {
307
+ distance_of_time_in_words : function ( to , from ) {
313
308
var distance_in_seconds = ( ( to - from ) / 1000 ) ;
314
309
var distance_in_minutes = Math . floor ( distance_in_seconds / 60 ) ;
315
310
var tense = distance_in_seconds < 0 ? " from now" : " ago" ;
@@ -346,5 +341,4 @@ var DateHelper = {
346
341
}
347
342
return 'over ' + Math . floor ( distance_in_minutes / 525960 ) + ' years' ;
348
343
}
349
- } ;
350
-
344
+ } ;
0 commit comments