1 ":";exec /home/private/plt/bin/mzscheme -r $0 "$@"
3 ;; (this is deprecated code; see the .py files)
4 ;; tagcloud-like for reddit
6 (require (planet "ssax.ss" ("lizorkin" "ssax.plt" 1 3))
7 (planet "htmlprag.ss" ("neil" "htmlprag.plt" 1 3))
8 (planet "sxml.ss" ("lizorkin" "sxml.plt" 1 4))
9 (planet "html.ss" ("jim" "webit.plt" 1 1)) ; for HTML generation
14 ; TODO: `id' is the http URL. I should use a better name
15 (define-struct reddit-link
16 (id href title comments score))
18 (define (all-reddit-links reddit-url)
19 ;; we are scrapping reddit HTML (thanks to htmlprag, ssax)
20 (let* ((doc (html->sxml (open-input-resource reddit-url)))
21 (tr-lst ((sxpath "//tr[contains(@class, 'Row')]") doc)))
23 ;; tr-lst -- the ugly reddit HTML
24 ;; what follows is, thus, an ugly hack
25 (define (generate-reddit-links tr-lst)
26 (if (null? tr-lst) '()
28 (let* ((row1 (car tr-lst))
30 (link-ele ((sxpath "/td[@colspan = 3]/a/@href/text()") row1))
31 (title-ele ((sxpath "/td[@colspan = 3]/a/text()") row1))
32 (id-ele ((sxpath "/td[@colspan = 3]/a[@class='bylink']/@href/text()") row2))
33 (score-ele ((sxpath "/td[@colspan = 3]/span[contains(@id, 'score')]/text()") row2))
34 (comments-ele ((sxpath "/td[@colspan = 3]/a[@class='bylink']/text()") row2)))
36 ;; extract values from sxml nodes
37 (let ((href (car link-ele))
38 (id (if (string-contains (car id-ele) "http://") ; normalize url
40 (format "~a~a" reddit-url (car id-ele))))
41 (title (car title-ele))
42 (comments (string->number
44 (regexp-match "[0-9]+" (car comments-ele))
46 (score (if (null? score-ele) 0 ; XXX: link submitted < 1 hr ?
47 (string->number (car (regexp-match "[0-9]+" (car score-ele)))))))
48 (cons (make-reddit-link id href title comments score)
49 (generate-reddit-links (cddr tr-lst))))))))
51 (generate-reddit-links tr-lst)))
54 (define (render-reddit url)
56 (let* ((links (all-reddit-links url))
57 (max-score (apply max (map reddit-link-score links))))
59 ;; we assign a suitable font-size based on the relative scores
60 ;; just like tagclouds <http://flickr.com/photos/tags/>
61 (define (find-font-size score)
62 (let* ((size-min 12) ; minimum css font-size
65 (size-total (/ (- size-max size-min)
69 (quotient (* score size-total)
73 (define (render-reddit-link link)
74 (h4:span h4:style: "margin-right: 10px;"
76 (h4:a h4:style: "color: gray;"
77 h4:href: (reddit-link-id link)
78 h4:title: (format "Click to see ~a comments in reddit"
79 (reddit-link-comments link))
80 (reddit-link-comments link)))
81 (h4:a h4:href: (reddit-link-href link)
82 h4:title: (format "~a points"
83 (if (= 0 (reddit-link-score link))
85 (reddit-link-score link)))
86 h4:style: (format "font-size: ~apx;"
87 (find-font-size (reddit-link-score link)))
88 (reddit-link-title link))))
90 (h4:div (map render-reddit-link links))))
92 (define (generate-html)
97 background-color: white;
101 a:link { text-decoration: none; }
102 a:visited { text-decoration: none; }
103 a:hover { text-decoration: none; background-color: #b9badb; }
104 a:active { text-decoration: none; background-color: #b9badb; }
106 img { border: none; }
111 (h4:p "This is the " (h4:b "reddit cloud") ", written in "
112 (h4:a h4:href: "http://nearfar.org/code/reddit/"
114 (h4:head (h4:title "reddit cloud")
115 (h4:style h4:type: "text/css"
117 (h4:body (h4:h2 (h4:a h4:href: "http://reddit.com/"
119 (render-reddit "http://reddit.com")
121 (h4:h2 (h4:a h4:id: "programming"
122 h4:href: "http://programming.reddit.com/"
123 "programming.reddit.com"))
124 (render-reddit "http://programming.reddit.com")
126 (h4:h2 (h4:a h4:id: "science"
127 h4:href: "http://science.reddit.com/"
128 "science.reddit.com"))
129 (render-reddit "http://science.reddit.com")
131 (h4:div h4:style: "display: none;"
132 (date->string (current-date)))))))
134 ; http://schemecookbook.org/Cookbook/FileRead
135 (define (read-all path)
136 (let ((size (file-size path)))
137 (call-with-input-file path
139 (read-string size p)))))
141 (define (cached-html html-generator timeout)
142 "cache the html returned by `html-genenerator' for `timeout' seconds"
143 (let ((cache-life (lambda ()
144 (- (time-second (current-time))
145 (if (file-exists? "cache")
146 (file-or-directory-modify-seconds "cache")
148 (update-cache (lambda (content)
149 (if (file-exists? "cache") (delete-file "cache"))
150 (with-output-to-file "cache"
151 (lambda () (display content) content))))
152 (retrieve-cache (lambda ()
153 (read-all "cache"))))
154 (if (> (cache-life) timeout)
155 (update-cache (html-generator))
159 "time the `code' form"
160 (let ((time-before (time-second (current-time))))
162 (- (time-second (current-time)) time-before)))
165 (display "content-type: text/html; charset=utf-8") (newline)
167 (display (format "<!-- ~a secs at ~a -->"
169 '(display (cached-html generate-html 300)))
170 (date->string (current-date)))))