blob: 5df77b36e2132d1c6e42eb64b34d3c68a3f4adad (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
(defpackage :webstats
(:use :common-lisp :hunchentoot :spinneret))
(defpackage :webstats-js
(:use :cl :parenscript))
(in-package :webstats-js)
(setf *js-target-version* "1.9")
(ps::define-statement-operator for-of ((var iterable) &rest body)
`(ps-js::for-of ,(ps::compile-expression var)
,(ps::compile-expression iterable)
,(ps::compile-loop-body (list var) body)))
(ps::defprinter ps-js::for-of (var object body-block)
"for (const "(ps::ps-print var)" of "(ps::ps-print object)") "
(ps::ps-print body-block))
(in-package :webstats)
(yesql:import log-queries
:from "queries.sql"
:as :cl-yesql/sqlite
:binding :all-functions)
;; (sqlite:with-open-database (db "test.db")
;; (drop-stats-table db)
;; (create-stats-table db))
;; (sqlite:with-open-database (db "test.db")
;; (sqlite:with-transaction db
;; (let ((ip "122.0.0.1")
;; (agent "sly"))
;; (add-ip db :ip ip)
;; (add-user-agent db :user-agent agent)
;; (insert db
;; :click nil
;; :page "ho"
;; :referer "ref"
;; :ip ip
;; :user-agent agent
;; :title "try"))))
(hunchentoot:define-easy-handler
(visit :uri "/visit" :default-request-type :both)
(title page referer click)
(format nil "you are our visit ~d"
(insert *sqlite*
:click click
:page page
:referer referer
:ip (remote-addr*)
:user-agent (user-agent)
:title title)))
(hunchentoot:define-easy-handler (stat-js :uri "/stats.js") ()
(setf (hunchentoot:content-type*) "text/javascript")
(ps:ps-compile-file "stats.paren"))
(hunchentoot:define-easy-handler (metric :uri "/metric.json") (q)
(setf (hunchentoot:content-type*) "application/json")
(cl-json:encode-json-to-string
(apply #'mapcar #'list
(cond
((string= q "all")
(activity-stats *sqlite*))
((string= q "split")
(activity-places *sqlite*))
((list (list)))))))
(hunchentoot:define-easy-handler (graphs :uri "/graphs") ()
(with-html-string
(:doctype)
(:html
(:head (:title "hu yu ipi")
(:meta :charset "utf-8")
(:link :rel "stylesheet" :href "/webstats/static/uPlot.min.css")
(:script :async t :src "/webstats/static/uPlot.iife.min.js" :type "text/javascript")
(:script :async t :src "/stats/stats.js" :type "text/javascript")
(:script :async t :src "http://127.0.0.1:8095/skewer"))
(:body
(:h1 "great graph stats")
(:div :id "graph")
(:script
(:raw
(ps:ps
(add-event-listener
"load"
(lambda ()
(ps:chain (fetch "/stats/metric.json?q=all")
(then #'response-to-json)
(then #'plot)))))))))))
(defvar *acceptor*)
(defvar *sqlite*)
(defun start-server (port)
(setf *acceptor*
(make-instance 'hunchentoot:easy-acceptor :port port))
(setf *sqlite* (sqlite:connect "test.db"))
(hunchentoot:start *acceptor*))
(defun main ()
(let ((port (parse-integer (or (uiop:getenv "PORT")
"4252"))))
(start-server port)
(format *standard-output* "Hunchentoot server started on port ~d.~&" port)
(handler-case (bt:join-thread
(find-if (lambda (th)
(search "hunchentoot" (bt:thread-name th)))
(bt:all-threads)))
;; Catch a user's C-c
(#+sbcl sb-sys:interactive-interrupt
#+ccl ccl:interrupt-signal-condition
#+clisp system::simple-interrupt-condition
#+ecl ext:interactive-interrupt
#+allegro excl:interrupt-signal
() (progn
(format *error-output* "Aborting.~&")
(hunchentoot:stop *acceptor*)
(sqlite:disconnect *sqlite*)
(uiop:quit)))
(error (c) (format t "Woops, an unknown error occured:~&~a~&" c)))))
(defun create-static-assets ()
(let ((ps:*ps-print-pretty* nil))
(with-open-file (ps:*parenscript-stream*
"stats.js" :direction :output
:if-exists :supersede)
(ps:ps-compile-file "stats.paren"))))
|