200 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Factor
		
	
	
		
			Executable File
		
	
			
		
		
	
	
			200 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Factor
		
	
	
		
			Executable File
		
	
| ! Copyright (C) 2008 Slava Pestov.
 | |
| ! See http://factorcode.org/license.txt for BSD license.
 | |
| USING: kernel accessors sequences sorting math math.order
 | |
| calendar alarms logging concurrency.combinators namespaces
 | |
| db.types db.tuples db fry locals hashtables
 | |
| syndication urls xml.writer validators
 | |
| html.forms
 | |
| html.components
 | |
| http.server
 | |
| http.server.dispatchers
 | |
| furnace
 | |
| furnace.actions
 | |
| furnace.redirection
 | |
| furnace.boilerplate
 | |
| furnace.auth.login
 | |
| furnace.auth
 | |
| furnace.syndication ;
 | |
| IN: webapps.planet
 | |
| 
 | |
| TUPLE: planet < dispatcher ;
 | |
| 
 | |
| SYMBOL: can-administer-planet?
 | |
| 
 | |
| can-administer-planet? define-capability
 | |
| 
 | |
| TUPLE: planet-admin < dispatcher ;
 | |
| 
 | |
| TUPLE: blog id name www-url feed-url ;
 | |
| 
 | |
| M: blog link-title name>> ;
 | |
| 
 | |
| M: blog link-href www-url>> ;
 | |
| 
 | |
| blog "BLOGS"
 | |
| {
 | |
|     { "id" "ID" INTEGER +db-assigned-id+ }
 | |
|     { "name" "NAME" { VARCHAR 256 } +not-null+ }
 | |
|     { "www-url" "WWWURL" URL +not-null+ }
 | |
|     { "feed-url" "FEEDURL" URL +not-null+ }
 | |
| } define-persistent
 | |
| 
 | |
| TUPLE: posting < entry id ;
 | |
| 
 | |
| posting "POSTINGS"
 | |
| {
 | |
|     { "id" "ID" INTEGER +db-assigned-id+ }
 | |
|     { "title" "TITLE" { VARCHAR 256 } +not-null+ }
 | |
|     { "url" "LINK" URL +not-null+ }
 | |
|     { "description" "DESCRIPTION" TEXT +not-null+ }
 | |
|     { "date" "DATE" TIMESTAMP +not-null+ }
 | |
| } define-persistent
 | |
| 
 | |
| : <blog> ( id -- todo )
 | |
|     blog new
 | |
|         swap >>id ;
 | |
| 
 | |
| : blogroll ( -- seq )
 | |
|     f <blog> select-tuples
 | |
|     [ [ name>> ] compare ] sort ;
 | |
| 
 | |
| : postings ( -- seq )
 | |
|     posting new select-tuples
 | |
|     [ [ date>> ] compare invert-comparison ] sort ;
 | |
| 
 | |
| : <edit-blogroll-action> ( -- action )
 | |
|     <page-action>
 | |
|         [ blogroll "blogroll" set-value ] >>init
 | |
|         { planet "admin" } >>template ;
 | |
| 
 | |
| : <planet-action> ( -- action )
 | |
|     <page-action>
 | |
|         [
 | |
|             blogroll "blogroll" set-value
 | |
|             postings "postings" set-value
 | |
|         ] >>init
 | |
| 
 | |
|         { planet "planet" } >>template ;
 | |
| 
 | |
| : <planet-feed-action> ( -- action )
 | |
|     <feed-action>
 | |
|         [ "Planet Factor" ] >>title
 | |
|         [ URL" $planet" ] >>url
 | |
|         [ postings ] >>entries ;
 | |
| 
 | |
