(defpackage #:lazybones-client.shared (:intern #:req-string) (:export #:*host* #:*body* #:*headers* #:*cookies*)) (defpackage #:ONELINERS.API-CLIENT (:use :cl :lazybones-client.shared) (:export #:*host* #:*body* #:*headers* #:*cookies* #:request-with #:GET--ONELINERS #:PUT--ONELINER-ENTRY-FLAG #:PATCH--ONELINER-ENTRY-EDIT #:PUT--ONELINER-ONELINER-LOCKED #:POST--ONELINER #:POST--INVITE #:DELETE--ACCESS-ACCESS #:POST--ACCESS #:POST--INVITE-REDEEM-CODE)) (in-package :ONELINERS.API-CLIENT) (defvar *host* nil "The host to which the client will send its requests.") (defvar *body* nil "Body passed to client post, put, and patch requests") (defvar *cookies* nil "An instance of CL-COOKIE:COOKIE-JAR.") (defvar *headers* nil "A liist of (header-name . header-value) pairs.") (defmacro request-with ((&key host body headers content-type cookies) &body forms) "Make a request in a specific context. HOST is a string, the hostname where the request will be sent. Defaults to *HOST*. BODY should be a string, an alist, or a pathname. Default to *BODY* HEADERS should be an ALIST of (header-name . header-value) string pairs. Defaults to *HEADERS*. CONTENT-TYPE is a convenience for supplying just the Content-Type header. COOKIES should be an instance of CL-COOKIE:COOKIE-JAR. Defaults to *COOKIES*. " (let ((content-type-var (gensym)) (http-error-var (gensym))) `(let ((*host* (or ,host *host*)) (*body* (or ,body *body*)) (*headers* (or ,headers *headers*)) (*cookies* (or ,cookies *cookies*)) (,content-type-var ,content-type)) (when ,content-type-var (push (cons "Content-Type" ,content-type-var) *headers*)) (handler-case (progn ,@forms) (dex:http-request-failed (,http-error-var) (format *error-output* "~a -- ~a" (dex:response-status ,http-error-var) (dex:response-body ,http-error-var))))))) (DEFUN GET--ONELINERS (&KEY TAGS LIMIT NOTFLAGGED) "A search endpoint returning a JSON encoded array of Oneliner Entries. TAGS cannot be empty. Returns a [Search Result](#search-result) object." (LET ((LAZYBONES-CLIENT.SHARED::REQ-STRING (APPLY #'CONCATENATE 'STRING LAZYBONES-CLIENT.SHARED:*HOST* (FORMAT NIL "/oneliners") (WHEN (OR TAGS LIMIT NOTFLAGGED) (LIST "?" (IF TAGS (CONCATENATE 'STRING (SYMBOL-NAME 'TAGS) "=" (FORMAT NIL "~a" TAGS)) "") (IF LIMIT (CONCATENATE 'STRING "&" (SYMBOL-NAME 'LIMIT) "=" (FORMAT NIL "~a" LIMIT)) "") (IF NOTFLAGGED (CONCATENATE 'STRING "&" (SYMBOL-NAME 'NOTFLAGGED) "=" (FORMAT NIL "~a" NOTFLAGGED)) "")))))) (DEXADOR:GET LAZYBONES-CLIENT.SHARED::REQ-STRING :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*))) (DEFUN PUT--ONELINER-ENTRY-FLAG (ENTRY &KEY TOKEN VALUE) "Flag the oneliner for review." (LET ((LAZYBONES-CLIENT.SHARED::REQ-STRING (APPLY #'CONCATENATE 'STRING LAZYBONES-CLIENT.SHARED:*HOST* (FORMAT NIL "/oneliner/~a/flag" ENTRY) (WHEN (OR TOKEN VALUE) (LIST "?" (IF TOKEN (CONCATENATE 'STRING (SYMBOL-NAME 'TOKEN) "=" (FORMAT NIL "~a" TOKEN)) "") (IF VALUE (CONCATENATE 'STRING "&" (SYMBOL-NAME 'VALUE) "=" (FORMAT NIL "~a" VALUE)) "")))))) (IF LAZYBONES-CLIENT.SHARED:*BODY* (DEXADOR:PUT LAZYBONES-CLIENT.SHARED::REQ-STRING :CONTENT LAZYBONES-CLIENT.SHARED:*BODY* :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*) (DEXADOR:PUT LAZYBONES-CLIENT.SHARED::REQ-STRING :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*)))) (DEFUN PATCH--ONELINER-ENTRY-EDIT (ENTRY &KEY TOKEN) "Edit the fields of a oneliner." (LET ((LAZYBONES-CLIENT.SHARED::REQ-STRING (APPLY #'CONCATENATE 'STRING LAZYBONES-CLIENT.SHARED:*HOST* (FORMAT NIL "/oneliner/~a/edit" ENTRY) (WHEN (OR TOKEN) (LIST "?" (IF TOKEN (CONCATENATE 'STRING (SYMBOL-NAME 'TOKEN) "=" (FORMAT NIL "~a" TOKEN)) "")))))) (IF LAZYBONES-CLIENT.SHARED:*BODY* (DEXADOR:PATCH LAZYBONES-CLIENT.SHARED::REQ-STRING :CONTENT LAZYBONES-CLIENT.SHARED:*BODY* :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*) (DEXADOR:PATCH LAZYBONES-CLIENT.SHARED::REQ-STRING :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*)))) (DEFUN PUT--ONELINER-ONELINER-LOCKED (ONELINER &KEY TOKEN VALUE) "Sets the locked value of the specified oneliner" (LET ((LAZYBONES-CLIENT.SHARED::REQ-STRING (APPLY #'CONCATENATE 'STRING LAZYBONES-CLIENT.SHARED:*HOST* (FORMAT NIL "/oneliner/~a/locked" ONELINER) (WHEN (OR TOKEN VALUE) (LIST "?" (IF TOKEN (CONCATENATE 'STRING (SYMBOL-NAME 'TOKEN) "=" (FORMAT NIL "~a" TOKEN)) "") (IF VALUE (CONCATENATE 'STRING "&" (SYMBOL-NAME 'VALUE) "=" (FORMAT NIL "~a" VALUE)) "")))))) (IF LAZYBONES-CLIENT.SHARED:*BODY* (DEXADOR:PUT LAZYBONES-CLIENT.SHARED::REQ-STRING :CONTENT LAZYBONES-CLIENT.SHARED:*BODY* :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*) (DEXADOR:PUT LAZYBONES-CLIENT.SHARED::REQ-STRING :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*)))) (DEFUN POST--ONELINER (&KEY TOKEN) "Make a new [oneliner](#oneliner)." (LET ((LAZYBONES-CLIENT.SHARED::REQ-STRING (APPLY #'CONCATENATE 'STRING LAZYBONES-CLIENT.SHARED:*HOST* (FORMAT NIL "/oneliner") (WHEN (OR TOKEN) (LIST "?" (IF TOKEN (CONCATENATE 'STRING (SYMBOL-NAME 'TOKEN) "=" (FORMAT NIL "~a" TOKEN)) "")))))) (IF LAZYBONES-CLIENT.SHARED:*BODY* (DEXADOR:POST LAZYBONES-CLIENT.SHARED::REQ-STRING :CONTENT LAZYBONES-CLIENT.SHARED:*BODY* :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*) (DEXADOR:POST LAZYBONES-CLIENT.SHARED::REQ-STRING :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*)))) (DEFUN POST--INVITE (&KEY TOKEN) "On success, return an object containing a new [invite token](#invite-token)." (LET ((LAZYBONES-CLIENT.SHARED::REQ-STRING (APPLY #'CONCATENATE 'STRING LAZYBONES-CLIENT.SHARED:*HOST* (FORMAT NIL "/invite") (WHEN (OR TOKEN) (LIST "?" (IF TOKEN (CONCATENATE 'STRING (SYMBOL-NAME 'TOKEN) "=" (FORMAT NIL "~a" TOKEN)) "")))))) (IF LAZYBONES-CLIENT.SHARED:*BODY* (DEXADOR:POST LAZYBONES-CLIENT.SHARED::REQ-STRING :CONTENT LAZYBONES-CLIENT.SHARED:*BODY* :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*) (DEXADOR:POST LAZYBONES-CLIENT.SHARED::REQ-STRING :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*)))) (DEFUN DELETE--ACCESS-ACCESS (ACCESS &KEY TOKEN) "Revoke access of CONTRIBUTOR" (LET ((LAZYBONES-CLIENT.SHARED::REQ-STRING (APPLY #'CONCATENATE 'STRING LAZYBONES-CLIENT.SHARED:*HOST* (FORMAT NIL "/access/~a" ACCESS) (WHEN (OR TOKEN) (LIST "?" (IF TOKEN (CONCATENATE 'STRING (SYMBOL-NAME 'TOKEN) "=" (FORMAT NIL "~a" TOKEN)) "")))))) (DEXADOR:DELETE LAZYBONES-CLIENT.SHARED::REQ-STRING :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*))) (DEFUN POST--ACCESS () "Authenticate a contributor and reply with an [API token](#access-token)" (LET ((LAZYBONES-CLIENT.SHARED::REQ-STRING (APPLY #'CONCATENATE 'STRING LAZYBONES-CLIENT.SHARED:*HOST* (FORMAT NIL "/access") NIL))) (IF LAZYBONES-CLIENT.SHARED:*BODY* (DEXADOR:POST LAZYBONES-CLIENT.SHARED::REQ-STRING :CONTENT LAZYBONES-CLIENT.SHARED:*BODY* :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*) (DEXADOR:POST LAZYBONES-CLIENT.SHARED::REQ-STRING :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*)))) (DEFUN POST--INVITE-REDEEM-CODE (CODE) "Redeem an [invite code](#invite-code) and create a new [contributor](#new-contributor-post-body)" (LET ((LAZYBONES-CLIENT.SHARED::REQ-STRING (APPLY #'CONCATENATE 'STRING LAZYBONES-CLIENT.SHARED:*HOST* (FORMAT NIL "/invite/redeem/~a" CODE) NIL))) (IF LAZYBONES-CLIENT.SHARED:*BODY* (DEXADOR:POST LAZYBONES-CLIENT.SHARED::REQ-STRING :CONTENT LAZYBONES-CLIENT.SHARED:*BODY* :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*) (DEXADOR:POST LAZYBONES-CLIENT.SHARED::REQ-STRING :COOKIE-JAR LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS LAZYBONES-CLIENT.SHARED:*HEADERS*))))