Add support for File: pages #7
					 4 changed files with 171 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -19,6 +19,7 @@
 | 
			
		|||
(require-reloadable "src/page-static.rkt" static-dispatcher)
 | 
			
		||||
(require-reloadable "src/page-subdomain.rkt" subdomain-dispatcher)
 | 
			
		||||
(require-reloadable "src/page-wiki.rkt" page-wiki)
 | 
			
		||||
(require-reloadable "src/page-file.rkt" page-file)
 | 
			
		||||
 | 
			
		||||
(reload!)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +39,7 @@
 | 
			
		|||
      page-proxy
 | 
			
		||||
      page-search
 | 
			
		||||
      page-wiki
 | 
			
		||||
      page-file
 | 
			
		||||
      redirect-wiki-home
 | 
			
		||||
      static-dispatcher
 | 
			
		||||
      subdomain-dispatcher))))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								dist.rkt
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								dist.rkt
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -13,6 +13,7 @@
 | 
			
		|||
(require (only-in "src/page-static.rkt" static-dispatcher))
 | 
			
		||||
(require (only-in "src/page-subdomain.rkt" subdomain-dispatcher))
 | 
			
		||||
(require (only-in "src/page-wiki.rkt" page-wiki))
 | 
			
		||||
(require (only-in "src/page-file.rkt" page-file))
 | 
			
		||||
 | 
			
		||||
