2010-07-24 02:54:13 +05:30
|
|
|
(ns clj-lastfm.core
|
|
|
|
(:import (java.net URI)
|
|
|
|
(java.text SimpleDateFormat)
|
|
|
|
(java.util TimeZone))
|
|
|
|
(:use [clj-lastfm.filecache]
|
|
|
|
[clojure.contrib.json.read :only (read-json)]
|
|
|
|
[clojure.walk :only (keywordize-keys)]
|
|
|
|
[clojure.contrib.import-static]
|
|
|
|
[clojure.contrib.logging]))
|
|
|
|
|
|
|
|
;;;;;;;;;; Basic ;;;;;;;;;;
|
|
|
|
|
|
|
|
(def #^{:private true}
|
|
|
|
api-root-url ["http" "ws.audioscrobbler.com" "/2.0/"])
|
|
|
|
|
|
|
|
(defn- api-key []
|
|
|
|
(let [lastfm-api-key (resolve '*lastfm-api-key*)]
|
|
|
|
(if (nil? lastfm-api-key)
|
|
|
|
(throw (IllegalStateException. "lastfm API key is not set"))
|
|
|
|
lastfm-api-key)))
|
|
|
|
|
2010-07-24 11:52:23 +05:30
|
|
|
(def #^{:private true} guid-pattern
|
2010-07-24 02:54:13 +05:30
|
|
|
#"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$")
|
|
|
|
|
2010-07-24 21:37:24 +05:30
|
|
|
(def #^{:private true} attr-kw (keyword "@attr"))
|
|
|
|
|
2010-07-24 16:27:03 +05:30
|
|
|
(defn- safe-parse-int [n]
|
|
|
|
(if (nil? n)
|
|
|
|
nil
|
|
|
|
(try
|
|
|
|
(Integer/parseInt n)
|
|
|
|
(catch NumberFormatException nfe nil))))
|
|
|
|
|
|
|
|
(defn- safe-parse-double [n]
|
|
|
|
(if (nil? n)
|
|
|
|
nil
|
|
|
|
(try
|
|
|
|
(Double/parseDouble n)
|
|
|
|
(catch NumberFormatException nfe nil))))
|
|
|
|
|
|
|
|
(defn- struct? [obj] (instance? clojure.lang.PersistentStructMap obj))
|
|
|
|
|
2010-07-24 16:43:38 +05:30
|
|
|
(def #^{:private true :tag SimpleDateFormat} sdftz
|
2010-07-24 02:54:13 +05:30
|
|
|
(doto (SimpleDateFormat. "EEE, dd MMMM yyyy HH:mm:ss +0000")
|
|
|
|
(.setTimeZone (TimeZone/getTimeZone "GMT"))))
|
|
|
|
|
2010-07-24 16:43:38 +05:30
|
|
|
(def #^{:private true :tag SimpleDateFormat} sdf
|
2010-07-24 16:27:03 +05:30
|
|
|
(doto (SimpleDateFormat. "EEE, dd MMMM yyyy HH:mm:ss")
|
|
|
|
(.setTimeZone (TimeZone/getTimeZone "GMT"))))
|
|
|
|
|
2010-07-24 11:52:23 +05:30
|
|
|
(defn- parse-date [date-str]
|
2010-07-24 16:27:03 +05:30
|
|
|
(try
|
|
|
|
(.parse sdftz date-str)
|
|
|
|
(catch java.text.ParseException e
|
|
|
|
(.parse sdf date-str))))
|
2010-07-24 02:54:13 +05:30
|
|
|
|
|
|
|
(defn- remove-nil-values [m]
|
|
|
|
(apply hash-map (apply concat (filter #(not (nil? (fnext %))) m))))
|
|
|
|
|
2010-07-24 21:37:24 +05:30
|
|
|
(defn- lastfm-url [path]
|
|
|
|
(.toString (URI. "http" "www.last.fm" path nil nil)))
|
|
|
|
|
2010-07-24 02:54:13 +05:30
|
|
|
(defn- create-url-query [query-params]
|
|
|
|
(apply str
|
|
|
|
(interpose
|
|
|
|
"&"
|
|
|
|
(map
|
|
|
|
#(str (name (first %)) "=" (second %))
|
|
|
|
(remove-nil-values query-params)))))
|
|
|
|
|
|
|
|
(defn- create-url [query-params]
|
|
|
|
(.toURL
|
2010-07-24 16:43:38 +05:30
|
|
|
(#^URI apply
|
2010-07-24 02:54:13 +05:30
|
|
|
#(URI. %1 %2 %3 %4 %5)
|
|
|
|
(conj
|
|
|
|
api-root-url
|
|
|
|
(create-url-query
|
|
|
|
(merge query-params {:api_key @(api-key) :format "json"}))
|
|
|
|
nil))))
|
|
|
|
|
|
|
|
(def #^{:private true} default-cache (create-file-cache))
|
|
|
|
|
|
|
|
(defn- get-url
|
|
|
|
([url] (get-url url default-cache))
|
|
|
|
([url cache]
|
|
|
|
(do
|
2010-07-24 12:41:48 +05:30
|
|
|
(info (str "URL: " url))
|
2010-07-24 02:54:13 +05:30
|
|
|
(get-file-content cache url))))
|
|
|
|
|
|
|
|
(defn- get-data [params]
|
2010-07-24 16:27:03 +05:30
|
|
|
(let [url (create-url params)
|
|
|
|
data (-> url get-url read-json keywordize-keys)]
|
2010-07-25 00:12:39 +05:30
|
|
|
(if (-> data :error nil?)
|
|
|
|
data
|
|
|
|
(throw (IllegalArgumentException. (-> data :message str))))))
|
2010-07-24 02:54:13 +05:30
|
|
|
|
2010-07-24 11:52:23 +05:30
|
|
|
(defn- create-get-obj-fn [fixed-params parse-fn]
|
2010-07-24 02:54:13 +05:30
|
|
|
(fn [more-params]
|
2010-07-25 00:12:39 +05:30
|
|
|
(parse-fn #(get-data (merge fixed-params more-params)))))
|
2010-07-24 02:54:13 +05:30
|
|
|
|
2010-07-24 11:52:23 +05:30
|
|
|
(defn- create-get-obj-field-fn [create-obj-fn extract-obj-id-fields-fn]
|
2010-07-24 02:54:13 +05:30
|
|
|
(fn [obj field-kw]
|
|
|
|
(let [field-val (obj field-kw)]
|
|
|
|
(if (nil? field-val)
|
|
|
|
((apply create-obj-fn (extract-obj-id-fields-fn obj)) field-kw)
|
|
|
|
field-val))))
|
|
|
|
|
2010-07-24 16:27:03 +05:30
|
|
|
(defn- create-parse-one-or-more-fn [parse-one-fn extractor-fn]
|
2010-07-25 00:12:39 +05:30
|
|
|
(fn [data-fn]
|
|
|
|
(lazy-seq
|
|
|
|
(let [data (data-fn) one-or-more (extractor-fn data)]
|
|
|
|
(do
|
|
|
|
(debug (str "parsing: " data))
|
|
|
|
(if (map? one-or-more)
|
|
|
|
(vector (parse-one-fn one-or-more))
|
|
|
|
(vec (map parse-one-fn one-or-more))))))))
|
2010-07-24 16:27:03 +05:30
|
|
|
|
|
|
|
(defn- create-parse-string-or-list-fn [obj-from-name-fn extractor-fn]
|
|
|
|
(fn [data]
|
|
|
|
(let [string-or-list (extractor-fn data)]
|
|
|
|
(if (string? string-or-list)
|
|
|
|
(vector (obj-from-name-fn string-or-list))
|
|
|
|
(vec (map obj-from-name-fn string-or-list))))))
|
|
|
|
|
2010-07-24 11:52:23 +05:30
|
|
|
;;;;;;;;;; forward declaration ;;;;;;;;;;
|
|
|
|
|
2010-07-24 13:07:21 +05:30
|
|
|
(declare bio-struct artist-struct tag-struct album-struct user-struct
|
2010-07-24 16:27:03 +05:30
|
|
|
track-struct event-struct venue-struct location-struct)
|
|
|
|
|
|
|
|
(declare artist-from-name tag-from-name)
|
2010-07-24 11:52:23 +05:30
|
|
|
|
2010-07-24 02:54:13 +05:30
|
|
|
;;;;;;;;;; Bio/Wiki ;;;;;;;;;;
|
|
|
|
|
|
|
|
(defstruct bio-struct :published :summary :content)
|
|
|
|
|
2010-07-24 11:52:23 +05:30
|
|
|
(defn- parse-bio [data]
|
2010-07-24 12:41:48 +05:30
|
|
|
(do
|
|
|
|
(debug (str "parse-bio: " data))
|
|
|
|
(struct
|
|
|
|
bio-struct
|
|
|
|
(-> data :published parse-date)
|
2010-07-24 16:27:03 +05:30
|
|
|
(data :summary)
|
|
|
|
(data :content))))
|
|
|
|
|
|
|
|
;;;;;;;;;; Location ;;;;;;;;;;
|
|
|
|
|
|
|
|
(defstruct location-struct
|
|
|
|
:latitude :longitude :street :postalcode :city :country)
|
|
|
|
|
|
|
|
(defn- parse-location [data]
|
|
|
|
(do
|
|
|
|
(debug (str "parse-location: " data))
|
|
|
|
(struct location-struct
|
|
|
|
(-> data :geo:point :geo:lat safe-parse-double)
|
|
|
|
(-> data :geo:point :geo:long safe-parse-double)
|
|
|
|
(data :street)
|
|
|
|
(data :postalcode)
|
|
|
|
(data :city)
|
|
|
|
(data :country))))
|
|
|
|
|
|
|
|
;;;;;;;;;; Venue ;;;;;;;;;;
|
|
|
|
|
|
|
|
(defstruct venue-struct
|
|
|
|
:id :name :location :url :website :phonenumber)
|
|
|
|
|
|
|
|
(defn- parse-venue [data]
|
|
|
|
(do
|
|
|
|
(debug (str "parse-venue: " data))
|
|
|
|
(struct venue-struct
|
|
|
|
(data :id)
|
|
|
|
(data :name)
|
|
|
|
(-> data :location parse-location)
|
|
|
|
(data :url)
|
|
|
|
(data :website)
|
|
|
|
(data :phonenumber))))
|
|
|
|
|
|
|
|
;;;;;;;;;; Event ;;;;;;;;;;
|
|
|
|
|
|
|
|
(defstruct event-struct
|
|
|
|
:id :title :artists :headliner :venue :start :description
|
|
|
|
:attendence :reviews :tag :url :website :cancelled :tags)
|
|
|
|
|
|
|
|
(def #^{:private true} parse-event-artists
|
|
|
|
(create-parse-string-or-list-fn
|
|
|
|
#(artist-from-name %) #(-> % :artists :artist)))
|
|
|
|
|
|
|
|
(def #^{:private true} parse-event-tags
|
|
|
|
(create-parse-string-or-list-fn
|
|
|
|
#(tag-from-name %) #(-> % :tags :tag)))
|
|
|
|
|
|
|
|
(defn- parse-event [data]
|
|
|
|
(do
|
|
|
|
(debug (str "parse-event: " data))
|
|
|
|
(struct event-struct
|
|
|
|
(data :id)
|
|
|
|
(data :title)
|
|
|
|
(parse-event-artists data)
|
|
|
|
(artist-from-name (-> data :artists :headliner))
|
|
|
|
(-> data :venue parse-venue)
|
|
|
|
(-> data :startDate parse-date)
|
|
|
|
(data :description)
|
|
|
|
(-> data :attendence safe-parse-int)
|
|
|
|
(-> data :reviews safe-parse-int)
|
|
|
|
(data :tag)
|
|
|
|
(data :url)
|
|
|
|
(data :website)
|
|
|
|
(= 1 (-> data :cancelled safe-parse-int))
|
|
|
|
(parse-event-tags data))))
|
2010-07-24 02:54:13 +05:30
|
|
|
|
2010-07-24 12:41:48 +05:30
|
|
|
;;;;;;;;;; Artist ;;;;;;;;;;
|
2010-07-24 02:54:13 +05:30
|
|
|
|
|
|
|
(defstruct artist-struct
|
|
|
|
:name :url :mbid :streamable :listeners :playcount :bio)
|
|
|
|
|
2010-07-24 11:52:23 +05:30
|
|
|
(defn- parse-artist [data]
|
2010-07-24 12:41:48 +05:30
|
|
|
(do
|
|
|
|
(debug (str "parse-artist: " data))
|
|
|
|
(struct
|
|
|
|
artist-struct
|
2010-07-24 16:27:03 +05:30
|
|
|
(data :name)
|
|
|
|
(data :artist :url)
|
|
|
|
(data :mbid)
|
|
|
|
(= 1 (-> data :streamable safe-parse-int))
|
|
|
|
(-> data :stats :listeners safe-parse-int)
|
|
|
|
(-> data :stats :playcount safe-parse-int)
|
|
|
|
(-> data :bio parse-bio))))
|
|
|
|
|
|
|
|
(defn- artist-from-name [artst-name]
|
|
|
|
(struct-map artist-struct :name artst-name))
|
2010-07-24 12:41:48 +05:30
|
|
|
|
|
|
|
;;;;;;;;;; artist.getinfo ;;;;;;;;;;
|
2010-07-24 02:54:13 +05:30
|
|
|
|
2010-07-25 00:12:39 +05:30
|
|
|
(defn- parse-artist-getinfo [data-fn]
|
|
|
|
(let [data (data-fn)]
|
|
|
|
(do
|
|
|
|
(debug (str "parse-artist-getinfo: " data))
|
|
|
|
(-> data :artist parse-artist))))
|
2010-07-24 16:27:03 +05:30
|
|
|
|
2010-07-25 00:12:39 +05:30
|
|
|
(def #^{:private true} get-artist
|
|
|
|
(create-get-obj-fn {:method "artist.getinfo"} parse-artist-getinfo))
|
2010-07-24 02:54:13 +05:30
|
|
|
|
|
|
|
(defmulti artist
|
|
|
|
(fn [artist-or-mbid & _]
|
|
|
|
(if (re-matches guid-pattern artist-or-mbid) :mbid :artist)))
|
|
|
|
|
|
|
|
(defmethod artist :artist
|
|
|
|
([artist-name] (artist artist-name nil nil))
|
|
|
|
([artist-name username] (artist artist-name username nil))
|
|
|
|
([artist-name username lang]
|
|
|
|
(get-artist {:artist artist-name :username username :lang lang})))
|
|
|
|
|
|
|
|
(defmethod artist :mbid
|
|
|
|
([mbid] (artist mbid nil nil))
|
|
|
|
([mbid username] (artist mbid username nil))
|
|
|
|
([mbid username lang]
|
|
|
|
(get-artist {:mbid mbid :username username :lang lang})))
|
|
|
|
|
|
|
|
(def artist-info
|
|
|
|
(create-get-obj-field-fn artist #(vector (% :name))))
|
|
|
|
|
2010-07-24 11:52:23 +05:30
|
|
|
;;;;;;;;;; artist.getsimilar ;;;;;;;;;;
|
|
|
|
|
2010-07-24 16:27:03 +05:30
|
|
|
(defn- parse-artist-similar-1 [data]
|
|
|
|
(struct-map artist-struct
|
|
|
|
:name (data :name)
|
|
|
|
:url (data :url)
|
|
|
|
:mbid (data :mbid)
|
|
|
|
:streamable (= 1 (-> data :streamable safe-parse-int))
|
|
|
|
:match (-> data :match safe-parse-double)))
|
|
|
|
|
|
|
|
(def #^{:private true} parse-artist-similar
|
|
|
|
(create-parse-one-or-more-fn
|
|
|
|
parse-artist-similar-1
|
|
|
|
#(-> % :similarartists :artist)))
|
2010-07-24 02:54:13 +05:30
|
|
|
|
|
|
|
(def #^{:private true} get-artist-similar
|
|
|
|
(create-get-obj-fn {:method "artist.getsimilar"} parse-artist-similar))
|
|
|
|
|
2010-07-24 11:52:23 +05:30
|
|
|
(defn- artist-or-name [artst-or-name & _]
|
2010-07-24 16:27:03 +05:30
|
|
|
(if (struct? artst-or-name) :artist :name))
|
2010-07-24 02:54:13 +05:30
|
|
|
|
2010-07-24 11:52:23 +05:30
|
|
|
(defmulti artist-similar artist-or-name)
|
|
|
|
|
|
|
|
(defmethod artist-similar :artist
|
2010-07-24 02:54:13 +05:30
|
|
|
([artst] (-> artst :name artist-similar))
|
|
|
|
([artst limit] (artist-similar (artst :name) limit)))
|
|
|
|
|
2010-07-24 11:52:23 +05:30
|
|
|
(defmethod artist-similar :name
|
|
|
|
([artist-name]
|
|
|
|
(get-artist-similar {:artist artist-name}))
|
|
|
|
([artist-name limit]
|
|
|
|
(get-artist-similar {:artist artist-name :limit limit})))
|
|
|
|
|
|
|
|
;;;;;;;;;; artist.gettoptags ;;;;;;;;;;
|
|
|
|
|
2010-07-24 16:27:03 +05:30
|
|
|
|
|
|
|
(def #^{:private true} parse-artist-toptags
|
|
|
|
(create-parse-one-or-more-fn
|
|
|
|
#(struct tag-struct (% :name) (% :url))
|
|
|
|
#(-> % :toptags :tag)))
|
2010-07-24 11:52:23 +05:30
|
|
|
|
|
|
|
(def #^{:private true} get-artist-toptags
|
|
|
|
(create-get-obj-fn {:method "artist.gettoptags"} parse-artist-toptags))
|
|
|
|
|
|
|
|
(defmulti artist-toptags artist-or-name)
|
|
|
|
|
|
|
|
(defmethod artist-toptags :artist [artst]
|
|
|
|
(-> artst :name artist-toptags))
|
|
|
|
|
|
|
|
(defmethod artist-toptags :name [artist-name]
|
|
|
|
(get-artist-toptags {:artist artist-name}))
|
|
|
|
|
2010-07-24 12:41:48 +05:30
|
|
|
;;;;;;;;;; artist.gettopalbums ;;;;;;;;;;
|
|
|
|
|
2010-07-24 16:27:03 +05:30
|
|
|
(defn- parse-artist-topalbums-1 [data]
|
|
|
|
(struct-map album-struct
|
|
|
|
:name (data :name)
|
|
|
|
:url (data :url)
|
|
|
|
:mbid (data :mbid)
|
|
|
|
:artist (struct-map artist-struct
|
|
|
|
:name (-> data :artist :name)
|
|
|
|
:url (-> data :artist :url)
|
|
|
|
:mbid (-> data :artist :mbid))
|
|
|
|
:playcount (-> data :playcount safe-parse-int)
|
2010-07-24 21:37:24 +05:30
|
|
|
:rank (-> data attr-kw :rank safe-parse-int)))
|
2010-07-24 16:27:03 +05:30
|
|
|
|
|
|
|
(def #^{:private true} parse-artist-topalbums
|
|
|
|
(create-parse-one-or-more-fn
|
|
|
|
parse-artist-topalbums-1
|
|
|
|
#(-> % :topalbums :album)))
|
2010-07-24 12:41:48 +05:30
|
|
|
|
|
|
|
(def #^{:private true} get-artist-topalbums
|
|
|
|
(create-get-obj-fn {:method "artist.gettopalbums"} parse-artist-topalbums))
|
|
|
|
|
|
|
|
(defmulti artist-topalbums artist-or-name)
|
|
|
|
|
|
|
|
(defmethod artist-topalbums :artist [artst]
|
|
|
|
(-> artst :name artist-topalbums))
|
|
|
|
|
|
|
|
(defmethod artist-topalbums :name [artist-name]
|
|
|
|
(get-artist-topalbums {:artist artist-name}))
|
|
|
|
|
2010-07-24 12:50:44 +05:30
|
|
|
;;;;;;;;;; artist.gettopfans ;;;;;;;;;;
|
|
|
|
|
2010-07-24 16:27:03 +05:30
|
|
|
(defn- parse-artist-topfans-1 [data]
|
|
|
|
(struct-map user-struct
|
|
|
|
:name (data :name)
|
|
|
|
:url (data :url)
|
|
|
|
:realname (data :realname)
|
|
|
|
:weight (-> data :weight safe-parse-int)))
|
|
|
|
|
|
|
|
(def #^{:private true} parse-artist-topfans
|
|
|
|
(create-parse-one-or-more-fn
|
|
|
|
parse-artist-topfans-1
|
|
|
|
#(-> % :topfans :user)))
|
2010-07-24 12:50:44 +05:30
|
|
|
|
|
|
|
(def #^{:private true} get-artist-topfans
|
|
|
|
(create-get-obj-fn {:method "artist.gettopfans"} parse-artist-topfans))
|
|
|
|
|
|
|
|
(defmulti artist-topfans artist-or-name)
|
|
|
|
|
|
|
|
(defmethod artist-topfans :artist [artst]
|
|
|
|
(-> artst :name artist-topfans))
|
|
|
|
|
|
|
|
(defmethod artist-topfans :name [artist-name]
|
|
|
|
(get-artist-topfans {:artist artist-name}))
|
2010-07-24 12:41:48 +05:30
|
|
|
|
2010-07-24 13:07:21 +05:30
|
|
|
;;;;;;;;;; artist.gettoptracks ;;;;;;;;;;
|
|
|
|
|
2010-07-24 16:27:03 +05:30
|
|
|
(defn- parse-artist-toptracks-1 [data]
|
|
|
|
(struct-map track-struct
|
|
|
|
:name (data :name)
|
|
|
|
:url (data :url)
|
|
|
|
:mbid (data :mbid)
|
|
|
|
:artist (struct-map artist-struct
|
|
|
|
:name (-> data :artist :name)
|
|
|
|
:url (-> data :artist :url)
|
|
|
|
:mbid (-> data :artist :mbid))
|
|
|
|
:playcount (-> data :playcount safe-parse-int)
|
|
|
|
:listeners (-> data :listeners safe-parse-int)
|
|
|
|
:streamable (= 1 (-> data :streamable :#text safe-parse-int))
|
|
|
|
:streamable-full (= 1 (-> data :streamable :fulltrack safe-parse-int))))
|
|
|
|
|
|
|
|
(def #^{:private true} parse-artist-toptracks
|
|
|
|
(create-parse-one-or-more-fn
|
|
|
|
parse-artist-toptracks-1
|
|
|
|
#(-> % :toptracks :track)))
|
2010-07-24 13:07:21 +05:30
|
|
|
|
|
|
|
(def #^{:private true} get-artist-toptracks
|
|
|
|
(create-get-obj-fn {:method "artist.gettoptracks"} parse-artist-toptracks))
|
|
|
|
|
|
|
|
(defmulti artist-toptracks artist-or-name)
|
|
|
|
|
|
|
|
(defmethod artist-toptracks :artist [artst]
|
|
|
|
(-> artst :name artist-toptracks))
|
|
|
|
|
|
|
|
(defmethod artist-toptracks :name [artist-name]
|
|
|
|
(get-artist-toptracks {:artist artist-name}))
|
|
|
|
|
2010-07-24 16:27:03 +05:30
|
|
|
;;;;;;;;;; artist.getevents ;;;;;;;;;;
|
|
|
|
|
|
|
|
(def #^{:private true} parse-artist-events
|
|
|
|
(create-parse-one-or-more-fn
|
|
|
|
parse-event
|
|
|
|
#(-> % :events :event)))
|
|
|
|
|
|
|
|
(def #^{:private true} get-artist-events
|
|
|
|
(create-get-obj-fn {:method "artist.getevents"} parse-artist-events))
|
|
|
|
|
|
|
|
(defmulti artist-events artist-or-name)
|
|
|
|
|
|
|
|
(defmethod artist-events :artist [artst]
|
|
|
|
(-> artst :name artist-events))
|
|
|
|
|
|
|
|
(defmethod artist-events :name [artist-name]
|
|
|
|
(get-artist-events {:artist artist-name}))
|
|
|
|
|
2010-07-24 21:37:24 +05:30
|
|
|
;;;;;;;;;; artist.getpastevents ;;;;;;;;;;
|
|
|
|
|
|
|
|
(declare get-artist-pastevents)
|
|
|
|
|
2010-07-25 00:12:39 +05:30
|
|
|
(defn- parse-artist-pastevents [data-fn]
|
|
|
|
(lazy-seq
|
|
|
|
(let [data (data-fn)
|
|
|
|
pages (-> data :events attr-kw :totalPages safe-parse-int)
|
|
|
|
page (-> data :events attr-kw :page safe-parse-int)
|
|
|
|
artist-name (-> data :events attr-kw :artist)]
|
|
|
|
(if (= page pages)
|
|
|
|
(parse-artist-events data-fn)
|
|
|
|
(lazy-cat
|
|
|
|
(parse-artist-events data-fn)
|
|
|
|
(get-artist-pastevents {:artist artist-name :page (inc page)}))))))
|
2010-07-24 21:37:24 +05:30
|
|
|
|
|
|
|
(defn- get-artist-pastevents
|
|
|
|
([params]
|
|
|
|
((create-get-obj-fn
|
|
|
|
{:method "artist.getpastevents"}
|
|
|
|
parse-artist-pastevents)
|
|
|
|
params))
|
|
|
|
([params page]
|
|
|
|
((create-get-obj-fn
|
|
|
|
{:method "artist.getpastevents" :page page}
|
|
|
|
parse-artist-pastevents)
|
|
|
|
params)))
|
|
|
|
|
|
|
|
(defmulti artist-pastevents artist-or-name)
|
|
|
|
|
|
|
|
(defmethod artist-pastevents :artist [artst]
|
|
|
|
(-> artst :name artist-pastevents))
|
|
|
|
|
|
|
|
(defmethod artist-pastevents :name [artist-name]
|
|
|
|
(get-artist-pastevents {:artist artist-name}))
|
|
|
|
|
2010-07-24 12:41:48 +05:30
|
|
|
;;;;;;;;;; Tag ;;;;;;;;;;
|
2010-07-24 11:52:23 +05:30
|
|
|
|
|
|
|
(defstruct tag-struct :name :url)
|
2010-07-24 02:54:13 +05:30
|
|
|
|
2010-07-24 16:27:03 +05:30
|
|
|
(defn- tag-from-name [tag-name]
|
2010-07-24 21:37:24 +05:30
|
|
|
(struct tag-struct tag-name (lastfm-url (str "/tag/" tag-name))))
|
2010-07-24 16:27:03 +05:30
|
|
|
|
2010-07-24 12:41:48 +05:30
|
|
|
;;;;;;;;;; Album ;;;;;;;;;;
|
|
|
|
|
|
|
|
(defstruct album-struct :name :url :mbid :artist :playcount)
|
|
|
|
|
2010-07-24 13:07:21 +05:30
|
|
|
;;;;;;;;;; Track ;;;;;;;;;;
|
|
|
|
|
|
|
|
(defstruct track-struct
|
|
|
|
:name :url :mbid :artist :playcount :listeners :streamable)
|
|
|
|
|
2010-07-24 12:50:44 +05:30
|
|
|
;;;;;;;;;; User ;;;;;;;;;;
|
|
|
|
|
|
|
|
(defstruct user-struct :name :url :realname)
|
|
|
|
|
2010-07-24 02:54:13 +05:30
|
|
|
(comment
|
|
|
|
|
|
|
|
(def *lastfm-api-key* "23caa86333d2cb2055fa82129802780a")
|
|
|
|
(def u2 (artist "u2"))
|
|
|
|
(println (artist-info u2 :url))
|
|
|
|
|
|
|
|
)
|