X-Git-Url: http://git.vanrenterghem.biz/musicbrainz.git/blobdiff_plain/d1ec6704c7f55517ef355273e4233093f2880450..006cf0949378dc3f0c3368f0e2e29093ec67e4da:/listenbrainz.el diff --git a/listenbrainz.el b/listenbrainz.el index 0229551..5ebf40a 100644 --- a/listenbrainz.el +++ b/listenbrainz.el @@ -2,9 +2,10 @@ ;; Copyright 2023 FoAM ;; -;; Author: nik gaffney +;; Author: nik gaffney , Frederik Vanrenterghem ;; Created: 2023-05-05 -;; Version: 0.1 +;; Updated: 2025-01-25 +;; Version: 0.2fv ;; Package-Requires: ((emacs "27.1") (request "0.3")) ;; Keywords: music, scrobbling, multimedia ;; URL: https://github.com/zzkt/listenbrainz @@ -27,10 +28,19 @@ ;;; Commentary: -;; - listen & submit metadata to ListenBrainz -;; - partial & incomplete -;; - no error checks -;; - sync -> async +;; An interface to ListenBrainz, a project to store a record of the music that +;; you listen to. The listening data, can be used to provide statistics, +;; recommendations and general exploration. +;; +;; The package can be used programmatically (e.g. from a music player) to auto +;; submit listening data `listenbrainz-submit-listen'. There are other entrypoints +;; for reading user stats such as `listenbrainz-stats-artists' or +;; `listenbrainz-listens'. +;; +;; Some API calls require a user token, which can be found in your ListenBrainz +;; profile. Configure, set or `customize' the `listenbrainz-api-token' as needed. +;; +;; https://listenbrainz.readthedocs.io/ ;;; Code: @@ -104,7 +114,6 @@ All timestamps used in ListenBrainz are UNIX epoch timestamps in UTC." ;; ;;;; ; ;; ; - (defmacro listenbrainz--deformatter (name format-string format-args alist) "Generate function with NAME to format data returned from an API call. The function has the name `listenbrainz--format-NAME`. @@ -216,7 +225,6 @@ macroexpands to something like -> ;; ;;; ; ;; ; ; ; -;;;###autoload (defun listenbrainz-validate-token (token) "Check if TOKEN is valid. Return a username or nil." (message "listenbrainz: checking token %s" token) @@ -255,7 +263,8 @@ macroexpands to something like -> :sync t :success (cl-function (lambda (&key data &allow-other-keys) - (message "Listens for user: %s" username))))))) + (message "Listens for user: %s\n%s" username + (if data data "")))))))) (princ (listenbrainz--format-listens response)))) @@ -272,7 +281,8 @@ macroexpands to something like -> :sync t :success (cl-function (lambda (&key data &allow-other-keys) - (message "User playing now: %s" username))))))) + (message "User playing now: %s\n%s" username + (if data data "")))))))) (princ (listenbrainz--format-playing response)))) @@ -280,12 +290,13 @@ macroexpands to something like -> ;; - https://listenbrainz.readthedocs.io/en/production/dev/api-usage/#submitting-listens ;; - https://listenbrainz.readthedocs.io/en/production/dev/json/#json-doc -(defun listenbrainz-submit-listen (type artist track &optional release) +(defun listenbrainz-submit-listen (type artist track &optional release timestamp) "Submit listening data to ListenBrainz. - listen TYPE (string) either \='single\=', \='import\=' or \='playing_now\=' - ARTIST name (string) - TRACK title (string) -- RELEASE title (string) also album title." +- RELEASE title (string) also album title. +- TIMESTAMP time (time) track was listened to" (message "listenbrainz: submitting %s - %s - %s" artist track release) (let* ((json-null "") (now (listenbrainz-timestamp)) @@ -297,6 +308,7 @@ macroexpands to something like -> (remove nil (list (when (string= type "single") (cons "listened_at" now)) + (when (string= type "import") (cons "listened_at" (listenbrainz-timestamp timestamp))) (list "track_metadata" (cons "artist_name" artist) (cons "track_name" track) @@ -323,6 +335,10 @@ macroexpands to something like -> "Submit data for track (ARTIST TRACK and optional RELEASE) playing now." (listenbrainz-submit-listen "playing_now" artist track (when release release))) +;;;###autoload +(defun listenbrainz-submit-historic-listen (artist track timestamp &optional release) + "Submit data for track (ARTIST TRACK and optional RELEASE) heard at TIMESTAMP." + (listenbrainz-submit-listen "import" artist track (if release release "") timestamp)) ;;; ;; ;; ; ; ; ; ; ; ;; @@ -351,7 +367,8 @@ possible values are week, month, year, all_time, defaults to all_time." :sync t :success (cl-function (lambda (&key data &allow-other-keys) - (message "Top recordings for user: %s" username))))))) + (message "Top recordings for user: %s\n%s" username + (if data data "")))))))) (princ (listenbrainz--format-stats-2 response)))) @@ -374,7 +391,8 @@ possible values are week, month, year, all_time, defaults to all_time." :sync t :success (cl-function (lambda (&key data &allow-other-keys) - (message "Top releases for user: %s" username))))))) + (message "Top releases for user: %s\n%s" username + (if data data "")))))))) (princ (listenbrainz--format-stats-0 response)))) @@ -397,7 +415,8 @@ possible values are week, month, year, all_time, defaults to all_time." :sync t :success (cl-function (lambda (&key data &allow-other-keys) - (message "Top artists for user: %s" username))))))) + (message "Top artists for user: %s\n%s" username + (if data data "")))))))) (princ (listenbrainz--format-stats-1 response)))) @@ -423,10 +442,11 @@ OUTPUT format can be either `list' (default) or `graph'." :sync t :success (cl-function (lambda (&key data &allow-other-keys) - (message "Followers for %s" username))))))) + (message "Followers for %s\n%s" username + (if data data "")))))))) (if (string= "graph" output) - (princ (listenbrainz--format-followers-graph response)) - (princ (listenbrainz--format-followers-list response))))) + (princ (listenbrainz--format-followers-graph response)) + (princ (listenbrainz--format-followers-list response))))) ;;;###autoload (defun listenbrainz-following (username) @@ -441,7 +461,8 @@ OUTPUT format can be either `list' (default) or `graph'." :sync t :success (cl-function (lambda (&key data &allow-other-keys) - (message "Users %s is following" username))))))) + (message "Users %s is following\n%s" username + (if data data "")))))))) (princ (listenbrainz--format-following response))))