mirror of
https://github.com/SqrtMinusOne/lyrics-fetcher.el.git
synced 2025-12-10 17:03:03 +03:00
refactor: use error
This commit is contained in:
parent
8c3df2bbe0
commit
8f4586dbf8
2 changed files with 120 additions and 103 deletions
|
|
@ -78,20 +78,20 @@ successful, CALLBACK will be called with the result.
|
||||||
SYNC determines whether the request is syncronous. The parameter
|
SYNC determines whether the request is syncronous. The parameter
|
||||||
is useful when it is neccessary to ask user for something right
|
is useful when it is neccessary to ask user for something right
|
||||||
after the request."
|
after the request."
|
||||||
(if (string-empty-p lyrics-fetcher-genius-access-token)
|
(when (string-empty-p lyrics-fetcher-genius-access-token)
|
||||||
(message "Genius client access token not set!")
|
(error "Genius client access token not set!"))
|
||||||
(message "Sending a query to genius API...")
|
(message "Sending a query to genius API...")
|
||||||
(request "https://api.genius.com/search"
|
(request "https://api.genius.com/search"
|
||||||
:params `(("q" . ,(lyrics-fetcher--genius-format-query track))
|
:params `(("q" . ,(lyrics-fetcher--genius-format-query track))
|
||||||
("access_token" . ,lyrics-fetcher-genius-access-token))
|
("access_token" . ,lyrics-fetcher-genius-access-token))
|
||||||
:parser 'json-read
|
:parser 'json-read
|
||||||
:sync sync
|
:sync sync
|
||||||
:success (cl-function
|
:success (cl-function
|
||||||
(lambda (&key data &allow-other-keys)
|
(lambda (&key data &allow-other-keys)
|
||||||
(funcall callback data)))
|
(funcall callback data)))
|
||||||
:error (cl-function
|
:error (cl-function
|
||||||
(lambda (&key error-thrown &allow-other-keys)
|
(lambda (&key error-thrown &allow-other-keys)
|
||||||
(message "Error!: %S" error-thrown))))))
|
(message "Error!: %S" error-thrown)))))
|
||||||
|
|
||||||
(defun lyrics-fetcher--genius-format-query (track)
|
(defun lyrics-fetcher--genius-format-query (track)
|
||||||
"Format track to genius.com query.
|
"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
|
If ASK is non-nil, prompt user for a choice, otherwise select the
|
||||||
first song."
|
first song."
|
||||||
(if (not (= (cdr (assoc 'status (assoc 'meta data))) 200))
|
(when (not (= (cdr (assoc 'status (assoc 'meta data))) 200))
|
||||||
(message "Error: %" (cdr (assoc 'message (assoc 'meta data))))
|
(error "Error: %" (cdr (assoc 'message (assoc 'meta data)))))
|
||||||
(let* ((results (cdr (assoc 'hits (assoc 'response data))))
|
(let* ((results (cdr (assoc 'hits (assoc 'response data))))
|
||||||
(results-songs (seq-filter
|
(results-songs (seq-filter
|
||||||
(lambda (entry)
|
(lambda (entry)
|
||||||
(string-equal (cdr (assoc 'type entry)) "song"))
|
(string-equal (cdr (assoc 'type entry)) "song"))
|
||||||
results)))
|
results)))
|
||||||
(if (seq-empty-p results-songs)
|
(when (seq-empty-p results-songs)
|
||||||
(message "Error: no results!")
|
(error "Error: no results!"))
|
||||||
(cdr
|
(cdr
|
||||||
(if ask
|
(if ask
|
||||||
(let ((results-songs-for-select
|
(let ((results-songs-for-select
|
||||||
(mapcar
|
(mapcar
|
||||||
(lambda (entry)
|
(lambda (entry)
|
||||||
(cons (lyrics-fetcher--genius-format-song-title entry)
|
(cons (lyrics-fetcher--genius-format-song-title entry)
|
||||||
(assoc key (assoc 'result entry))))
|
(assoc key (assoc 'result entry))))
|
||||||
results-songs)))
|
results-songs)))
|
||||||
(cdr
|
(cdr
|
||||||
(assoc
|
(assoc
|
||||||
(completing-read
|
(completing-read
|
||||||
"Pick a result: "
|
"Pick a result: "
|
||||||
results-songs-for-select
|
results-songs-for-select
|
||||||
nil t)
|
nil t)
|
||||||
results-songs-for-select)))
|
results-songs-for-select)))
|
||||||
(assoc key (assoc 'result (car results-songs)))))))))
|
(assoc key (assoc 'result (car results-songs)))))))
|
||||||
|
|
||||||
(defun lyrics-fetcher--genius-fetch-lyrics (url callback &optional sync)
|
(defun lyrics-fetcher--genius-fetch-lyrics (url callback &optional sync)
|
||||||
"Fetch lyrics from genius.com page at URL and call CALLBACK with result.
|
"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.<extension>\".
|
to FOLDER and will be name \"cover_full.<extension>\".
|
||||||
|
|
||||||
CALLBACK will be called with the path to the resulting file."
|
CALLBACK will be called with the path to the resulting file."
|
||||||
(if (not (= (cdr (assoc 'status (assoc 'meta data))) 200))
|
(when (not (= (cdr (assoc 'status (assoc 'meta data))) 200))
|
||||||
(message "Error: %" (cdr (assoc 'message (assoc 'meta data))))
|
(error "Error: %" (cdr (assoc 'message (assoc 'meta data)))))
|
||||||
(let ((url (cdr
|
(let ((url (cdr
|
||||||
(assoc 'cover_art_url
|
(assoc 'cover_art_url
|
||||||
(assoc 'album
|
(assoc 'album
|
||||||
(assoc 'song
|
(assoc 'song
|
||||||
(assoc 'response data)))))))
|
(assoc 'response data)))))))
|
||||||
(if (not url)
|
(if (not url)
|
||||||
(message "Album cover not found")
|
(message "Album cover not found")
|
||||||
(message "Downloading the cover image...")
|
(message "Downloading the cover image...")
|
||||||
(request url
|
(request url
|
||||||
:encoding 'binary
|
:encoding 'binary
|
||||||
:complete
|
:complete
|
||||||
(cl-function
|
(cl-function
|
||||||
(lambda (&key data &allow-other-keys)
|
(lambda (&key data &allow-other-keys)
|
||||||
(let ((filename
|
(let ((filename
|
||||||
(concat folder "cover_large" (url-file-extension url))))
|
(concat folder "cover_large" (url-file-extension url))))
|
||||||
(with-temp-file filename
|
(with-temp-file filename
|
||||||
(toggle-enable-multibyte-characters)
|
(toggle-enable-multibyte-characters)
|
||||||
(set-buffer-file-coding-system 'raw-text)
|
(set-buffer-file-coding-system 'raw-text)
|
||||||
(seq-doseq (char data)
|
(seq-doseq (char data)
|
||||||
(insert char)))
|
(insert char)))
|
||||||
(funcall callback filename))))
|
(funcall callback filename))))
|
||||||
:error
|
:error
|
||||||
(cl-function
|
(cl-function
|
||||||
(lambda (&key error-thrown &allow-other-keys)
|
(lambda (&key error-thrown &allow-other-keys)
|
||||||
(message "Error!: %S" error-thrown))))))))
|
(message "Error!: %S" error-thrown)))))))
|
||||||
|
|
||||||
(provide 'lyrics-fetcher-genius)
|
(provide 'lyrics-fetcher-genius)
|
||||||
;;; lyrics-fetcher-genius.el ends here
|
;;; lyrics-fetcher-genius.el ends here
|
||||||
|
|
|
||||||
|
|
@ -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
|
useful if there are multiple tracks with similar names, and the top
|
||||||
one isn’t the one required."
|
one isn’t the one required."
|
||||||
(interactive)
|
(interactive)
|
||||||
(when (not track)
|
(unless track
|
||||||
(setq track (funcall lyrics-fetcher-current-track-method)))
|
(setq track (funcall lyrics-fetcher-current-track-method)))
|
||||||
(if (not track)
|
(unless track
|
||||||
(message "Error: no track found!")
|
(error "Error: no track found!"))
|
||||||
(let ((song-name (funcall lyrics-fetcher-format-song-name-method track))
|
(let ((song-name (funcall lyrics-fetcher-format-song-name-method track))
|
||||||
(file-name (funcall lyrics-fetcher-format-file-name-method track))
|
(file-name (funcall lyrics-fetcher-format-file-name-method track))
|
||||||
;; The function is indented to be called both interactively
|
;; The function is indented to be called both interactively
|
||||||
;; and via recursion in asyncronous callbacks, during with
|
;; and via recursion in asyncronous callbacks, during with
|
||||||
;; `current-prefix-arg' will be unset. So this is necessary
|
;; `current-prefix-arg' will be unset. So this is necessary
|
||||||
;; to pass the behavior down the recursive calls.
|
;; to pass the behavior down the recursive calls.
|
||||||
(force-fetch (or force-fetch (member (prefix-numeric-value current-prefix-arg) '(4 16))))
|
(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)))))
|
(sync (or sync (member (prefix-numeric-value current-prefix-arg) '(16)))))
|
||||||
(if (and (not force-fetch) (lyrics-fetcher--lyrics-saved-p file-name))
|
(if (and (not force-fetch) (lyrics-fetcher--lyrics-saved-p file-name))
|
||||||
(progn
|
(progn
|
||||||
(message "Found fetched lyrics for: %s" song-name)
|
(message "Found fetched lyrics for: %s" song-name)
|
||||||
(when callback
|
(when callback
|
||||||
(funcall callback file-name))
|
(funcall callback file-name))
|
||||||
(unless suppress-open
|
(unless suppress-open
|
||||||
(lyrics-fetcher--open-lyrics file-name track)))
|
(lyrics-fetcher--open-lyrics file-name track)))
|
||||||
(funcall
|
(funcall
|
||||||
lyrics-fetcher-fetch-method track
|
lyrics-fetcher-fetch-method track
|
||||||
(lambda (result)
|
(lambda (result)
|
||||||
(lyrics-fetcher--save-lyrics result file-name)
|
(lyrics-fetcher--save-lyrics result file-name)
|
||||||
(unless suppress-open
|
(unless suppress-open
|
||||||
(lyrics-fetcher--open-lyrics file-name track))
|
(lyrics-fetcher--open-lyrics file-name track))
|
||||||
(when callback
|
(when callback
|
||||||
(funcall callback file-name)))
|
(funcall callback file-name)))
|
||||||
sync)))))
|
sync))))
|
||||||
|
|
||||||
(defun lyrics-fetcher-show-lyrics-query (query)
|
(defun lyrics-fetcher-show-lyrics-query (query)
|
||||||
"Fetch lyrics from a text QUERY.
|
"Fetch lyrics from a text QUERY.
|
||||||
|
|
@ -253,7 +253,7 @@ the same way as `lyrics-fetcher-show-lyrics'."
|
||||||
(interactive)
|
(interactive)
|
||||||
(let ((data (emms-browser-bdata-at-point)))
|
(let ((data (emms-browser-bdata-at-point)))
|
||||||
(if (not data)
|
(if (not data)
|
||||||
(message "Nothing is found at point!")
|
(error "Nothing is found at point!")
|
||||||
(if (eq (cdr (assoc 'type data)) 'info-title)
|
(if (eq (cdr (assoc 'type data)) 'info-title)
|
||||||
(lyrics-fetcher-show-lyrics (cdadr (assoc 'data data)))
|
(lyrics-fetcher-show-lyrics (cdadr (assoc 'data data)))
|
||||||
(lyrics-fetcher--fetch-many
|
(lyrics-fetcher--fetch-many
|
||||||
|
|
@ -280,10 +280,23 @@ the same way as `lyrics-fetcher-show-lyrics'."
|
||||||
(interactive)
|
(interactive)
|
||||||
(let ((data (emms-browser-bdata-at-point)))
|
(let ((data (emms-browser-bdata-at-point)))
|
||||||
(if (not data)
|
(if (not data)
|
||||||
(message "Nothing is found at point!")
|
(error "Nothing is found at point!")
|
||||||
(lyrics-fetcher--fetch-cover-many
|
(lyrics-fetcher--fetch-cover-many
|
||||||
(lyrics-fetcher--emms-extract-albums data)))))
|
(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)
|
(defun lyrics-fetcher--emms-extract-albums (bdata)
|
||||||
"Extract a list of sample song alists from each album in 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
|
If FORCE-FETCH is non-nil, always fetch regardless of whether the
|
||||||
file exists."
|
file exists."
|
||||||
(let ((covers-found (f-entries
|
(let ((cover-found (lyrics-fetcher--get-cover-in-directory
|
||||||
(f-dirname (cdr (assoc 'name track)))
|
(f-dirname (cdr (assoc 'name track))))))
|
||||||
(lambda (f)
|
(if (and (not force-fetch) cover-found)
|
||||||
(string-match-p
|
|
||||||
(rx (* nonl) "cover_large" (* nonl)) f)))))
|
|
||||||
(if (and (not force-fetch)
|
|
||||||
(not (seq-empty-p covers-found)))
|
|
||||||
(progn
|
(progn
|
||||||
(message "Cover already downloaded")
|
(message "Cover already downloaded")
|
||||||
(when callback
|
(when callback
|
||||||
(funcall callback (car covers-found))))
|
(funcall callback cover-found)))
|
||||||
(funcall lyrics-fetcher-download-cover-method
|
(funcall lyrics-fetcher-download-cover-method
|
||||||
track
|
track
|
||||||
(lambda (filename)
|
(lambda (filename)
|
||||||
|
|
@ -409,6 +418,14 @@ file exists."
|
||||||
(concat (f-dirname (cdr (assoc 'name track))) "/")
|
(concat (f-dirname (cdr (assoc 'name track))) "/")
|
||||||
sync))))
|
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)
|
(defun lyrics-fetcher--generate-cover-sizes (filename)
|
||||||
"Create small and medium versions of FILENAME.
|
"Create small and medium versions of FILENAME.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue