2022-09-16 13:56:03 +00:00
|
|
|
#lang racket/base
|
2022-10-09 07:53:09 +00:00
|
|
|
(require racket/list
|
2022-10-31 06:39:19 +00:00
|
|
|
racket/match
|
2022-11-29 11:03:54 +00:00
|
|
|
web-server/http/request-structs
|
|
|
|
net/url-string
|
|
|
|
(only-in net/cookies/server cookie-header->alist cookie->set-cookie-header make-cookie)
|
2022-10-09 07:53:09 +00:00
|
|
|
(prefix-in easy: net/http-easy)
|
2023-02-05 04:56:15 +00:00
|
|
|
db
|
2022-10-09 07:53:09 +00:00
|
|
|
memo
|
2022-10-31 06:39:19 +00:00
|
|
|
"static-data.rkt"
|
2023-02-05 04:56:15 +00:00
|
|
|
"whole-utils.rkt"
|
2023-03-08 09:56:04 +00:00
|
|
|
"../lib/url-utils.rkt"
|
2023-02-05 04:56:15 +00:00
|
|
|
"../lib/xexpr-utils.rkt"
|
|
|
|
"../archiver/archiver-database.rkt"
|
|
|
|
"config.rkt")
|
2022-09-16 13:56:03 +00:00
|
|
|
|
|
|
|
(provide
|
2022-10-09 09:50:50 +00:00
|
|
|
(struct-out siteinfo^)
|
|
|
|
(struct-out license^)
|
2022-10-31 06:39:19 +00:00
|
|
|
(struct-out head-data^)
|
2022-11-29 11:03:54 +00:00
|
|
|
(struct-out user-cookies^)
|
2022-10-09 07:53:09 +00:00
|
|
|
siteinfo-fetch
|
2022-10-09 09:50:50 +00:00
|
|
|
siteinfo-default
|
2022-10-31 06:39:19 +00:00
|
|
|
license-default
|
|
|
|
head-data-getter
|
2022-11-29 11:03:54 +00:00
|
|
|
head-data-default
|
|
|
|
user-cookies-getter
|
|
|
|
user-cookies-default
|
|
|
|
user-cookies-setter
|
|
|
|
user-cookies-setter-url)
|
2022-09-16 13:56:03 +00:00
|
|
|
|
2022-10-09 09:50:50 +00:00
|
|
|
(struct siteinfo^ (sitename basepage license) #:transparent)
|
|
|
|
(struct license^ (text url) #:transparent)
|
2022-10-31 06:39:19 +00:00
|
|
|
(struct head-data^ (body-class icon-url) #:transparent)
|
2022-10-09 07:53:09 +00:00
|
|
|
|
2022-10-09 09:50:50 +00:00
|
|
|
(define license-default (license^ "CC-BY-SA" "https://www.fandom.com/licensing"))
|
2023-02-05 04:56:15 +00:00
|
|
|
(define siteinfo-default (siteinfo^ "Unknown Wiki" "Main_Page" license-default))
|
2022-10-31 07:03:50 +00:00
|
|
|
(define head-data-default (head-data^ "skin-fandomdesktop" (get-static-url "breezewiki-favicon.svg")))
|
2022-10-09 07:53:09 +00:00
|
|
|
|
2023-03-09 10:06:35 +00:00
|
|
|
(when (config-true? 'feature_offline::only)
|
|
|
|
(void (get-slc)))
|
|
|
|
|
2022-10-09 07:53:09 +00:00
|
|
|
(define/memoize (siteinfo-fetch wikiname) #:hash hash
|
2023-02-05 04:56:15 +00:00
|
|
|
(cond
|
|
|
|
[(config-true? 'feature_offline::only)
|
|
|
|
(when (config-true? 'debug)
|
|
|
|
(printf "using offline mode for siteinfo ~a~n" wikiname))
|
2023-03-08 09:56:04 +00:00
|
|
|
(define row (query-maybe-row* "select sitename, basepage, license_text, license_url from wiki where wikiname = ?"
|
|
|
|
wikiname))
|
2023-02-05 04:56:15 +00:00
|
|
|
(if row
|
|
|
|
(siteinfo^ (vector-ref row 0)
|
|
|
|
(vector-ref row 1)
|
|
|
|
(license^ (vector-ref row 2)
|
|
|
|
(vector-ref row 3)))
|
|
|
|
siteinfo-default)]
|
|
|
|
[else
|
|
|
|
(define dest-url
|
|
|
|
(format "https://~a.fandom.com/api.php?~a"
|
|
|
|
wikiname
|
|
|
|
(params->query '(("action" . "query")
|
|
|
|
("meta" . "siteinfo")
|
|
|
|
("siprop" . "general|rightsinfo")
|
|
|
|
("format" . "json")
|
|
|
|
("formatversion" . "2")))))
|
|
|
|
(log-outgoing dest-url)
|
|
|
|
(define res (easy:get dest-url))
|
|
|
|
(define data (easy:response-json res))
|
|
|
|
(siteinfo^ (jp "/query/general/sitename" data)
|
|
|
|
(second (regexp-match #rx"/wiki/(.*)" (jp "/query/general/base" data)))
|
|
|
|
(license^ (jp "/query/rightsinfo/text" data)
|
|
|
|
(jp "/query/rightsinfo/url" data)))]))
|
2022-10-31 06:39:19 +00:00
|
|
|
|
|
|
|
(define/memoize (head-data-getter wikiname) #:hash hash
|
|
|
|
;; data will be stored here, can be referenced by the memoized closure
|
|
|
|
(define this-data head-data-default)
|
|
|
|
;; returns the getter
|
|
|
|
(λ ([res-in #f])
|
|
|
|
(when res-in
|
|
|
|
;; when actual information is provided, parse it into the struct and store it for the future
|
|
|
|
(define head-html (jp "/parse/headhtml" res-in ""))
|
|
|
|
(define data
|
|
|
|
(head-data^
|
|
|
|
(match (regexp-match #rx"<body [^>]*class=\"([^\"]*)" head-html)
|
|
|
|
[(list _ classes) classes]
|
|
|
|
[_ (head-data^-body-class head-data-default)])
|
|
|
|
(match (regexp-match #rx"<link rel=\"(?:shortcut )?icon\" href=\"([^\"]*)" head-html)
|
|
|
|
[(list _ icon-url) icon-url]
|
|
|
|
[_ (head-data^-icon-url head-data-default)])))
|
|
|
|
(set! this-data data))
|
|
|
|
;; then no matter what, return the best information we have so far
|
|
|
|
this-data))
|
2022-11-29 11:03:54 +00:00
|
|
|
|
|
|
|
(struct user-cookies^ (theme) #:prefab)
|
|
|
|
(define user-cookies-default (user-cookies^ 'default))
|
|
|
|
(define (user-cookies-getter req)
|
|
|
|
(define cookie-header (headers-assq* #"cookie" (request-headers/raw req)))
|
|
|
|
(define cookies-alist (if cookie-header (cookie-header->alist (header-value cookie-header) bytes->string/utf-8) null))
|
|
|
|
(define cookies-hash
|
|
|
|
(for/hasheq ([pair cookies-alist])
|
|
|
|
(match pair
|
|
|
|
[(cons "theme" (and theme (or "light" "dark" "default")))
|
|
|
|
(values 'theme (string->symbol theme))]
|
|
|
|
[_ (values #f #f)])))
|
|
|
|
(user-cookies^
|
|
|
|
(hash-ref cookies-hash 'theme (user-cookies^-theme user-cookies-default))))
|
|
|
|
|
|
|
|
(define (user-cookies-setter user-cookies)
|
|
|
|
(map (λ (c) (header #"Set-Cookie" (cookie->set-cookie-header c)))
|
|
|
|
(list (make-cookie "theme" (symbol->string (user-cookies^-theme user-cookies))
|
|
|
|
#:path "/"
|
|
|
|
#:max-age (* 60 60 24 365 10)))))
|
|
|
|
|
|
|
|
(define (user-cookies-setter-url req new-settings)
|
2022-12-04 10:44:35 +00:00
|
|
|
(format "/set-user-settings?~a" (params->query `(("next_location" . ,(url->string (request-uri req)))
|
2022-11-29 11:03:54 +00:00
|
|
|
("new_settings" . ,(format "~a" new-settings))))))
|