From 8f4586dbf863ef1ca3fe3c8b13e134ddb338c128 Mon Sep 17 00:00:00 2001 From: SqrtMinusOne Date: Sat, 7 Aug 2021 13:08:25 +0300 Subject: [PATCH] refactor: use error --- lyrics-fetcher-genius.el | 132 +++++++++++++++++++-------------------- lyrics-fetcher.el | 91 ++++++++++++++++----------- 2 files changed, 120 insertions(+), 103 deletions(-) diff --git a/lyrics-fetcher-genius.el b/lyrics-fetcher-genius.el index ca0a0ce..ef53d17 100644 --- a/lyrics-fetcher-genius.el +++ b/lyrics-fetcher-genius.el @@ -78,20 +78,20 @@ successful, CALLBACK will be called with the result. SYNC determines whether the request is syncronous. The parameter is useful when it is neccessary to ask user for something right after the request." - (if (string-empty-p lyrics-fetcher-genius-access-token) - (message "Genius client access token not set!") - (message "Sending a query to genius API...") - (request "https://api.genius.com/search" - :params `(("q" . ,(lyrics-fetcher--genius-format-query track)) - ("access_token" . ,lyrics-fetcher-genius-access-token)) - :parser 'json-read - :sync sync - :success (cl-function - (lambda (&key data &allow-other-keys) - (funcall callback data))) - :error (cl-function - (lambda (&key error-thrown &allow-other-keys) - (message "Error!: %S" error-thrown)))))) + (when (string-empty-p lyrics-fetcher-genius-access-token) + (error "Genius client access token not set!")) + (message "Sending a query to genius API...") + (request "https://api.genius.com/search" + :params `(("q" . ,(lyrics-fetcher--genius-format-query track)) + ("access_token" . ,lyrics-fetcher-genius-access-token)) + :parser 'json-read + :sync sync + :success (cl-function + (lambda (&key data &allow-other-keys) + (funcall callback data))) + :error (cl-function + (lambda (&key error-thrown &allow-other-keys) + (message "Error!: %S" error-thrown))))) (defun lyrics-fetcher--genius-format-query (track) "Format track to genius.com query. @@ -119,31 +119,31 @@ contains `info-albumartist' or `info-artist' and `info-title'" If ASK is non-nil, prompt user for a choice, otherwise select the first song." - (if (not (= (cdr (assoc 'status (assoc 'meta data))) 200)) - (message "Error: %" (cdr (assoc 'message (assoc 'meta data)))) - (let* ((results (cdr (assoc 'hits (assoc 'response data)))) - (results-songs (seq-filter - (lambda (entry) - (string-equal (cdr (assoc 'type entry)) "song")) - results))) - (if (seq-empty-p results-songs) - (message "Error: no results!") - (cdr - (if ask - (let ((results-songs-for-select - (mapcar - (lambda (entry) - (cons (lyrics-fetcher--genius-format-song-title entry) - (assoc key (assoc 'result entry)))) - results-songs))) - (cdr - (assoc - (completing-read - "Pick a result: " - results-songs-for-select - nil t) - results-songs-for-select))) - (assoc key (assoc 'result (car results-songs))))))))) + (when (not (= (cdr (assoc 'status (assoc 'meta data))) 200)) + (error "Error: %" (cdr (assoc 'message (assoc 'meta data))))) + (let* ((results (cdr (assoc 'hits (assoc 'response data)))) + (results-songs (seq-filter + (lambda (entry) + (string-equal (cdr (assoc 'type entry)) "song")) + results))) + (when (seq-empty-p results-songs) + (error "Error: no results!")) + (cdr + (if ask + (let ((results-songs-for-select + (mapcar + (lambda (entry) + (cons (lyrics-fetcher--genius-format-song-title entry) + (assoc key (assoc 'result entry)))) + results-songs))) + (cdr + (assoc + (completing-read + "Pick a result: " + results-songs-for-select + nil t) + results-songs-for-select))) + (assoc key (assoc 'result (car results-songs))))))) (defun lyrics-fetcher--genius-fetch-lyrics (url callback &optional sync) "Fetch lyrics from genius.com page at URL and call CALLBACK with result. @@ -225,33 +225,33 @@ DATA should be a response from GET /songs/:id. The file will be saved to FOLDER and will be name \"cover_full.\". CALLBACK will be called with the path to the resulting file." - (if (not (= (cdr (assoc 'status (assoc 'meta data))) 200)) - (message "Error: %" (cdr (assoc 'message (assoc 'meta data)))) - (let ((url (cdr - (assoc 'cover_art_url - (assoc 'album - (assoc 'song - (assoc 'response data))))))) - (if (not url) - (message "Album cover not found") - (message "Downloading the cover image...") - (request url - :encoding 'binary - :complete - (cl-function - (lambda (&key data &allow-other-keys) - (let ((filename - (concat folder "cover_large" (url-file-extension url)))) - (with-temp-file filename - (toggle-enable-multibyte-characters) - (set-buffer-file-coding-system 'raw-text) - (seq-doseq (char data) - (insert char))) - (funcall callback filename)))) - :error - (cl-function - (lambda (&key error-thrown &allow-other-keys) - (message "Error!: %S" error-thrown)))))))) + (when (not (= (cdr (assoc 'status (assoc 'meta data))) 200)) + (error "Error: %" (cdr (assoc 'message (assoc 'meta data))))) + (let ((url (cdr + (assoc 'cover_art_url + (assoc 'album + (assoc 'song + (assoc 'response data))))))) + (if (not url) + (message "Album cover not found") + (message "Downloading the cover image...") + (request url + :encoding 'binary + :complete + (cl-function + (lambda (&key data &allow-other-keys) + (let ((filename + (concat folder "cover_large" (url-file-extension url)))) + (with-temp-file filename + (toggle-enable-multibyte-characters) + (set-buffer-file-coding-system 'raw-text) + (seq-doseq (char data) + (insert char))) + (funcall callback filename)))) + :error + (cl-function + (lambda (&key error-thrown &allow-other-keys) + (message "Error!: %S" error-thrown))))))) (provide 'lyrics-fetcher-genius) ;;; lyrics-fetcher-genius.el ends here diff --git a/lyrics-fetcher.el b/lyrics-fetcher.el index 0944bb6..0cd6e4b 100644 --- a/lyrics-fetcher.el +++ b/lyrics-fetcher.el @@ -173,34 +173,34 @@ is non-nil, then ask the user to select a matching song. This may be useful if there are multiple tracks with similar names, and the top one isn’t the one required." (interactive) - (when (not track) + (unless track (setq track (funcall lyrics-fetcher-current-track-method))) - (if (not track) - (message "Error: no track found!") - (let ((song-name (funcall lyrics-fetcher-format-song-name-method track)) - (file-name (funcall lyrics-fetcher-format-file-name-method track)) - ;; The function is indented to be called both interactively - ;; and via recursion in asyncronous callbacks, during with - ;; `current-prefix-arg' will be unset. So this is necessary - ;; to pass the behavior down the recursive calls. - (force-fetch (or force-fetch (member (prefix-numeric-value current-prefix-arg) '(4 16)))) - (sync (or sync (member (prefix-numeric-value current-prefix-arg) '(16))))) - (if (and (not force-fetch) (lyrics-fetcher--lyrics-saved-p file-name)) - (progn - (message "Found fetched lyrics for: %s" song-name) - (when callback - (funcall callback file-name)) - (unless suppress-open - (lyrics-fetcher--open-lyrics file-name track))) - (funcall - lyrics-fetcher-fetch-method track - (lambda (result) - (lyrics-fetcher--save-lyrics result file-name) - (unless suppress-open - (lyrics-fetcher--open-lyrics file-name track)) - (when callback - (funcall callback file-name))) - sync))))) + (unless track + (error "Error: no track found!")) + (let ((song-name (funcall lyrics-fetcher-format-song-name-method track)) + (file-name (funcall lyrics-fetcher-format-file-name-method track)) + ;; The function is indented to be called both interactively + ;; and via recursion in asyncronous callbacks, during with + ;; `current-prefix-arg' will be unset. So this is necessary + ;; to pass the behavior down the recursive calls. + (force-fetch (or force-fetch (member (prefix-numeric-value current-prefix-arg) '(4 16)))) + (sync (or sync (member (prefix-numeric-value current-prefix-arg) '(16))))) + (if (and (not force-fetch) (lyrics-fetcher--lyrics-saved-p file-name)) + (progn + (message "Found fetched lyrics for: %s" song-name) + (when callback + (funcall callback file-name)) + (unless suppress-open + (lyrics-fetcher--open-lyrics file-name track))) + (funcall + lyrics-fetcher-fetch-method track + (lambda (result) + (lyrics-fetcher--save-lyrics result file-name) + (unless suppress-open + (lyrics-fetcher--open-lyrics file-name track)) + (when callback + (funcall callback file-name))) + sync)))) (defun lyrics-fetcher-show-lyrics-query (query) "Fetch lyrics from a text QUERY. @@ -253,7 +253,7 @@ the same way as `lyrics-fetcher-show-lyrics'." (interactive) (let ((data (emms-browser-bdata-at-point))) (if (not data) - (message "Nothing is found at point!") + (error "Nothing is found at point!") (if (eq (cdr (assoc 'type data)) 'info-title) (lyrics-fetcher-show-lyrics (cdadr (assoc 'data data))) (lyrics-fetcher--fetch-many @@ -280,10 +280,23 @@ the same way as `lyrics-fetcher-show-lyrics'." (interactive) (let ((data (emms-browser-bdata-at-point))) (if (not data) - (message "Nothing is found at point!") + (error "Nothing is found at point!") (lyrics-fetcher--fetch-cover-many (lyrics-fetcher--emms-extract-albums data))))) +(defun lyrics-fetcher-emms-browser-open-large-cover-at-point () + "Open large_cover for the current point in EMMS browser." + (interactive) + (let ((tracks (lyrics-fetcher--emms-extract-albums (emms-browser-bdata-at-point)))) + (when (seq-empty-p tracks) + (error "Nothing is found at point!")) + (let ((cover-file (lyrics-fetcher--get-cover-in-directory + (f-dirname (cdr (assoc 'name (car tracks))))))) + (if (not cover-file) + (error "Cover not found") + (start-process "cover-open" nil + "xdg-open" cover-file))))) + (defun lyrics-fetcher--emms-extract-albums (bdata) "Extract a list of sample song alists from each album in BDATA. @@ -387,17 +400,13 @@ If SYNC is non-nil, prompt user for a matching track. If FORCE-FETCH is non-nil, always fetch regardless of whether the file exists." - (let ((covers-found (f-entries - (f-dirname (cdr (assoc 'name track))) - (lambda (f) - (string-match-p - (rx (* nonl) "cover_large" (* nonl)) f))))) - (if (and (not force-fetch) - (not (seq-empty-p covers-found))) + (let ((cover-found (lyrics-fetcher--get-cover-in-directory + (f-dirname (cdr (assoc 'name track)))))) + (if (and (not force-fetch) cover-found) (progn (message "Cover already downloaded") (when callback - (funcall callback (car covers-found)))) + (funcall callback cover-found))) (funcall lyrics-fetcher-download-cover-method track (lambda (filename) @@ -409,6 +418,14 @@ file exists." (concat (f-dirname (cdr (assoc 'name track))) "/") sync)))) +(defun lyrics-fetcher--get-cover-in-directory (dirname) + "Get a path to the large cover file in DIRNAME if one exists." + (car (f-entries + dirname + (lambda (f) + (string-match-p + (rx (* nonl) "cover_large" (* nonl)) f))))) + (defun lyrics-fetcher--generate-cover-sizes (filename) "Create small and medium versions of FILENAME.