1 ! Copyright (C) 2007, 2010, 2023 Slava Pestov, Raghu Ranganathan.
2 ! See https://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 furnace.utilities
6 html.forms http.server.dispatchers http.server.responses kernel
7 math.parser namespaces present sequences smtp sorting splitting
8 urls validators xmode.catalog literals ;
11 TUPLE: pastebin < dispatcher ;
13 SYMBOL: can-delete-pastes?
15 SYMBOL: pastebin-email-from
16 SYMBOL: pastebin-email-to
18 CONSTANT: paste-mode-names $[ "text" mode-names remove "text" prefix ]
20 can-delete-pastes? define-capability
26 TUPLE: entity id summary author mode date contents ;
30 { "id" "ID" INTEGER +db-assigned-id+ }
31 { "summary" "SUMMARY" { VARCHAR 256 } +not-null+ }
32 { "author" "AUTHOR" { VARCHAR 256 } +not-null+ }
33 { "mode" "MODE" { VARCHAR 256 } +not-null+ }
34 { "date" "DATE" DATETIME +not-null+ }
35 { "contents" "CONTENTS" TEXT +not-null+ }
38 GENERIC: entity-url ( entity -- url )
40 M: entity feed-entry-title summary>> ;
42 M: entity feed-entry-date date>> ;
44 M: entity feed-entry-url entity-url ;
46 TUPLE: paste-state < entity annotations ;
48 \ paste-state "PASTES" { } define-persistent
50 : <paste-state> ( id -- paste )
54 : pastes ( -- pastes )
55 f <paste-state> select-tuples
59 TUPLE: annotation < entity parent ;
61 \ annotation "ANNOTATIONS"
63 { "parent" "PARENT" INTEGER +not-null+ }
66 : <annotation> ( parent id -- annotation )
71 : lookup-annotation ( id -- annotation )
72 [ f ] dip <annotation> select-tuple ;
74 : paste ( id -- paste/f )
75 [ <paste-state> select-tuple ] keep over [
76 f <annotation> select-tuples >>annotations
83 CONSTANT: pastebin-url URL" $pastebin/"
85 : paste-url ( id -- url )
86 "$pastebin/paste" >url swap "id" set-query-param ;
88 M: paste-state entity-url
91 : annotation-url ( parent id -- url )
92 "$pastebin/paste" >url
93 swap number>string >>anchor
94 swap "id" set-query-param ;
96 M: annotation entity-url
97 [ parent>> ] [ id>> ] bi annotation-url ;
103 : <pastebin-action> ( -- action )
105 [ pastes "pastes" set-value ] >>init
106 { pastebin "pastebin" } >>template ;
108 : <pastebin-feed-action> ( -- action )
110 [ pastebin-url ] >>url
111 [ "Factor Pastebin" ] >>title
112 [ pastes ] >>entries ;
119 : <paste-action> ( -- action )
123 "id" value paste from-object
128 paste-mode-names "modes" set-value
129 "factor" "mode" set-value
133 { pastebin "paste" } >>template ;
135 : <raw-paste-action> ( -- action )
137 [ validate-integer-id "id" value paste from-object ] >>init
138 [ "contents" value <text-content> ] >>display ;
140 : <paste-feed-action> ( -- action )
142 [ validate-integer-id ] >>init
143 [ "id" value paste-url ] >>url
144 [ "Paste " "id" value number>string append ] >>title
145 [ "id" value f <annotation> select-tuples ] >>entries ;
147 : validate-entity ( -- )
149 { "summary" [ v-one-line ] }
150 { "author" [ v-one-line ] }
151 { "mode" [ v-mode ] }
152 { "contents" [ v-required ] }
156 : deposit-entity-slots ( tuple -- )
158 { "summary" "author" "mode" "contents" } to-object ;
160 : email-on-paste ( url -- )
161 pastebin-email-to get-global [
166 swap adjust-url present >>body
167 pastebin-email-from get-global >>from
168 "New paste!" >>subject
172 : <new-paste-action> ( -- action )
175 "factor" "mode" set-value
176 paste-mode-names "modes" set-value
179 { pastebin "new-paste" } >>template
182 paste-mode-names "modes" set-value
188 [ deposit-entity-slots ]
190 [ id>> paste-url [ email-on-paste ] [ <redirect> ] bi ]
194 : <delete-paste-action> ( -- action )
197 [ validate-integer-id ] >>validate
201 "id" value <paste-state> delete-tuples
202 "id" value f <annotation> delete-tuples
204 pastebin-url <redirect>
208 "delete pastes" >>description
209 { can-delete-pastes? } >>capabilities ;
215 : <new-annotation-action> ( -- action )
218 paste-mode-names "modes" set-value
219 { { "parent" [ v-integer ] } } validate-params
224 "parent" value f <annotation>
225 [ deposit-entity-slots ]
227 [ entity-url <redirect> ]
231 : <raw-annotation-action> ( -- action )
233 [ validate-integer-id "id" value lookup-annotation from-object ] >>init
234 [ "contents" value <text-content> ] >>display ;
236 : <delete-annotation-action> ( -- action )
239 [ { { "id" [ v-number ] } } validate-params ] >>validate
242 "id" value lookup-annotation
244 [ parent>> paste-url <redirect> ]
249 "delete annotations" >>description
250 { can-delete-pastes? } >>capabilities ;
252 : <pastebin> ( -- responder )
253 pastebin new-dispatcher
254 <pastebin-action> "" add-responder
255 <pastebin-feed-action> "list.atom" add-responder
256 <paste-action> "paste" add-responder
257 <raw-paste-action> "paste.txt" add-responder
258 <paste-feed-action> "paste.atom" add-responder
259 <new-paste-action> "new-paste" add-responder
260 <delete-paste-action> "delete-paste" add-responder
261 <new-annotation-action> "new-annotation" add-responder
262 <raw-annotation-action> "annotation.txt" add-responder
263 <delete-annotation-action> "delete-annotation" add-responder
265 { pastebin "pastebin-common" } >>template ;