! Copyright (C) 2008, 2010 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. USING: kernel accessors sequences sorting math math.order calendar timers logging concurrency.combinators namespaces db.types db.tuples db fry locals hashtables continuations syndication urls xml.writer validators html.forms html.components http.server http.server.dispatchers http.server.static furnace furnace.actions furnace.redirection furnace.boilerplate furnace.auth.login furnace.auth furnace.syndication syndication.pubsubhubbub ; 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 CONSTANT: hubs { { URL" http://pubsubhubbub.appspot.com/" URL" http://pubsubhubbub.appspot.com/publish" } } : ( id -- todo ) blog new swap >>id ; : blogroll ( -- seq ) f select-tuples [ name>> ] sort-with ; : sort-postings ( seq -- seq ) [ date>> ] inv-sort-with ; : postings ( -- seq ) posting new select-tuples sort-postings ; : ( -- action ) [ blogroll "blogroll" set-value ] >>init { planet "admin" } >>template ; : ( -- action ) [ blogroll "blogroll" set-value postings "postings" set-value ] >>init { planet "planet" } >>template ; : hubs-urls ( -- seq ) hubs [ first ] map ; : ping-hubs ( -- ) { URL" http://planet.factorcode.org/feed.xml" } hubs [ second ] map [ [ ping ] [ 3drop ] recover ] with each ; : ( -- action ) [ "Planet Factor" ] >>title [ URL" $planet" ] >>url [ hubs-urls ] >>hubs [ 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>> ] inv-sort-with ; : set-cached-postings ( seq -- ) [ posting new delete-tuples [ insert-tuple ] each ] with-transaction ; : update-cached-postings ( -- ) blogroll fetch-blogroll sort-entries 8 short head sort-postings dup postings = [ drop ] [ set-cached-postings ping-hubs ] if ; : ( -- action ) [ update-cached-postings URL" $planet/admin" ] >>submit ; : ( -- action ) [ validate-integer-id ] >>validate [ "id" value delete-tuples URL" $planet/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 "new-blog" } >>template [ validate-blog ] >>validate [ f [ deposit-blog-slots ] [ insert-tuple ] bi URL" $planet/admin" ] >>submit ; : ( -- action ) [ validate-integer-id "id" value select-tuple from-object ] >>init { planet "edit-blog" } >>template [ validate-integer-id validate-blog ] >>validate [ f [ deposit-blog-slots ] [ "id" value >>id update-tuple ] bi "$planet/admin" >>path "id" value "id" set-query-param ] >>submit ; : ( -- responder ) planet-admin new-dispatcher "" add-responder "update" add-responder "new-blog" add-responder "edit-blog" add-responder "delete-blog" add-responder "administer Planet Factor" >>description { can-administer-planet? } >>capabilities ; : ( -- responder ) planet new-dispatcher "" add-responder "feed.xml" add-responder "admin" add-responder "vocab:webapps/planet/icons/" "icons" add-responder { planet "planet-common" } >>template ; : start-update-task ( db -- ) '[ "webapps.planet" [ _ [ update-cached-postings ] with-db ] with-logging ] 10 minutes every drop ;