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 ;
 |