98 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Factor
		
	
	
			
		
		
	
	
			98 lines
		
	
	
		
			3.0 KiB
		
	
	
	
		
			Factor
		
	
	
| ! Copyright (C) 2006 Chris Double.
 | |
| ! See http://factorcode.org/license.txt for BSD license.
 | |
| IN: rss
 | |
| ! USING: kernel http-client xml xml-utils xml-data errors io strings
 | |
| !    sequences xml-writer parser-combinators lazy-lists entities ;
 | |
| USING: xml.utilities kernel promises parser-combinators assocs
 | |
|     parser-combinators.replace strings sequences xml.data xml.writer
 | |
|     io.streams.string combinators xml xml.entities io.files io
 | |
|     http.client ;
 | |
| 
 | |
| : ?children>string ( tag/f -- string/f )
 | |
|     [ children>string ] [ f ] if* ;
 | |
| 
 | |
| LAZY: '&' ( -- parser )
 | |
|     "&" token
 | |
|     [ blank? ] satisfy &>
 | |
|     [ "&" swap add ] <@ ;
 | |
| 
 | |
| : &>& ( string -- string )
 | |
|     '&' replace ;
 | |
| 
 | |
| TUPLE: feed title link entries ;
 | |
| 
 | |
| C: <feed> feed
 | |
| 
 | |
| TUPLE: entry title link description pub-date ;
 | |
| 
 | |
| C: <entry> entry
 | |
| 
 | |
| : rss1.0 ( xml -- feed )
 | |
|     [
 | |
|         "channel" tag-named
 | |
|         [ "title" tag-named children>string ] keep
 | |
|         "link" tag-named children>string
 | |
|     ] keep
 | |
|     "item" tags-named [
 | |
|         [ "title" tag-named children>string ] keep   
 | |
|         [ "link" tag-named children>string ] keep
 | |
|         [ "description" tag-named children>string ] keep
 | |
|         f "date" "http://purl.org/dc/elements/1.1/" <name>
 | |
|         tag-named ?children>string
 | |
|         <entry>
 | |
|     ] map <feed> ;
 | |
| 
 | |
| : rss2.0 ( xml -- feed )
 | |
|     "channel" tag-named 
 | |
|     [ "title" tag-named children>string ] keep
 | |
|     [ "link" tag-named children>string ] keep
 | |
|     "item" tags-named [
 | |
|         [ "title" tag-named children>string ] keep
 | |
|         [ "link" tag-named ] keep
 | |
|         [ "guid" tag-named dupd ? children>string ] keep
 | |
|         [ "description" tag-named children>string ] keep
 | |
|         "pubDate" tag-named children>string <entry>
 | |
|     ] map <feed> ;
 | |
| 
 | |
| : atom1.0 ( xml -- feed )
 | |
|     [ "title" tag-named children>string ] keep
 | |
|     [ "link" tag-named "href" swap at ] keep
 | |
|     "entry" tags-named [
 | |
|         [ "title" tag-named children>string ] keep
 | |
|         [ "link" tag-named "href" swap at ] keep
 | |
|         [
 | |
|             dup "content" tag-named
 | |
|             [ nip ] [ "summary" tag-named ] if*
 | |
|             dup tag-children [ tag? ] contains?
 | |
|             [ tag-children [ write-chunk ] string-out ]
 | |
|             [ children>string ] if
 | |
|         ] keep
 | |
|         dup "published" tag-named
 | |
|         [ nip ] [ "updated" tag-named ] if*
 | |
|         children>string <entry>
 | |
|     ] map <feed> ;
 | |
| 
 | |
| : feed ( xml -- feed )
 | |
|     dup name-tag {
 | |
|         { "RDF" [ rss1.0 ] }
 | |
|         { "rss" [ rss2.0 ] }
 | |
|         { "feed" [ atom1.0 ] }
 | |
|     } case ;
 | |
| 
 | |
| : read-feed ( string -- feed )
 | |
|     ! &>& ! this will be uncommented when parser-combinators are fixed
 | |
|     [ string>xml ] with-html-entities feed ;
 | |
| 
 | |
| : load-news-file ( filename -- feed )
 | |
|     #! Load an news syndication file and process it, returning
 | |
|     #! it as an feed tuple.
 | |
|     <file-reader> [ contents read-feed ] keep stream-close ;
 | |
| 
 | |
| : news-get ( url -- feed )
 | |
|     #! Retrieve an news syndication file, return as a feed tuple.
 | |
|     http-get rot 200 = [
 | |
|         nip read-feed
 | |
|     ] [
 | |
|         2drop "Error retrieving newsfeed file" throw
 | |
|     ] if ;
 |