1 ! Copyright (C) 2007, 2010 Slava Pestov
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors calendar db db.tuples db.types furnace.actions
4 furnace.auth furnace.boilerplate furnace.recaptcha
5 furnace.redirection furnace.syndication html.forms
6 http.server.dispatchers http.server.responses kernel math.parser
7 sequences sorting urls validators xmode.catalog ;
10 TUPLE: pastebin < dispatcher ;
12 SYMBOL: can-delete-pastes?
14 can-delete-pastes? define-capability
20 TUPLE: entity id summary author mode date contents ;
24 { "id" "ID" INTEGER +db-assigned-id+ }
25 { "summary" "SUMMARY" { VARCHAR 256 } +not-null+ }
26 { "author" "AUTHOR" { VARCHAR 256 } +not-null+ }
27 { "mode" "MODE" { VARCHAR 256 } +not-null+ }
28 { "date" "DATE" DATETIME +not-null+ }
29 { "contents" "CONTENTS" TEXT +not-null+ }
32 GENERIC: entity-url ( entity -- url )
34 M: entity feed-entry-title summary>> ;
36 M: entity feed-entry-date date>> ;
38 M: entity feed-entry-url entity-url ;
40 TUPLE: paste-state < entity annotations ;
42 \ paste-state "PASTES" { } define-persistent
44 : <paste-state> ( id -- paste )
48 : pastes ( -- pastes )
49 f <paste-state> select-tuples
53 TUPLE: annotation < entity parent ;
55 \ annotation "ANNOTATIONS"
57 { "parent" "PARENT" INTEGER +not-null+ }
60 : <annotation> ( parent id -- annotation )
65 : lookup-annotation ( id -- annotation )
66 [ f ] dip <annotation> select-tuple ;
68 : paste ( id -- paste/f )
69 [ <paste-state> select-tuple ] keep over [
70 f <annotation> select-tuples >>annotations
77 CONSTANT: pastebin-url URL" $pastebin/"
79 : paste-url ( id -- url )
80 "$pastebin/paste" >url swap "id" set-query-param ;
82 M: paste-state entity-url
85 : annotation-url ( parent id -- url )
86 "$pastebin/paste" >url
87 swap number>string >>anchor
88 swap "id" set-query-param ;
90 M: annotation entity-url
91 [ parent>> ] [ id>> ] bi annotation-url ;
97 : <pastebin-action> ( -- action )
99 [ pastes "pastes" set-value ] >>init
100 { pastebin "pastebin" } >>template ;
102 : <pastebin-feed-action> ( -- action )
104 [ pastebin-url ] >>url
105 [ "Factor Pastebin" ] >>title
106 [ pastes ] >>entries ;
112 : <paste-action> ( -- action )
116 "id" value paste from-object
121 mode-names "modes" set-value
122 "factor" "mode" set-value
126 { pastebin "paste" } >>template ;
128 : <raw-paste-action> ( -- action )
130 [ validate-integer-id "id" value paste from-object ] >>init
131 [ "contents" value <text-content> ] >>display ;
133 : <paste-feed-action> ( -- action )
135 [ validate-integer-id ] >>init
136 [ "id" value paste-url ] >>url
137 [ "Paste " "id" value number>string append ] >>title
138 [ "id" value f <annotation> select-tuples ] >>entries ;
140 : validate-entity ( -- )
142 { "summary" [ v-one-line ] }
143 { "author" [ v-one-line ] }
144 { "mode" [ v-mode ] }
145 { "contents" [ v-required ] }
149 : deposit-entity-slots ( tuple -- )
151 { "summary" "author" "mode" "contents" } to-object ;
153 : <new-paste-action> ( -- action )
156 "factor" "mode" set-value
157 mode-names "modes" set-value
160 { pastebin "new-paste" } >>template
163 mode-names "modes" set-value
169 [ deposit-entity-slots ]
171 [ id>> paste-url <redirect> ]
175 : <delete-paste-action> ( -- action )
178 [ validate-integer-id ] >>validate
182 "id" value <paste-state> delete-tuples
183 "id" value f <annotation> delete-tuples
185 pastebin-url <redirect>
189 "delete pastes" >>description
190 { can-delete-pastes? } >>capabilities ;
196 : <new-annotation-action> ( -- action )
199 mode-names "modes" set-value
200 { { "parent" [ v-integer ] } } validate-params
205 "parent" value f <annotation>
206 [ deposit-entity-slots ]
208 [ entity-url <redirect> ]
212 : <raw-annotation-action> ( -- action )
214 [ validate-integer-id "id" value lookup-annotation from-object ] >>init
215 [ "contents" value <text-content> ] >>display ;
217 : <delete-annotation-action> ( -- action )
220 [ { { "id" [ v-number ] } } validate-params ] >>validate
223 f "id" value lookup-annotation
225 [ parent>> paste-url <redirect> ]
230 "delete annotations" >>description
231 { can-delete-pastes? } >>capabilities ;
233 : <pastebin> ( -- responder )
234 pastebin new-dispatcher
235 <pastebin-action> "" add-responder
236 <pastebin-feed-action> "list.atom" add-responder
237 <paste-action> "paste" add-responder
238 <raw-paste-action> "paste.txt" add-responder
239 <paste-feed-action> "paste.atom" add-responder
240 <new-paste-action> "new-paste" add-responder
241 <delete-paste-action> "delete-paste" add-responder
242 <new-annotation-action> "new-annotation" add-responder
243 <raw-annotation-action> "annotation.txt" add-responder
244 <delete-annotation-action> "delete-annotation" add-responder
246 { pastebin "pastebin-common" } >>template ;