seanut/web.lisp

54 lines
2.4 KiB
Common Lisp

;;; web.lisp
(in-package :seanut)
(eval-when (:compile-toplevel)
(declaim (inline json-request format-url generate-authorization download-media
format-hostname)))
(defun generate-authorization (&optional token)
"generates a properly formatted authorization header"
(let ((hostname (str:replace-first ".local" "" (uiop:hostname))))
(apply #'format `(nil ,*authorization-format*
,@(mapcar #'url-encode
(list (str:concat "Seanut " (seanut-version))
hostname (string-downcase (md5-string hostname))
(seanut-version) (or token "")))))))
(defun format-url (domain slug &rest args)
"formats DOMAIN into a url, ensures we include the url scheme
SLUG is a format-coded string that represents the path for the query
ARGS are the arguments for the SLUG format string"
(format nil "~:[https://~;~]~A/~A"
(uiop:string-prefix-p "https://" domain)
domain (apply #'format `(nil ,slug ,@args))))
(defun json-request (url &key auth (method :get) extra-headers content)
"makes a request to URL, using AUTH as the X-Emby-Authorization header and METHOD as the http method (defaults to get) and parses the returned value with jzon:parse
if EXTRA-HEADERS is non-nil, includes them in the headers alongside the X-Emby-Authorization one
if CONTENT is non-nil, passes that along to the request"
(parse (dex:request url :method method
:content content
:headers `(,(when auth
`("Authorization" . ,auth))
,@extra-headers))))
(defun run-search-query (domain auth type name)
"runs the search query to get the initial list of items
can probably be removed and the request can be made in-line"
(gethash "Items"
(json-request (format-url domain "Items?fields=Path,ChildCount&includeItemTypes=~A&recursive=true&searchTerm=~A"
type name)
:auth auth)))
(defun download-media (path url auth)
"downloads the media at URL, using HEADER as the authorization header.
if DESTINATION is non-nil, dumps media into that directory, otherwise it uses CWD"
(dex:fetch url path
:if-exists nil
:headers `(("Authorization" . ,auth))))