aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sx-method.el74
-rw-r--r--sx-request.el65
2 files changed, 78 insertions, 61 deletions
diff --git a/sx-method.el b/sx-method.el
index e9c4f60..feebd84 100644
--- a/sx-method.el
+++ b/sx-method.el
@@ -25,32 +25,66 @@
(require 'json)
(require 'url)
(require 'sx)
+(require 'sx-auth)
(require 'sx-request)
(require 'sx-filter)
-(defun sx-method-call
- (method &optional keyword-arguments filter need-auth use-post silent)
- "Call METHOD with KEYWORD-ARGUMENTS using FILTER.
+(cl-defun sx-method-call (method &key id
+ submethod
+ keywords
+ (filter 'none)
+ auth
+ (url-method "GET")
+ (site sx-site-default))
+ "Call METHOD with additional keys.
-If NEED-AUTH is non-nil, an auth-token is required. If 'WARN,
-warn the user `(user-error ...)' if they do not have an AUTH
-token set.
-
-If USE-POST is non-nil, use `POST' rather than `GET' for passing
-arguments.
-
-If SILENT is non-nil, no messages will be printed.
+:ID is the id associated with a question, answer, comment, post or
+user.
+:SUBMETHOD is the additional segments of the method.
+:KEYWORDS are the api parameters.
+:FILTER is the set of filters to control the returned information
+:AUTH defines how to act if the method or filters require
+authentication.
+:URL-METHOD is either \"POST\" or \"GET\"
+:SITE is the api parameter specifying the site.
Return the entire response as a complex alist."
- (sx-request-make
- method
- (cons (cons 'filter
- (sx-filter-get-var
- (cond (filter filter)
- ((boundp 'stack-filter) stack-filter))))
- keyword-arguments)
- need-auth
- use-post))
+ (let ((access-token (sx-cache-get 'auth))
+ (method-auth (sx-auth--method-p method submethod))
+ (filter-auth (sx-auth--filter-p filter))
+ (full-method (concat (format "%s" method)
+ (when id
+ (format "/%s" id))
+ (when submethod
+ (format "/%s" submethod))))
+ (call 'sx-request-make))
+ (lwarn "sx-call-method" :warning "A: %S T: %S. M: %S,%s. F: %S" (equal 'warn auth)
+ access-token method-auth full-method filter-auth)
+ (unless access-token
+ (cond
+ ;; 1. Need auth and warn user (interactive use)
+ ((and method-auth (equal 'warn auth))
+ (user-error
+ "This request requires authentication. Please run `M-x sx-auth-authenticate' and try again."))
+ ;; 2. Need auth to populate UI, cannot provide subset
+ ((and method-auth auth)
+ (setq call 'sx-request-fallback))
+ ;; 3. Need auth for type. Use auth-less filter.
+ ((and filter-auth auth)
+ (setq filter filter-auth))
+ ;; 4. Requires auth but no value set for auth
+ ((and (or filter-auth method-auth) (not auth))
+ (error "This request requires authentication."))))
+ ;; Concatenate all parameters now that filter is ensured.
+ (setq parameters
+ (cons `(site . ,site)
+ (cons (cons 'filter
+ (sx-filter-get-var filter))
+ keywords)))
+ (funcall call
+ full-method
+ parameters
+ url-method)))
(provide 'sx-method)
;;; sx-method.el ends here
diff --git a/sx-request.el b/sx-request.el
index d982057..6673e48 100644
--- a/sx-request.el
+++ b/sx-request.el
@@ -71,19 +71,16 @@ number of requests left every time it finishes a call.")
;;; Making Requests
(defun sx-request-make
- (method &optional args need-auth use-post silent)
- (let ((url-automatic-caching sx-request-cache-p)
- (url-inhibit-uncompression t)
- (silent (or silent sx-request-silent-p))
- (request-method (if use-post "POST" "GET"))
- (request-args
- (sx-request--build-keyword-arguments args nil need-auth))
- (request-url (concat sx-request-api-root method)))
- (unless silent (sx-message "Request: %S" request-url))
- (let ((response-buffer (sx-request--request request-url
- request-args
- request-method
- silent)))
+ (method &optional args request-method)
+ (let* ((url-automatic-caching sx-request-cache-p)
+ (url-inhibit-uncompression t)
+ (url-request-data (sx-request--build-keyword-arguments args
+ nil))
+ (request-url (concat sx-request-api-root method))
+ (url-request-method request-method)
+ (url-request-extra-headers
+ '(("Content-Type" . "application/x-www-form-urlencoded")))
+ (response-buffer (url-retrieve-synchronously request-url)))
(if (not response-buffer)
(error "Something went wrong in `url-retrieve-synchronously'")
(with-current-buffer response-buffer
@@ -115,23 +112,21 @@ number of requests left every time it finishes a call.")
sx-request-remaining-api-requests-message-threshold)
(sx-message "%d API requests reamining"
sx-request-remaining-api-requests))
- (sx-encoding-clean-content-deep .items))))))))
+ (sx-encoding-clean-content-deep .items)))))))
+
+(defun sx-request-fallback (method &optional args request-method)
+ "Fallback method when authentication is not available.
+This is for UI generation when the associated API call would
+require authentication.
+
+Currently returns nil."
+ nil)
;;; Support Functions
-(defun sx-request--request (url args method silent)
- (let ((url-request-method method)
- (url-request-extra-headers
- '(("Content-Type" . "application/x-www-form-urlencoded")))
- (url-request-data args))
- (cond
- ((equal '(24 . 4) (cons emacs-major-version emacs-minor-version))
- (url-retrieve-synchronously url silent))
- (t (url-retrieve-synchronously url)))))
-
(defun sx-request--build-keyword-arguments (alist &optional
- kv-value-sep need-auth)
+ kv-value-sep)
"Build a \"key=value&key=value&...\"-style string with the elements
of ALIST. If any value in the alist is `nil', that pair will not
be included in the return. If you wish to pass a notion of
@@ -139,23 +134,11 @@ false, use the symbol `false'. Each element is processed with
`sx--thing-as-string'."
;; Add API key to list of arguments, this allows for increased quota
;; automatically.
- (let* ((warn (equal need-auth 'warn))
- (api-key (cons "key" sx-request-api-key))
- (auth
- (let ((auth (car (sx-cache-get 'auth))))
- (cond
- (auth)
- ;; Pass user error when asking to warn
- (warn
- (user-error
- "This query requires authentication. Please run `M-x sx-auth-authenticate' and try again."))
- ((not auth)
- (lwarn "stack-mode" :debug
- "This query requires authentication")
- nil)))))
+ (let ((api-key (cons "key" sx-request-api-key))
+ (auth (car (sx-cache-get 'auth))))
(push api-key alist)
- (if (and need-auth auth)
- (push auth alist))
+ (when auth
+ (push auth alist))
(mapconcat
(lambda (pair)
(concat