aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.lisp3
-rw-r--r--oneliners.api-client.lisp209
-rw-r--r--src/main.lisp23
3 files changed, 171 insertions, 64 deletions
diff --git a/build.lisp b/build.lisp
new file mode 100644
index 0000000..f8e4227
--- /dev/null
+++ b/build.lisp
@@ -0,0 +1,3 @@
+
+(asdf:load-system "oneliners.cli")
+(sb-ext:save-lisp-and-die "ol" :toplevel 'oneliners.cli::main :executable t)
diff --git a/oneliners.api-client.lisp b/oneliners.api-client.lisp
index d3142fb..98c156d 100644
--- a/oneliners.api-client.lisp
+++ b/oneliners.api-client.lisp
@@ -5,26 +5,32 @@
(defpackage #:ONELINERS.API-CLIENT
(:use :cl :lazybones-client.shared)
(:export #:*host* #:*body* #:*headers* #:*cookies* #:request-with
- #:POST--AUTH
- #:POST--ONELINER
- #:PUT--ONELINER-ONELINER
- #:GET--SEARCH))
+ #:GET--SEARCH
+#:PATCH--FLAG-ONELINER
+#:PATCH--EDIT-ONELINER
+#:PATCH--UNLOCK-ONELINER
+#:PATCH--LOCK-ONELINER
+#:POST--ADD-ONELINER
+#:POST--MAKE-INVITE
+#:POST--REVOKE-CONTRIBUTOR
+#:POST--TOKEN-CONTRIBUTOR
+#:POST--REDEEM-INVITE))
(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 *body* nil
+ "Body passed to client post, put, and patch requests")
-(defvar *cookies* nil
- "An instance of CL-COOKIE:COOKIE-JAR.")
+ (defvar *cookies* nil
+ "An instance of CL-COOKIE:COOKIE-JAR.")
-(defvar *headers* nil
- "A liist of (header-name . header-value) pairs.")
+ (defvar *headers* nil
+ "A liist of (header-name . header-value) pairs.")
-(defmacro request-with ((&key host body headers content-type cookies) &body forms)
+ (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
@@ -52,11 +58,97 @@ COOKIES should be an instance of CL-COOKIE:COOKIE-JAR. Defaults to
,@forms)))
-(DEFUN POST--AUTH ()
- "Requests an authorization token"
+(DEFUN GET--SEARCH (&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 "/auth") (WHEN (OR) (LIST "?")))))
+ (FORMAT NIL "/search")
+ (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 PATCH--FLAG-ONELINER (ONELINER)
+ "Flag the oneliner for review. Open to anyone."
+ (LET ((LAZYBONES-CLIENT.SHARED::REQ-STRING
+ (APPLY #'CONCATENATE 'STRING LAZYBONES-CLIENT.SHARED:*HOST*
+ (FORMAT NIL "/flag/~a" ONELINER) NIL)))
+ (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 PATCH--EDIT-ONELINER (ONELINER)
+ "Edit the fields of a oneliner."
+ (LET ((LAZYBONES-CLIENT.SHARED::REQ-STRING
+ (APPLY #'CONCATENATE 'STRING LAZYBONES-CLIENT.SHARED:*HOST*
+ (FORMAT NIL "/edit/~a" ONELINER) NIL)))
+ (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 PATCH--UNLOCK-ONELINER (ONELINER)
+ "Unlocks a oneliner."
+ (LET ((LAZYBONES-CLIENT.SHARED::REQ-STRING
+ (APPLY #'CONCATENATE 'STRING LAZYBONES-CLIENT.SHARED:*HOST*
+ (FORMAT NIL "/unlock/~a" ONELINER) NIL)))
+ (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 PATCH--LOCK-ONELINER (ONELINER)
+ "Locks a oneliner. Locked oneliners cannot be edited or flagged."
+ (LET ((LAZYBONES-CLIENT.SHARED::REQ-STRING
+ (APPLY #'CONCATENATE 'STRING LAZYBONES-CLIENT.SHARED:*HOST*
+ (FORMAT NIL "/lock/~a" ONELINER) NIL)))
+ (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 POST--ADD-ONELINER ()
+ "Make a new [oneliner](#oneliner)."
+ (LET ((LAZYBONES-CLIENT.SHARED::REQ-STRING
+ (APPLY #'CONCATENATE 'STRING LAZYBONES-CLIENT.SHARED:*HOST*
+ (FORMAT NIL "/add-oneliner") NIL)))
(IF LAZYBONES-CLIENT.SHARED:*BODY*
(DEXADOR:POST LAZYBONES-CLIENT.SHARED::REQ-STRING :CONTENT
LAZYBONES-CLIENT.SHARED:*BODY* :COOKIE-JAR
@@ -67,11 +159,11 @@ COOKIES should be an instance of CL-COOKIE:COOKIE-JAR. Defaults to
LAZYBONES-CLIENT.SHARED:*HEADERS*))))
-(DEFUN POST--ONELINER ()
- "Adds a new oneliner entry to the wiki database."
+(DEFUN POST--MAKE-INVITE ()
+ "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 "/oneliner") (WHEN (OR) (LIST "?")))))
+ (FORMAT NIL "/make-invite") NIL)))
(IF LAZYBONES-CLIENT.SHARED:*BODY*
(DEXADOR:POST LAZYBONES-CLIENT.SHARED::REQ-STRING :CONTENT
LAZYBONES-CLIENT.SHARED:*BODY* :COOKIE-JAR
@@ -82,68 +174,69 @@ COOKIES should be an instance of CL-COOKIE:COOKIE-JAR. Defaults to
LAZYBONES-CLIENT.SHARED:*HEADERS*))))
-(DEFUN PUT--ONELINER-ONELINER (ONELINER)
- "Updates a oneliner entry in the wiki database."
+(DEFUN POST--REVOKE-CONTRIBUTOR (CONTRIBUTOR)
+ "A contributor can revoke their own access (if for some reason their
+ API key ends up out of their control), or an admin can revoke
+ anybody's access token, forcing the to re-authenticate."
(LET ((LAZYBONES-CLIENT.SHARED::REQ-STRING
(APPLY #'CONCATENATE 'STRING LAZYBONES-CLIENT.SHARED:*HOST*
- (FORMAT NIL "/oneliner/~a" ONELINER) (WHEN (OR) (LIST "?")))))
+ (FORMAT NIL "/revoke/~a" CONTRIBUTOR) NIL)))
(IF LAZYBONES-CLIENT.SHARED:*BODY*
- (DEXADOR:PUT LAZYBONES-CLIENT.SHARED::REQ-STRING :CONTENT
+ (DEXADOR:POST 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
+ (DEXADOR:POST LAZYBONES-CLIENT.SHARED::REQ-STRING :COOKIE-JAR
LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS
LAZYBONES-CLIENT.SHARED:*HEADERS*))))
-(DEFUN GET--SEARCH
- (&KEY COMMANDS KEYWORDS LIMIT PAGE NEXTPAGE NOTFLAGGED ONLYAUDITED)
- "A search endpoint returning a JSON encoded array of Oneliner Entries.
+(DEFUN POST--TOKEN-CONTRIBUTOR (CONTRIBUTOR &KEY PASSWORD)
+ "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 "/token/~a" CONTRIBUTOR)
+ (WHEN (OR PASSWORD)
+ (LIST "?"
+ (IF PASSWORD
+ (CONCATENATE 'STRING (SYMBOL-NAME 'PASSWORD) "="
+ (FORMAT NIL "~a" PASSWORD))
+ ""))))))
+ (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*))))
+
-**Note**: either command or keywords are required.
-"
+(DEFUN POST--REDEEM-INVITE (INVITE &KEY USERNAME PASSWORD1 PASSWORD2)
+ "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 "/search")
- (WHEN
- (OR COMMANDS KEYWORDS LIMIT PAGE NEXTPAGE NOTFLAGGED
- ONLYAUDITED)
+ (FORMAT NIL "/redeem/~a" INVITE)
+ (WHEN (OR USERNAME PASSWORD1 PASSWORD2)
(LIST "?"
- (IF COMMANDS
- (CONCATENATE 'STRING (SYMBOL-NAME 'COMMANDS) "="
- (FORMAT NIL "~a" COMMANDS))
+ (IF USERNAME
+ (CONCATENATE 'STRING (SYMBOL-NAME 'USERNAME) "="
+ (FORMAT NIL "~a" USERNAME))
"")
- (IF KEYWORDS
- (CONCATENATE 'STRING "&" (SYMBOL-NAME 'KEYWORDS)
- "=" (FORMAT NIL "~a" KEYWORDS))
+ (IF PASSWORD1
+ (CONCATENATE 'STRING "&" (SYMBOL-NAME 'PASSWORD1)
+ "=" (FORMAT NIL "~a" PASSWORD1))
"")
- (IF LIMIT
- (CONCATENATE 'STRING "&" (SYMBOL-NAME 'LIMIT) "="
- (FORMAT NIL "~a" LIMIT))
- "")
- (IF PAGE
- (CONCATENATE 'STRING "&" (SYMBOL-NAME 'PAGE) "="
- (FORMAT NIL "~a" PAGE))
- "")
- (IF NEXTPAGE
- (CONCATENATE 'STRING "&" (SYMBOL-NAME 'NEXTPAGE)
- "=" (FORMAT NIL "~a" NEXTPAGE))
- "")
- (IF NOTFLAGGED
- (CONCATENATE 'STRING "&" (SYMBOL-NAME 'NOTFLAGGED)
- "=" (FORMAT NIL "~a" NOTFLAGGED))
- "")
- (IF ONLYAUDITED
- (CONCATENATE 'STRING "&" (SYMBOL-NAME 'ONLYAUDITED)
- "=" (FORMAT NIL "~a" ONLYAUDITED))
+ (IF PASSWORD2
+ (CONCATENATE 'STRING "&" (SYMBOL-NAME 'PASSWORD2)
+ "=" (FORMAT NIL "~a" PASSWORD2))
""))))))
(IF LAZYBONES-CLIENT.SHARED:*BODY*
- (DEXADOR:GET LAZYBONES-CLIENT.SHARED::REQ-STRING :CONTENT
+ (DEXADOR:POST LAZYBONES-CLIENT.SHARED::REQ-STRING :CONTENT
LAZYBONES-CLIENT.SHARED:*BODY* :COOKIE-JAR
LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS
LAZYBONES-CLIENT.SHARED:*HEADERS*)
- (DEXADOR:GET LAZYBONES-CLIENT.SHARED::REQ-STRING :COOKIE-JAR
+ (DEXADOR:POST LAZYBONES-CLIENT.SHARED::REQ-STRING :COOKIE-JAR
LAZYBONES-CLIENT.SHARED:*COOKIES* :HEADERS
LAZYBONES-CLIENT.SHARED:*HEADERS*))))
diff --git a/src/main.lisp b/src/main.lisp
index 6c64ce2..0b33a6e 100644
--- a/src/main.lisp
+++ b/src/main.lisp
@@ -1,7 +1,8 @@
;;;; main.lisp -- oneliners.cli entrypoint
(defpackage oneliners.cli
- (:use :cl))
+ (:use :cl)
+ (:local-nicknames (#:api #:oneliners.api-client)))
(in-package :oneliners.cli)
;;; CLI OPTIONS
@@ -30,10 +31,7 @@
:arg-parser #'parse-integer)
(:name :not-flagged
:description "Filter flagged oneliners from the search results"
- :long "not-flagged")
- (:name :audited-only
- :description "Filter unaudited oneliners from the search results"
- :long "audited-only"))
+ :long "not-flagged"))
(defparameter +help-suffix+
"Unless RESULT is an integer, search for oneliners that involve each command in COMMANDS.
@@ -61,7 +59,7 @@ E.g.
(defun last-search-file ()
(merge-pathnames ".last_oneliners_search" (user-homedir-pathname)))
-;;; UTILITIES
+;;; RUNNING COMMANDS
(defun parent-process-name ()
"Prints the name of the parent process of the current process."
@@ -104,3 +102,16 @@ printed to OUTPUT-STREAM. "
(loop while (listen shell-output)
do (princ (read-line shell-output) output-stream)
(terpri output-stream))))))
+
+;;; main
+
+(defun main ()
+ (handler-case
+ (multiple-value-bind (options free-args) (opts:get-opts)
+ (print (list :options options :free-args free-args))
+ (terpri)
+ (uiop:quit))
+ (unix-opts:unknown-option (err)
+ (declare (ignore err))
+ (princ (help-text))
+ (terpri))))