! Copyright (C) 2007, 2008 Slava Pestov ! See http://factorcode.org/license.txt for BSD license. USING: namespaces assocs sorting sequences kernel accessors hashtables sequences.lib db.types db.tuples db combinators calendar calendar.format math.parser rss urls xml.writer xmode.catalog validators html.components html.templates.chloe http.server http.server.dispatchers http.server.redirection furnace furnace.actions furnace.auth furnace.auth.login furnace.boilerplate furnace.rss ; IN: webapps.pastebin TUPLE: pastebin < dispatcher ; ! ! ! ! DOMAIN MODEL ! ! ! TUPLE: entity id summary author mode date contents ; entity f { { "id" "ID" INTEGER +db-assigned-id+ } { "summary" "SUMMARY" { VARCHAR 256 } +not-null+ } { "author" "AUTHOR" { VARCHAR 256 } +not-null+ } { "mode" "MODE" { VARCHAR 256 } +not-null+ } { "date" "DATE" DATETIME +not-null+ } { "contents" "CONTENTS" TEXT +not-null+ } } define-persistent TUPLE: paste < entity annotations ; \ paste "PASTES" { } define-persistent : ( id -- paste ) \ paste new swap >>id ; : pastes ( -- pastes ) f select-tuples ; TUPLE: annotation < entity parent ; annotation "ANNOTATIONS" { { "parent" "PARENT" INTEGER +not-null+ } } define-persistent : ( parent id -- annotation ) annotation new swap >>id swap >>parent ; : fetch-annotations ( paste -- paste ) dup annotations>> [ dup id>> f select-tuples >>annotations ] unless ; : paste ( id -- paste ) select-tuple fetch-annotations ; ! ! ! ! LINKS, ETC ! ! ! : pastebin-link ( -- url ) URL" $pastebin/list" ; GENERIC: entity-link ( entity -- url ) : paste-link ( id -- url ) "$pastebin/paste" >>path swap "id" set-query-param ; M: paste entity-link id>> paste-link ; : annotation-link ( parent id -- url ) "$pastebin/paste" >>path swap number>string >>anchor swap "id" set-query-param ; M: annotation entity-link [ parent>> ] [ id>> ] bi annotation-link ; ! ! ! ! PASTE LIST ! ! ! : ( -- action ) [ pastes "pastes" set-value ] >>init { pastebin "pastebin" } >>template ; : pastebin-feed-entries ( seq -- entries ) 20 short head [ entry new swap [ summary>> >>title ] [ date>> >>pub-date ] [ entity-link adjust-url relative-to-request >>link ] tri ] map ; : pastebin-feed ( -- feed ) feed new "Factor Pastebin" >>title pastebin-link >>link pastes pastebin-feed-entries >>entries ; : ( -- action ) [ pastebin-feed ] >>feed ; ! ! ! ! PASTES ! ! ! : ( -- action ) [ validate-integer-id "id" value paste from-object "id" value "new-annotation" [ "id" set-value mode-names "modes" set-value "factor" "mode" set-value ] nest-values ] >>init { pastebin "paste" } >>template ; : paste-feed-entries ( paste -- entries ) fetch-annotations annotations>> pastebin-feed-entries ; : paste-feed ( paste -- feed ) feed new swap [ "Paste " swap id>> number>string append >>title ] [ entity-link adjust-url relative-to-request >>link ] [ paste-feed-entries >>entries ] tri ; : ( -- action ) [ validate-integer-id ] >>init [ "id" value paste paste-feed ] >>feed ; : validate-entity ( -- ) { { "summary" [ v-one-line ] } { "author" [ v-one-line ] } { "mode" [ v-mode ] } { "contents" [ v-required ] } { "captcha" [ v-captcha ] } } validate-params ; : deposit-entity-slots ( tuple -- ) now >>date { "summary" "author" "mode" "contents" } deposit-slots ; : ( -- action ) [ "factor" "mode" set-value mode-names "modes" set-value ] >>init { pastebin "new-paste" } >>template [ mode-names "modes" set-value ] >>validate [ validate-entity f [ deposit-entity-slots ] [ insert-tuple ] [ id>> paste-link ] tri ] >>submit ; : ( -- action ) [ validate-integer-id ] >>validate [ "id" value delete-tuples "id" value f delete-tuples URL" $pastebin/list" ] >>submit ; ! ! ! ! ANNOTATIONS ! ! ! : ( -- action ) [ { { "id" [ v-integer ] } } validate-params "id" value paste-link ] >>display [ { { "id" [ v-integer ] } } validate-params validate-entity ] >>validate [ "id" value f [ deposit-entity-slots ] [ insert-tuple ] [ entity-link ] tri ] >>submit ; : ( -- action ) [ { { "id" [ v-number ] } } validate-params ] >>validate [ f "id" value select-tuple [ delete-tuples ] [ parent>> paste-link ] bi ] >>submit ; SYMBOL: can-delete-pastes? can-delete-pastes? define-capability : ( -- responder ) pastebin new-dispatcher "list" add-main-responder "list.atom" add-responder "paste" add-responder "paste.atom" add-responder "new-paste" add-responder { can-delete-pastes? } "delete-paste" add-responder "new-annotation" add-responder { can-delete-pastes? } "delete-annotation" add-responder { pastebin "pastebin-common" } >>template ; : init-pastes-table \ paste ensure-table ; : init-annotations-table annotation ensure-table ;