! 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 sequences.lib 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-factor < dispatcher ; SYMBOL: can-administer-planet-factor? can-administer-planet-factor? define-capability TUPLE: planet-factor-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 : ( id -- todo ) blog new swap >>id ; : blogroll ( -- seq ) f select-tuples [ [ name>> ] compare ] sort ; : postings ( -- seq ) posting new select-tuples [ [ date>> ] compare invert-comparison ] sort ; : ( -- action ) [ blogroll "blogroll" set-value ] >>init { planet-factor "admin" } >>template ; : ( -- action ) [ blogroll "blogroll" set-value postings "postings" set-value ] >>init { planet-factor "planet" } >>template ; : ( -- action ) [ "Planet Factor" ] >>title [ URL" $planet-factor" ] >>url [ postings ] >>entries ; :: ( 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 [ '[ , ] 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 ; : ( -- action ) [ update-cached-postings URL" $planet-factor/admin" ] >>submit ; : ( -- action ) [ validate-integer-id ] >>validate [ "id" value delete-tuples URL" $planet-factor/admin" ] >>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 ; : ( -- action ) { planet-factor "new-blog" } >>template [ validate-blog ] >>validate [ f [ deposit-blog-slots ] [ insert-tuple ] [ "$planet-factor/admin/edit-blog" >>path swap id>> "id" set-query-param ] tri ] >>submit ; : ( -- action ) [ validate-integer-id "id" value select-tuple from-object ] >>init { planet-factor "edit-blog" } >>template [ validate-integer-id validate-blog ] >>validate [ f [ deposit-blog-slots ] [ update-tuple ] [ "$planet-factor/admin" >>path swap id>> "id" set-query-param ] tri ] >>submit ; : ( -- responder ) planet-factor-admin new-dispatcher "blogroll" add-main-responder "update" add-responder "new-blog" add-responder "edit-blog" add-responder "delete-blog" add-responder "administer Planet Factor" >>description { can-administer-planet-factor? } >>capabilities ; : ( -- responder ) planet-factor new-dispatcher "list" add-main-responder "feed.xml" add-responder "admin" add-responder { planet-factor "planet-common" } >>template ; : start-update-task ( db params -- ) '[ , , [ update-cached-postings ] with-db ] 10 minutes every drop ;