aboutsummaryrefslogtreecommitdiff
path: root/module/entry-points/server.scm
blob: 972b89a843fa96d8342541a30e768b39fa8ddc1c (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
133
134
135
136
(define-module (entry-points server)
  :export (main)
  :use-module (util)
  :use-module (vcomponent)
  :use-module (parameters)
  )

(use-modules* (web (server request response uri))
              (output (html))
              (server (util macro))
              (sxml (simple))
              (ice-9 (match control rdelim curried-definitions ftw
                            getopt-long
                            iconv regex #| regex here due to bad macros |#  ))
              (srfi (srfi-1 srfi-88)))

(use-modules (datetime)
             (datetime util))

(define (file-extension name)
  (car (last-pair (string-split name #\.))))

(define (sxml->html-string sxml)
  (with-output-to-string
    (lambda () (display "<!doctype html>\n") (sxml->xml sxml))))

(define (directory-table dir)
  `(table
    (thead
     (tr (th "") (th "Name") (th "Perm")))
    (tbody
     ,@(map (lambda (kv)
              (let* (((k stat) kv))
                `(tr (td ,(case (stat:type stat)
                            [(directory) "📁"]
                            [(regular) "📰"]
                            [else "🙃"]))
                     (td (a (@ (href "/" ,dir ,k)) ,k))
                     (td ,(number->string (stat:perms stat) 8)))))
            (cddr (file-system-tree dir))))))


(define (make-make-routes calendar events)
  (make-routes

   (GET "/week/:start-date.html" (start-date)
        (let* ((start-date (parse-iso-date start-date)))

          (return '((content-type text/html))
                  (with-output-to-string
                    (lambda ()
                      (html-generate calendars: calendar
                                     events: events
                                     start-date: start-date
                                     end-date: (date+ start-date (date day: 6))
                                     next-start: (lambda (d) (date+ d (date day: 7)))
                                     prev-start: (lambda (d) (date- d (date day: 7)))
                                     render-calendar: render-calendar
                                     ))))))

   (GET "/month/:start-date.html" (start-date)
        (let* ((start-date (parse-iso-date start-date)))

          (return '((content-type text/html))
                  (with-output-to-string
                    (lambda ()
                      (html-generate calendars: calendar
                                     events: events
                                     start-date: start-date
                                     end-date: (date- (month+ start-date)
                                                      (date day: 1))
                                     next-start: month+
                                     prev-start: month-
                                     render-calendar: render-calendar-table
                                     pre-start: (start-of-week start-date)
                                     post-end: (end-of-week start-date)
                                     ))))))

   (GET "/static" ()
        (return
         '((content-type text/html))
         (sxml->html-string
          (directory-table "static/"))))

   (GET "/static/:filename.css" (filename)
        (return
         `((content-type text/css))
         (call-with-input-file (string-append "static/" filename ".css")
           read-string)))

   (GET "/static/:filename.js" (filename)
        (return
         `((content-type text/javascript))
         (call-with-input-file (string-append "static/" filename ".js")
           read-string)))

   (GET "/count" ()
        ;; (sleep 1)
        (return '((content-type text/plain))
                (string-append (number->string state) "\n")
                (1+ state)))

   ))

(define options
  '((port (value #t) (single-char #\p))
    (addr (value #t))
    (family (value #t)
            (predicate ,(lambda (v) (memv (string->symbol (string-upcase v))
                                  '(INET INET4 INET6)))))))

(define-public (main args)

  (define opts (getopt-long args options))
  (define port (option-ref opts 'port 8080))
  (define family (case (string->symbol (string-upcase (option-ref opts 'family "INET6")))
                   [(INET INET4) AF_INET]
                   [(INET6) AF_INET6]
                   [else (error "That address family is not supported")]) )
  ;; TODO the guile methods wants the ip address in numeric form. This is currently extra impossible
  (define addr (option-ref opts 'addr 0))

  (define-values (c e)
    (load-calendars
     calendar-files: (cond [(option-ref opts 'file #f) => list]
                           [else (calendar-files)]) ))

  (format #t "Starting server on ~a:~a~%I'm ~a, runing from ~a~%"
          (inet-ntop family addr) port
          (getpid) (getcwd))

  (run-server (make-make-routes c e)
              'http
              `(port: ,port
                addr: ,addr)
              0))