;;; web.lisp (in-package :seanut) (eval-when (:compile-toplevel) (declaim (inline json-request format-url generate-authorization download-media))) (defun generate-authorization (&optional token) "generates a properly formatted authorization header" (format nil *authorization-format* (seanut-version) (uiop:hostname) (md5-string (uiop: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 auth &key (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 `(("Authorization" . ,auth) ,@extra-headers)))) (defun run-search-query (domain auth type name) (gethash "Items" (json-request (format-url domain "Items?fields=Path&includeItemTypes=~A&recursive=true&searchTerm=~A" type name) 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 `(("X-Emby-Authorization" . ,auth))))