From 40cc7b4d6470c0efb5214144f91a4ce1e1464ab2 Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Wed, 19 Nov 2014 17:09:54 -0500 Subject: Implement checking for filter and method authentication requirement. Currently no filter items are defined pending confirmation of which require it. --- sx-auth.el | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/sx-auth.el b/sx-auth.el index b470523..0f55814 100644 --- a/sx-auth.el +++ b/sx-auth.el @@ -41,6 +41,44 @@ This is needed to use your account to write questions, make comments, and read your inbox. Do not alter this unless you know what you are doing!") +(defvar sx-auth-method-auth '((me . t) + (inbox . t) + (notifications . t) + (events . t) + (posts (comments add)) + (comments delete + edit + flags + upvote) + (answers accept + delete + downvote + edit + flags + upvote) + (questions answers + add + close + delete + downvote + edit + favorite + flags + render + upvote + (unanswered my-tags))) + "List of methods that require auth. +Methods are of form (METHOD SUBMETHODS) where SUBMETHODS + is (METHOD METHOD METHOD ...). + +If all SUBMETHODS require auth or there are no submethods, form +will be (METHOD . t)") + +(defvar sx-auth-filter-auth '() + "List of filter types that require auth. +Keywords are of form (OBJECT TYPES) where TYPES is (FILTER FILTER +FILTER).") + (defun sx-auth-authenticate () "Authenticate this application. @@ -68,6 +106,36 @@ questions)." (error "You must enter this code to use this client fully")) (sx-cache-set 'auth `((access_token . ,sx-auth-access-token))))) +(defun sx-auth--method-p (method &optional submethod) + "Check if METHOD is one that may require authentication. +If it has `auth required` SUBMETHODs, return t." + (let ((method-auth (cdr (assoc method sx-auth-method-auth))) + ;; If the submethod has additional options, they may all be + ;; eligible, in which case we only need to check the `car'. + (sub-head (if (listp submethod) + (car submethod)))) + (and method-auth + (or + ;; All submethods require auth. + (eq t method-auth) + ;; All sub-submethods require auth. + (member sub-head method-auth) + ;; Specific submethod requires auth. + (member submethod method-auth)))))) + +;; Temporary solution. When we switch to pre-defined filters we will +;; have to change the logic to match against specific filters. +(defun sx-auth--filter-p (object &optional filter) + "Check if OBJECT is one that may require authentication. +If it has `auth required` FILTERs, return t." + (let ((object-auth (cdr (assoc object sx-auth-filter-auth)))) + (and object-auth + (or + ;; All elements of object require auth. + (eq t object-auth) + ;; Specific filters on object require auth. + (member filter object-auth)))))) + (provide 'sx-auth) ;;; sx-auth.el ends here -- cgit v1.2.3 From 7f041f830c8d1f9aaca0eb8a898070873668a4fd Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Thu, 20 Nov 2014 10:25:33 -0500 Subject: Fix filter logic to account for alist of properties. sx-auth-filter-auth now returns a filter that will not require auth for use when auth not available. Add a few known auth-required types. --- sx-auth.el | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/sx-auth.el b/sx-auth.el index 0f55814..8085098 100644 --- a/sx-auth.el +++ b/sx-auth.el @@ -74,7 +74,8 @@ Methods are of form (METHOD SUBMETHODS) where SUBMETHODS If all SUBMETHODS require auth or there are no submethods, form will be (METHOD . t)") -(defvar sx-auth-filter-auth '() +(defvar sx-auth-filter-auth '(question.upvoted + question.downvoted) "List of filter types that require auth. Keywords are of form (OBJECT TYPES) where TYPES is (FILTER FILTER FILTER).") @@ -125,16 +126,26 @@ If it has `auth required` SUBMETHODs, return t." ;; Temporary solution. When we switch to pre-defined filters we will ;; have to change the logic to match against specific filters. -(defun sx-auth--filter-p (object &optional filter) - "Check if OBJECT is one that may require authentication. -If it has `auth required` FILTERs, return t." - (let ((object-auth (cdr (assoc object sx-auth-filter-auth)))) - (and object-auth - (or - ;; All elements of object require auth. - (eq t object-auth) - ;; Specific filters on object require auth. - (member filter object-auth)))))) +(defun sx-auth--filter-p (filter) + "Check if FILTER contains properties that require authentication. +If it has `auth-required' properties, return a filter that has +removed those properties." + (let ((auth-filters (cl-remove-if #'nil + ;; Only retrieve the elements that + ;; are issues. + (mapcar (lambda (prop) + (car + (member prop + sx-auth-filter-auth))) + filter))) + (clean-filter)) + ;; Auth-filters is the filters that are issues + (when auth-filters + (setq clean-filter + (cl-remove-if (lambda (prop) + (member prop auth-filters)) + filter))) + clean-filter)) (provide 'sx-auth) ;;; sx-auth.el ends here -- cgit v1.2.3 From 52a8faf61568cb198727aad50d2ec4388a751348 Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Thu, 20 Nov 2014 10:27:44 -0500 Subject: Fix sx-auth--method-p to work correctly when there is no submethod specified. --- sx-auth.el | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sx-auth.el b/sx-auth.el index 8085098..e786466 100644 --- a/sx-auth.el +++ b/sx-auth.el @@ -109,7 +109,7 @@ questions)." (defun sx-auth--method-p (method &optional submethod) "Check if METHOD is one that may require authentication. -If it has `auth required` SUBMETHODs, return t." +If it has `auth-required' SUBMETHODs, or no submethod, return t." (let ((method-auth (cdr (assoc method sx-auth-method-auth))) ;; If the submethod has additional options, they may all be ;; eligible, in which case we only need to check the `car'. @@ -117,12 +117,14 @@ If it has `auth required` SUBMETHODs, return t." (car submethod)))) (and method-auth (or + ;; No submethod specified + (not submethod) ;; All submethods require auth. (eq t method-auth) ;; All sub-submethods require auth. (member sub-head method-auth) ;; Specific submethod requires auth. - (member submethod method-auth)))))) + (member submethod method-auth))))) ;; Temporary solution. When we switch to pre-defined filters we will ;; have to change the logic to match against specific filters. -- cgit v1.2.3 From 97dae4030bcfb3062bd0909f471f41b5967c88d2 Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Thu, 20 Nov 2014 12:58:53 -0500 Subject: Do not actually need to check for no submethods. Already tested for. --- sx-auth.el | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sx-auth.el b/sx-auth.el index e786466..bd8c206 100644 --- a/sx-auth.el +++ b/sx-auth.el @@ -115,10 +115,9 @@ If it has `auth-required' SUBMETHODs, or no submethod, return t." ;; eligible, in which case we only need to check the `car'. (sub-head (if (listp submethod) (car submethod)))) + (lwarn " sx-auth method" :debug "Method %s requires auth" method-auth) (and method-auth (or - ;; No submethod specified - (not submethod) ;; All submethods require auth. (eq t method-auth) ;; All sub-submethods require auth. -- cgit v1.2.3 From 2e2619d7b1ec9a5d7338c5ec224ac0ba920e017c Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Thu, 20 Nov 2014 12:59:17 -0500 Subject: Improve method for returning clean filter. Logic now verifies `include` if `include`,`exclude`,`base` is used. Otherwise verify entire filter. --- sx-auth.el | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/sx-auth.el b/sx-auth.el index bd8c206..e67f9a1 100644 --- a/sx-auth.el +++ b/sx-auth.el @@ -131,22 +131,31 @@ If it has `auth-required' SUBMETHODs, or no submethod, return t." "Check if FILTER contains properties that require authentication. If it has `auth-required' properties, return a filter that has removed those properties." - (let ((auth-filters (cl-remove-if #'nil - ;; Only retrieve the elements that - ;; are issues. - (mapcar (lambda (prop) - (car - (member prop - sx-auth-filter-auth))) - filter))) - (clean-filter)) - ;; Auth-filters is the filters that are issues + (let* ((incl-filter (if (listp filter) (car filter))) + (rest-filter (if incl-filter (cdr filter))) + (auth-filters (cl-remove-if #'nil + ;; Only retrieve the elements that + ;; are issues. + (mapcar (lambda (prop) + (car + (member prop + sx-auth-filter-auth))) + (or incl-filter filter)))) + clean-filter out-filter) + (lwarn "sx-auth filter" :debug "Filter: %S" filter) + ;; Auth-filters is the filters that are issues (when auth-filters (setq clean-filter (cl-remove-if (lambda (prop) (member prop auth-filters)) - filter))) - clean-filter)) + (or incl-filter filter)))) + (if (and incl-filter clean-filter) + (setq out-filter + (cons clean-filter rest-filter)) + (setq out-filter clean-filter)) + (lwarn "sx-auth filter2" :debug "Filter property %s requires auth. %S" + auth-filters out-filter) + out-filter)) (provide 'sx-auth) ;;; sx-auth.el ends here -- cgit v1.2.3 From 534b1ab1f70dbc9029cd76d4ac627c1792e69ed9 Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Thu, 20 Nov 2014 13:06:01 -0500 Subject: sx-method-call rewritten and associated improvements in sx-request. Now requires `'sx-auth` to account for authentication. (sx-method-call) is now defined using `cl-defun` and uses keys rather than positional arguments. Authentication logic is performed in `sx-method-call` to ensure commands are only passed on once they are needed. When access token is available: - Filters will be used as provided - Methods will be called When access token is unavailable: - Filters will downgrade to only request object that do not require auth. - Methods will instead use `sx-request-fallback` and return nil. If auth is not specified but is required, `sx-method-call` will throw an error. If auth is specified as `'warn`, `user-error` will be called. (sx-request--build-keyword-arguments) has been simplified. It will always pass an available access_token (api indicates doing so will use a user/key quota rather than simply key quota). (sx-request-make) now performs url retrieval directly. Query construction is all performed by `sx-method-call`. --- sx-method.el | 74 +++++++++++++++++++++++++++++++++++++++++++---------------- sx-request.el | 65 +++++++++++++++++++-------------------------------- 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 -- cgit v1.2.3 From 6b94d5f8c2c5b187a458c1256d9b496a0378770f Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Thu, 20 Nov 2014 13:17:48 -0500 Subject: Remove default site specification. Defaults to nil if not specified (for network-wide searches). Remove :warning, drop back to :debug --- sx-method.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sx-method.el b/sx-method.el index feebd84..5499fb1 100644 --- a/sx-method.el +++ b/sx-method.el @@ -35,7 +35,7 @@ (filter 'none) auth (url-method "GET") - (site sx-site-default)) + site) "Call METHOD with additional keys. :ID is the id associated with a question, answer, comment, post or @@ -58,7 +58,7 @@ Return the entire response as a complex alist." (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) + (lwarn "sx-call-method" :debug "A: %S T: %S. M: %S,%s. F: %S" (equal 'warn auth) access-token method-auth full-method filter-auth) (unless access-token (cond -- cgit v1.2.3 From e63d08fe75cff6e4b713a477408203351cc14e57 Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Thu, 20 Nov 2014 13:18:44 -0500 Subject: Uses of `sx-method-call` have been updated to use new format. sx-question now includes 2 authentication requiring parameters, `question.upvoted` and `question.downvoted`. These will only be used if access token exists. sx-favorites still uses site-workaround pending #82. --- sx-favorites.el | 8 ++++---- sx-networks.el | 9 +++++---- sx-question.el | 20 +++++++++++--------- sx-site.el | 7 ++++--- 4 files changed, 24 insertions(+), 20 deletions(-) diff --git a/sx-favorites.el b/sx-favorites.el index 3aa96dd..55ebf49 100644 --- a/sx-favorites.el +++ b/sx-favorites.el @@ -55,10 +55,10 @@ Added as hook to initialization." (defun sx-favorites--retrieve-favorites (site) "Obtain list of starred QUESTION_IDs for SITE." - (sx-method-call (format "me/favorites?site=%s" site) - nil - sx-favorite-list-filter - 'warn)) + (sx-method-call 'me + :submethod (format "favorites?site=%s" site) + :filter sx-favorite-list-filter + :auth 'warn)) (defun sx-favorites--update-site-favorites (site) "Update list of starred QUESTION_IDs for SITE. diff --git a/sx-networks.el b/sx-networks.el index 755d62c..ff5a630 100644 --- a/sx-networks.el +++ b/sx-networks.el @@ -67,10 +67,11 @@ If cache is not available, retrieve current data." Sets cache and then uses `sx-network--get-associated' to update the variables." (sx-cache-set 'network-user - (sx-method-call "me/associated" - '((types . (main_site meta_site))) - sx-network--user-filter - 'warn)) + (sx-method-call 'me + :submethod 'associated + :keywords '((types . (main_site meta_site))) + :filter sx-network--user-filter + :auth 'warn)) (sx-network--get-associated)) (defun sx-network--initialize () diff --git a/sx-question.el b/sx-question.el index 972e9d9..d040bad 100644 --- a/sx-question.el +++ b/sx-question.el @@ -35,6 +35,8 @@ question.last_editor question.accepted_answer_id question.link + question.upvoted + question.downvoted user.display_name comment.owner comment.body_markdown @@ -50,18 +52,18 @@ "Get the page PAGE of questions from SITE." (mapcar (lambda (question) (cons (cons 'site site) question)) - (sx-method-call - "questions" - `((site . ,site) - (page . ,page)) - sx-question-browse-filter))) + (sx-method-call 'questions + :keywords `((page . ,page)) + :site site + :auth t + :filter sx-question-browse-filter))) (defun sx-question-get-question (site id) "Get the question ID from SITE." - (let ((res (sx-method-call - (format "questions/%s" id) - `((site . ,site)) - sx-question-browse-filter))) + (let ((res (sx-method-call 'questions + :id id + :site site + :filter sx-question-browse-filter))) (if (vectorp res) (elt res 0) (error "Couldn't find question %S in %S" id site)))) diff --git a/sx-site.el b/sx-site.el index 6bef91f..6928ea8 100644 --- a/sx-site.el +++ b/sx-site.el @@ -48,9 +48,10 @@ (defun sx-site--get-site-list () (sx-cache-get 'site-list - '(sx-method-call - "sites" '((pagesize . 999)) - sx-site-browse-filter))) + '(sx-method-call 'sites + :keywords '((pagesize . 999)) + :filter sx-site-browse-filter + :auth 'warn))) (defcustom sx-site-favorites nil -- cgit v1.2.3 From 81e662bb2572c69d0cdd42fddd9d09acf17f9027 Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Thu, 20 Nov 2014 13:48:00 -0500 Subject: Fix auth settings in calls. Do not use 'warn in non-interactive commands. --- sx-favorites.el | 2 +- sx-networks.el | 2 +- sx-question.el | 1 + sx-site.el | 3 +-- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sx-favorites.el b/sx-favorites.el index 55ebf49..f254137 100644 --- a/sx-favorites.el +++ b/sx-favorites.el @@ -58,7 +58,7 @@ Added as hook to initialization." (sx-method-call 'me :submethod (format "favorites?site=%s" site) :filter sx-favorite-list-filter - :auth 'warn)) + :auth t)) (defun sx-favorites--update-site-favorites (site) "Update list of starred QUESTION_IDs for SITE. diff --git a/sx-networks.el b/sx-networks.el index ff5a630..110f975 100644 --- a/sx-networks.el +++ b/sx-networks.el @@ -71,7 +71,7 @@ the variables." :submethod 'associated :keywords '((types . (main_site meta_site))) :filter sx-network--user-filter - :auth 'warn)) + :auth t)) (sx-network--get-associated)) (defun sx-network--initialize () diff --git a/sx-question.el b/sx-question.el index d040bad..75f786c 100644 --- a/sx-question.el +++ b/sx-question.el @@ -63,6 +63,7 @@ (let ((res (sx-method-call 'questions :id id :site site + :auth t :filter sx-question-browse-filter))) (if (vectorp res) (elt res 0) diff --git a/sx-site.el b/sx-site.el index 6928ea8..3966a9f 100644 --- a/sx-site.el +++ b/sx-site.el @@ -50,8 +50,7 @@ 'site-list '(sx-method-call 'sites :keywords '((pagesize . 999)) - :filter sx-site-browse-filter - :auth 'warn))) + :filter sx-site-browse-filter))) (defcustom sx-site-favorites nil -- cgit v1.2.3 From fd15926704a1eac86e87d994b1dc0a552077a2ac Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Thu, 20 Nov 2014 13:54:03 -0500 Subject: Do not initialize Stack-Mode. Initializing will retrieve user preferences/authentication. We do not need this. --- test/tests.el | 1 + 1 file changed, 1 insertion(+) diff --git a/test/tests.el b/test/tests.el index 6a48257..6ddb65d 100644 --- a/test/tests.el +++ b/test/tests.el @@ -29,6 +29,7 @@ (should (string-match ,regexp line)))) (setq + sx-initialized t) sx-request-remaining-api-requests-message-threshold 50000 debug-on-error t sx-request-silent-p nil -- cgit v1.2.3 From 69632894d25a916b14d3cb1602da057e4fd95c08 Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Thu, 20 Nov 2014 13:57:59 -0500 Subject: Typo fix. --- test/tests.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/tests.el b/test/tests.el index 6ddb65d..d53cd31 100644 --- a/test/tests.el +++ b/test/tests.el @@ -29,7 +29,7 @@ (should (string-match ,regexp line)))) (setq - sx-initialized t) + sx-initialized t sx-request-remaining-api-requests-message-threshold 50000 debug-on-error t sx-request-silent-p nil -- cgit v1.2.3 From a32e103ff075a81b34752e0027052e23a82c462b Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Thu, 20 Nov 2014 14:09:27 -0500 Subject: Properly return a nil entry when falling back sx-request-make returns a nested list (or vector of lists). Return `'(())` to ensure it is an acceptable response. --- sx-request.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sx-request.el b/sx-request.el index 6673e48..8686216 100644 --- a/sx-request.el +++ b/sx-request.el @@ -120,7 +120,7 @@ This is for UI generation when the associated API call would require authentication. Currently returns nil." - nil) + '(())) ;;; Support Functions -- cgit v1.2.3 From 91069a3b2fe9b800436c603f94186c2e34a212ac Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Fri, 21 Nov 2014 08:45:54 -0500 Subject: Update docstring to reflect uses of `AUTH`. --- sx-method.el | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sx-method.el b/sx-method.el index c5764cd..ee1f0b2 100644 --- a/sx-method.el +++ b/sx-method.el @@ -51,6 +51,21 @@ authentication. :URL-METHOD is either \"POST\" or \"GET\" :SITE is the api parameter specifying the site. +When AUTH is nil, it is assumed that no auth-requiring filters or +methods will be used. If they are an error will be signaled. This is +to ensure awareness of where auth is needed. + +When AUTH Is t, filters will automatically use a non-auth subset if +no `access_token' is available. Methods requiring auth will instead +use `sx-request-fallback' rather than have a failed API response. +This is meant to allow for UI pages where portions may require AUTH +but could still be used without authenticating (i.e a launch/home page). + +When AUTH is 'warn, methods will signal a `user-error'. This is meant +for interactive commands that absolutely require authentication +(submitting questions/answers, reading inbox, etc). Filters will +treat 'warn as equivalent to t. + Return the entire response as a complex alist." (let ((access-token (sx-cache-get 'auth)) (method-auth (sx-auth--method-p method submethod)) -- cgit v1.2.3 From 2c0bca36d2d1e13aa4ca0a83ef5af1f70bf76b4c Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Fri, 21 Nov 2014 08:54:20 -0500 Subject: Fix docstring/argument list ordering (mistake during merge). Fix `url-automatic-caching` to use `t` rather than `sx-request-cache-p` (used in tests only). --- sx-request.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sx-request.el b/sx-request.el index c667978..6b09988 100644 --- a/sx-request.el +++ b/sx-request.el @@ -92,7 +92,8 @@ number of requests left every time it finishes a call." ;;; Making Requests (defun sx-request-make - "Make a request to the API, executing METHOD with ARGS. + (method &optional args request-method) + "Make a request to the API, executing METHOD with ARGS. You should almost certainly be using `sx-method-call' instead of this function. REQUEST-METHOD is one of `GET' (default) or `POST'. @@ -113,8 +114,7 @@ then read with `json-read-from-string'. `sx-request-remaining-api-requests' is updated appropriately and the main content of the response is returned." - (method &optional args request-method) - (let* ((url-automatic-caching sx-request-cache-p) + (let* ((url-automatic-caching t) (url-inhibit-uncompression t) (url-request-data (sx-request--build-keyword-arguments args nil)) -- cgit v1.2.3 From 3c772002f24db89410b14d7a938ff12b23ac5580 Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Fri, 21 Nov 2014 10:29:27 -0500 Subject: Whitespace/indent fixup. --- sx-method.el | 76 ++++++++++++++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/sx-method.el b/sx-method.el index ee1f0b2..a1a2901 100644 --- a/sx-method.el +++ b/sx-method.el @@ -39,7 +39,7 @@ auth (url-method "GET") site) - "Call METHOD with additional keys. + "Call METHOD with additional keys. :ID is the id associated with a question, answer, comment, post or user. @@ -63,46 +63,46 @@ but could still be used without authenticating (i.e a launch/home page). When AUTH is 'warn, methods will signal a `user-error'. This is meant for interactive commands that absolutely require authentication -(submitting questions/answers, reading inbox, etc). Filters will + (submitting questions/answers, reading inbox, etc). Filters will treat 'warn as equivalent to t. Return the entire response as a complex alist." - (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" :debug "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))) + (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" :debug "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 -- cgit v1.2.3 From a62483526c336219424c9f7d03abbe2ba6516c53 Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Fri, 21 Nov 2014 10:29:49 -0500 Subject: Use `(declare (indent 1)) in `sx-method-call`. --- sx-method.el | 1 + 1 file changed, 1 insertion(+) diff --git a/sx-method.el b/sx-method.el index a1a2901..ed32b3d 100644 --- a/sx-method.el +++ b/sx-method.el @@ -67,6 +67,7 @@ for interactive commands that absolutely require authentication treat 'warn as equivalent to t. Return the entire response as a complex alist." + (declare (indent 1)) (let ((access-token (sx-cache-get 'auth)) (method-auth (sx-auth--method-p method submethod)) (filter-auth (sx-auth--filter-p filter)) -- cgit v1.2.3 From dc17d78972536c746be0c1ed66989a1509f5ad70 Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Fri, 21 Nov 2014 10:31:49 -0500 Subject: Use `\(` for ( at beginning of line in docstring. --- sx-method.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sx-method.el b/sx-method.el index ed32b3d..3eea5d7 100644 --- a/sx-method.el +++ b/sx-method.el @@ -63,7 +63,7 @@ but could still be used without authenticating (i.e a launch/home page). When AUTH is 'warn, methods will signal a `user-error'. This is meant for interactive commands that absolutely require authentication - (submitting questions/answers, reading inbox, etc). Filters will +\(submitting questions/answers, reading inbox, etc). Filters will treat 'warn as equivalent to t. Return the entire response as a complex alist." -- cgit v1.2.3 From 1d4dd3d3171895e66ab16948d2320b22841f582e Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Fri, 21 Nov 2014 12:10:57 -0500 Subject: Fix indentation following indent declaration. --- sx-favorites.el | 6 +++--- sx-networks.el | 8 ++++---- sx-question.el | 16 ++++++++-------- sx-site.el | 4 ++-- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/sx-favorites.el b/sx-favorites.el index c00d262..aaf2734 100644 --- a/sx-favorites.el +++ b/sx-favorites.el @@ -52,9 +52,9 @@ Added as hook to initialization." (defun sx-favorites--retrieve-favorites (site) "Obtain list of starred QUESTION_IDs for SITE." (sx-method-call 'me - :submethod (format "favorites?site=%s" site) - :filter sx-favorite-list-filter - :auth t)) + :submethod (format "favorites?site=%s" site) + :filter sx-favorite-list-filter + :auth t)) (defun sx-favorites--update-site-favorites (site) "Update list of starred QUESTION_IDs for SITE. diff --git a/sx-networks.el b/sx-networks.el index f5aa9f5..e4660af 100644 --- a/sx-networks.el +++ b/sx-networks.el @@ -64,10 +64,10 @@ Sets cache and then uses `sx-network--get-associated' to update the variables." (sx-cache-set 'network-user (sx-method-call 'me - :submethod 'associated - :keywords '((types . (main_site meta_site))) - :filter sx-network--user-filter - :auth t)) + :submethod 'associated + :keywords '((types . (main_site meta_site))) + :filter sx-network--user-filter + :auth t)) (sx-network--get-associated)) (defun sx-network--initialize () diff --git a/sx-question.el b/sx-question.el index c02cf62..c66d253 100644 --- a/sx-question.el +++ b/sx-question.el @@ -58,19 +58,19 @@ property. (mapcar (lambda (question) (cons (cons 'site site) question)) (sx-method-call 'questions - :keywords `((page . ,page)) - :site site - :auth t - :filter sx-question-browse-filter))) + :keywords `((page . ,page)) + :site site + :auth t + :filter sx-question-browse-filter))) (defun sx-question-get-question (site question-id) "Query SITE for a QUESTION-ID and return it. If QUESTION-ID doesn't exist on SITE, raise an error." (let ((res (sx-method-call 'questions - :id id - :site site - :auth t - :filter sx-question-browse-filter))) + :id id + :site site + :auth t + :filter sx-question-browse-filter))) (if (vectorp res) (elt res 0) (error "Couldn't find question %S in %S" diff --git a/sx-site.el b/sx-site.el index 065f113..04b5240 100644 --- a/sx-site.el +++ b/sx-site.el @@ -49,8 +49,8 @@ (sx-cache-get 'site-list '(sx-method-call 'sites - :keywords '((pagesize . 999)) - :filter sx-site-browse-filter))) + :keywords '((pagesize . 999)) + :filter sx-site-browse-filter))) (defcustom sx-site-favorites nil -- cgit v1.2.3 From 06cd4215de8d2e8680de74546984d9bdbc47b1d3 Mon Sep 17 00:00:00 2001 From: Jonathan Leech-Pepin Date: Fri, 21 Nov 2014 12:11:11 -0500 Subject: Whitespace fixup (spaces not tabs). --- sx-method.el | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/sx-method.el b/sx-method.el index 3eea5d7..04d973d 100644 --- a/sx-method.el +++ b/sx-method.el @@ -69,41 +69,41 @@ treat 'warn as equivalent to t. Return the entire response as a complex alist." (declare (indent 1)) (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)) + (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" :debug "A: %S T: %S. M: %S,%s. F: %S" (equal 'warn auth) - access-token method-auth full-method filter-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.")) + (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)) + (setq call 'sx-request-fallback)) ;; 3. Need auth for type. Use auth-less filter. ((and filter-auth auth) - (setq filter filter-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.")))) + (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))) + (cons `(site . ,site) + (cons (cons 'filter + (sx-filter-get-var filter)) + keywords))) (funcall call - full-method - parameters - url-method))) + full-method + parameters + url-method))) (provide 'sx-method) ;;; sx-method.el ends here -- cgit v1.2.3