| :: <posting> ( entry name -- entry' )
 | |
|     posting new
 | |
|         name ": " entry title>> 3append >>title
 | |
|         entry url>> >>url
 | |
|         entry description>> >>description
 | |
|         entry date>> >>date ;
 | |
| 
 | |
| : fetch-feed ( url -- feed )
 | |
|     download-feed entries>> ;
 | |
| 
 | |
| \ fetch-feed DEBUG add-error-logging
 | |
| 
 | |
| : fetch-blogroll ( blogroll -- entries )
 | |
|     [ [ feed-url>> fetch-feed ] parallel-map ] [ [ name>> ] map ] bi
 | |
|     [ '[ _ <posting> ] map ] 2map concat ;
 | |
| 
 | |
| : sort-entries ( entries -- entries' )
 | |
|     [ [ date>> ] compare invert-comparison ] sort ;
 | |
| 
 | |
| : update-cached-postings ( -- )
 | |
|     blogroll fetch-blogroll sort-entries 8 short head [
 | |
|         posting new delete-tuples
 | |
|         [ insert-tuple ] each
 | |
|     ] with-transaction ;
 | |
| 
 | |
| : <update-action> ( -- action )
 | |
|     <action>
 | |
|         [
 | |
|             update-cached-postings
 | |
|             URL" $planet/admin" <redirect>
 | |
|         ] >>submit ;
 | |
| 
 | |
| : <delete-blog-action> ( -- action )
 | |
|     <action>
 | |
|         [ validate-integer-id ] >>validate
 | |
| 
 | |
|         [
 | |
|             "id" value <blog> delete-tuples
 | |
|             URL" $planet/admin" <redirect>
 | |
|         ] >>submit ;
 | |
| 
 | |
| : validate-blog ( -- )
 | |
|     {
 | |
|         { "name" [ v-one-line ] }
 | |
|         { "www-url" [ v-url ] }
 | |
|         { "feed-url" [ v-url ] }
 | |
|     } validate-params ;
 | |
| 
 | |
| : deposit-blog-slots ( blog -- )
 | |
|     { "name" "www-url" "feed-url" } to-object ;
 | |
| 
 | |
| : <new-blog-action> ( -- action )
 | |
|     <page-action>
 | |
| 
 | |
|         { planet "new-blog" } >>template
 | |
| 
 | |
|         [ validate-blog ] >>validate
 | |
| 
 | |
|         [
 | |
|             f <blog>
 | |
|             [ deposit-blog-slots ]
 | |
|             [ insert-tuple ]
 | |
|             bi
 | |
|             URL" $planet/admin" <redirect>
 | |
|         ] >>submit ;
 | |
| 
 | |
| : <edit-blog-action> ( -- action )
 | |
|     <page-action>
 | |
| 
 | |
|         [
 | |
|             validate-integer-id
 | |
|             "id" value <blog> select-tuple from-object
 | |
|         ] >>init
 | |
| 
 | |
|         { planet "edit-blog" } >>template
 | |
| 
 | |
|         [
 | |
|             validate-integer-id
 | |
|             validate-blog
 | |
|         ] >>validate
 | |
| 
 | |
|         [
 | |
|             f <blog>
 | |
|             [ deposit-blog-slots ]
 | |
|             [ "id" value >>id ]
 | |
|             [ update-tuple ]
 | |
|             tri
 | |
| 
 | |
|             <url>
 | |
|                 "$planet/admin" >>path
 | |
|                 "id" value "id" set-query-param
 | |
|             <redirect>
 | |
|         ] >>submit ;
 | |
| 
 | |
| : <planet-admin> ( -- responder )
 | |
|     planet-admin new-dispatcher
 | |
|         <edit-blogroll-action> "" add-responder
 | |
|         <update-action> "update" add-responder
 | |
|         <new-blog-action> "new-blog" add-responder
 | |
|         <edit-blog-action> "edit-blog" add-responder
 | |
|         <delete-blog-action> "delete-blog" add-responder
 | |
|     <protected>
 | |
|         "administer Planet Factor" >>description
 | |
|         { can-administer-planet? } >>capabilities ;
 | |
| 
 | |
| : <planet> ( -- responder )
 | |
|     planet new-dispatcher
 | |
|         <planet-action> "" add-responder
 | |
|         <planet-feed-action> "feed.xml" add-responder
 | |
|         <planet-admin> "admin" add-responder
 | |
|     <boilerplate>
 | |
|         { planet "planet-common" } >>template ;
 | |
| 
 | |
| : start-update-task ( db -- )
 | |
|     '[ _ [ update-cached-postings ] with-db ] 10 minutes every drop ;
 |