(serve/launch/wait
 | 
			
		||||
 #:listen-ip (if (config-true? 'debug) "127.0.0.1" #f)
 | 
			
		||||
| 
						 | 
				
			
			@ -27,6 +28,7 @@
 | 
			
		|||
    page-proxy
 | 
			
		||||
    page-search
 | 
			
		||||
    page-wiki
 | 
			
		||||
    page-file
 | 
			
		||||
    redirect-wiki-home
 | 
			
		||||
    static-dispatcher
 | 
			
		||||
    subdomain-dispatcher)))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,6 +45,7 @@
 | 
			
		|||
              (pathprocedure:make "/proxy" (hash-ref ds 'page-proxy))
 | 
			
		||||
              (pathprocedure:make "/search" (hash-ref ds 'page-global-search))
 | 
			
		||||
              (filter:make (pregexp (format "^/~a/wiki/Category:.+$" px-wikiname)) (lift:make (hash-ref ds 'page-category)))
 | 
			
		||||
              (filter:make (pregexp (format "^/~a/wiki/File:.+$" px-wikiname)) (lift:make (hash-ref ds 'page-file)))
 | 
			
		||||
              (filter:make (pregexp (format "^/~a/wiki/.+$" px-wikiname)) (lift:make (hash-ref ds 'page-wiki)))
 | 
			
		||||
              (filter:make (pregexp (format "^/~a/search$" px-wikiname)) (lift:make (hash-ref ds 'page-search)))
 | 
			
		||||
              (filter:make (pregexp (format "^/~a(/(wiki(/)?)?)?$" px-wikiname)) (lift:make (hash-ref ds 'redirect-wiki-home)))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										166
									
								
								src/page-file.rkt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								src/page-file.rkt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,166 @@
 | 
			
		|||
#lang racket/base
 | 
			
		||||
(require racket/dict
 | 
			
		||||
         racket/list
 | 
			
		||||
         racket/match
 | 
			
		||||
         racket/string
 | 
			
		||||
         (prefix-in easy: net/http-easy)
 | 
			
		||||
         ; html libs
 | 
			
		||||
         html-parsing
 | 
			
		||||
         html-writing
 | 
			
		||||
         ; web server libs
 | 
			
		||||
         net/url
 | 
			
		||||
         web-server/http
 | 
			
		||||
         (only-in web-server/dispatchers/dispatch next-dispatcher)
 | 
			
		||||
         #;(only-in web-server/http/redirect redirect-to)
 | 
			
		||||
         "application-globals.rkt"
 | 
			
		||||
         "config.rkt"
 | 
			
		||||
         "data.rkt"
 | 
			
		||||
         "page-wiki.rkt"
 | 
			
		||||
         "syntax.rkt"
 | 
			
		||||
         "url-utils.rkt"
 | 
			
		||||
         "xexpr-utils.rkt")
 | 
			
		||||
 | 
			
		||||
(provide page-file)
 | 
			
		||||
 | 
			
		||||
(module+ test
 | 
			
		||||
  (require rackunit)
 | 
			
		||||
  (define test-media-detail
 | 
			
		||||
    '#hasheq((fileTitle . "Example file")
 | 
			
		||||
             (videoEmbedCode . "")
 | 
			
		||||
             (imageUrl . "https://static.wikia.nocookie.net/examplefile")
 | 
			
		||||
             (rawImageUrl . "https://static.wikia.nocookie.net/examplefile")
 | 
			
		||||
             (userName . "blankie")
 | 
			
		||||
             (isPostedIn . #t)
 | 
			
		||||
             (smallerArticleList . (#hasheq((title . "Example_article")
 | 
			
		||||
                                            (titleText . "Example article"))))
 | 
			
		||||
             (articleListIsSmaller . 0)
 | 
			
		||||
             (exists . #t)
 | 
			
		||||
             (imageDescription . #f))))
 | 
			
		||||
 | 
			
		||||
(define (url-content-type url)
 | 
			
		||||
  (log-outgoing url)
 | 
			
		||||
  (define dest-res (easy:head url #:timeouts timeouts))
 | 
			
		||||
  (easy:response-headers-ref dest-res 'content-type))
 | 
			
		||||
 | 
			
		||||
(define (get-media-html url content-type)
 | 
			
		||||
  (define maybe-proxied-url (if (config-true? 'strict_proxy) (u-proxy-url url) url))
 | 
			
		||||
  (cond
 | 
			
		||||
    [(eq? content-type #f) `""]
 | 
			
		||||
    [(regexp-match? #rx"(?i:^image/)" content-type) `(img (@ (src ,maybe-proxied-url)))]
 | 
			
		||||
    [(regexp-match? #rx"(?i:^audio/|^application/ogg(;|$))" content-type)
 | 
			
		||||
     `(audio (@ (src ,maybe-proxied-url) (controls)))]
 | 
			
		||||
    [(regexp-match? #rx"(?i:^video/)" content-type) `(video (@ (src ,maybe-proxied-url) (controls)))]
 | 
			
		||||
    [else `""]))
 | 
			
		||||
 | 
			
		||||
(define (generate-results-page #:source-url source-url
 | 
			
		||||
                               #:wikiname wikiname
 | 
			
		||||
                               #:title title
 | 
			
		||||
                               #:media-detail media-detail
 | 
			
		||||
                               #:image-content-type image-content-type
 | 
			
		||||
                               #:siteinfo [siteinfo #f])
 | 
			
		||||
  (define video-embed-code (jp "/videoEmbedCode" media-detail ""))
 | 
			
		||||
  (define raw-image-url (jp "/rawImageUrl" media-detail))
 | 
			
		||||
  (define image-url (jp "/imageUrl" media-detail raw-image-url))
 | 
			
		||||
  (define username (jp "/userName" media-detail))
 | 
			
		||||
  (define is-posted-in (jp "/isPostedIn" media-detail #f))
 | 
			
		||||
  (define smaller-article-list (jp "/smallerArticleList" media-detail))
 | 
			
		||||
  (define article-list-is-smaller (jp "/articleListIsSmaller" media-detail))
 | 
			
		||||
  (define image-description (jp "/imageDescription" media-detail #f))
 | 
			
		||||
  (define maybe-proxied-raw-image-url
 | 
			
		||||
    (if (config-true? 'strict_proxy) (u-proxy-url raw-image-url) raw-image-url))
 | 
			
		||||
  (generate-wiki-page
 | 
			
		||||
   #:source-url source-url
 | 
			
		||||
   #:wikiname wikiname
 | 
			
		||||
   #:title title
 | 
			
		||||
   #:siteinfo siteinfo
 | 
			
		||||
   `(div ,(if (non-empty-string? video-embed-code)
 | 
			
		||||
              (update-tree-wiki (html->xexp (preprocess-html-wiki video-embed-code)) wikiname)
 | 
			
		||||
              (get-media-html image-url image-content-type))
 | 
			
		||||
         (p ,(if (non-empty-string? video-embed-code)
 | 
			
		||||
                 `""
 | 
			
		||||
                 `(span (a (@ (href ,maybe-proxied-raw-image-url)) "View original file") ". "))
 | 
			
		||||
            "Added by "
 | 
			
		||||
            (a (@ (href ,(format "/~a/wiki/User:~a" wikiname username))) ,username)
 | 
			
		||||
            "."
 | 
			
		||||
            ,(if is-posted-in
 | 
			
		||||
                 `(span " Posted in "
 | 
			
		||||
                        ,@(map (λ (article)
 | 
			
		||||
                                 (define page-path (jp "/title" article))
 | 
			
		||||
                                 (define title (jp "/titleText" article page-path))
 | 
			
		||||
                                 `(span ,(if (eq? (car smaller-article-list) article) "" ", ")
 | 
			
		||||
                                        (a (@ (href ,(format "/~a/wiki/~a" wikiname page-path)))
 | 
			
		||||
                                           ,title)))
 | 
			
		||||
                               smaller-article-list)
 | 
			
		||||
                        ,(if (eq? article-list-is-smaller 1) "…" "."))
 | 
			
		||||
                 `""))
 | 
			
		||||
         ,(if (string? image-description)
 | 
			
		||||
              (update-tree-wiki (html->xexp (preprocess-html-wiki image-description)) wikiname)
 | 
			
		||||
              ""))))
 | 
			
		||||
 | 
			
		||||
(define (page-file req)
 | 
			
		||||
  (define wikiname (path/param-path (first (url-path (request-uri req)))))
 | 
			
		||||
  (define prefixed-title (path/param-path (caddr (url-path (request-uri req)))))
 | 
			
		||||
  (define origin (format "https://~a.fandom.com" wikiname))
 | 
			
		||||
  (define source-url (format "~a/wiki/~a" origin prefixed-title))
 | 
			
		||||
 | 
			
		||||
  (thread-let ([media-detail
 | 
			
		||||
                (define dest-url
 | 
			
		||||
                  (format "~a/wikia.php?~a"
 | 
			
		||||
                          origin
 | 
			
		||||
                          (params->query `(("format" . "json") ("controller" . "Lightbox")
 | 
			
		||||
                                                               ("method" . "getMediaDetail")
 | 
			
		||||
                                                               ("fileTitle" . ,prefixed-title)))))
 | 
			
		||||
                (log-outgoing dest-url)
 | 
			
		||||
                (define dest-res (easy:get dest-url #:timeouts timeouts))
 | 
			
		||||
                (easy:response-json dest-res)]
 | 
			
		||||
               [siteinfo (siteinfo-fetch wikiname)])
 | 
			
		||||
              (if (not (jp "/exists" media-detail #f))
 | 
			
		||||
                  (next-dispatcher)
 | 
			
		||||
                  (response-handler
 | 
			
		||||
                   (define file-title (jp "/fileTitle" media-detail ""))
 | 
			
		||||
                   (define title
 | 
			
		||||
                     (if (non-empty-string? file-title) (format "File:~a" file-title) prefixed-title))
 | 
			
		||||
                   (define image-content-type
 | 
			
		||||
                     (if (non-empty-string? (jp "/videoEmbedCode" media-detail ""))
 | 
			
		||||
                         #f
 | 
			
		||||
                         (url-content-type (jp "/imageUrl" media-detail))))
 | 
			
		||||
                   (define body
 | 
			
		||||
                     (generate-results-page #:source-url source-url
 | 
			
		||||
                                            #:wikiname wikiname
 | 
			
		||||
                                            #:title title
 | 
			
		||||
                                            #:media-detail media-detail
 | 
			
		||||
                                            #:image-content-type image-content-type
 | 
			
		||||
                                            #:siteinfo siteinfo))
 | 
			
		||||
                   (when (config-true? 'debug)
 | 
			
		||||
                     ; used for its side effects
 | 
			
		||||
                     ; convert to string with error checking, error will be raised if xexp is invalid
 | 
			
		||||
                     (xexp->html body))
 | 
			
		||||
                   (response/output #:code 200
 | 
			
		||||
                                    #:headers (build-headers always-headers)
 | 
			
		||||
                                    (λ (out) (write-html body out)))))))
 | 
			
		||||
(module+ test
 | 
			
		||||
  (parameterize ([(config-parameter 'strict_proxy) "true"])
 | 
			
		||||
    (check-equal? (get-media-html "https://static.wikia.nocookie.net/a" "image/jpeg")
 | 
			
		||||
                  `(img (@ (src "/proxy?dest=https%3A%2F%2Fstatic.wikia.nocookie.net%2Fa"))))
 | 
			
		||||
    (check-equal? (get-media-html "https://static.wikia.nocookie.net/b" "audio/mp3")
 | 
			
		||||
                  `(audio (@ (src "/proxy?dest=https%3A%2F%2Fstatic.wikia.nocookie.net%2Fb")
 | 
			
		||||
                             (controls)))))
 | 
			
		||||
  (parameterize ([(config-parameter 'strict_proxy) "no"])
 | 
			
		||||
    (check-equal? (get-media-html "https://static.wikia.nocookie.net/c" "application/ogg")
 | 
			
		||||
                  `(audio (@ (src "/proxy?dest=https%3A%2F%2Fstatic.wikia.nocookie.net%2Fc")
 | 
			
		||||
                             (controls))))
 | 
			
		||||
    (check-equal? (get-media-html "https://static.wikia.nocookie.net/d" "video/mp4")
 | 
			
		||||
                  `(video (@ (src "/proxy?dest=https%3A%2F%2Fstatic.wikia.nocookie.net%2Fd")
 | 
			
		||||
                             (controls)))))
 | 
			
		||||
  (check-equal? (get-media-html "https://example.com" "who knows") `"")
 | 
			
		||||
  (check-equal? (get-media-html "https://example.com" #f) `""))
 | 
			
		||||
(module+ test
 | 
			
		||||
  (parameterize ([(config-parameter 'strict_proxy) "true"])
 | 
			
		||||
    (check-not-false
 | 
			
		||||
     ((query-selector
 | 
			
		||||
       (attribute-selector 'src "/proxy?dest=https%3A%2F%2Fstatic.wikia.nocookie.net%2Fexamplefile")
 | 
			
		||||
       (generate-results-page #:source-url ""
 | 
			
		||||
                              #:wikiname "test"
 | 
			
		||||
                              #:title "File:Example file"
 | 
			
		||||
                              #:media-detail test-media-detail
 | 
			
		||||
                              #:image-content-type "image/jpeg"))))))
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue