blob: 531c825e899b5ba6d7a37e08b62e565a0e48e4f3 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
(ns dionysus.spotify
(:require [clj-spotify.core :as spotify-api]
[hato.client :as hc]
[dotenv :as env]
[overtone.at-at :as at])
(:import (java.util Date Calendar)))
(def token (atom nil))
(defn search! [query] (spotify-api/search {:q query :type "track"} (:token @token)))
(defn add-item-to-queue! [uri] ((spotify-api/api-post "me/player/queue" {:query-params [:uri]})
{:uri uri} (:token @token)))
(defn get-current-track! [] (spotify-api/get-users-currently-playing-track {} (:token @token)))
#_(:item (get-current-track!))
(defn get-track! [id] (spotify-api/get-a-track {:id id} (:token @token)))
(defn get-artist! [id] (spotify-api/get-an-artist {:id id} (:token @token)))
(defn parse-share-url [url]
(when-let [parsed (->> url
(re-seq #"https:\/\/open\.spotify\.com\/intl-de\/(track|artist)\/([0-9A-z]*)")
first)]
{:url (first parsed)
:type (second parsed)
:id (last parsed)}))
(defn time-to-refresh-token? []
(when-let [t @token]
(-> t
:expires
.getTime
(- (.getTime (Date.)))
(< 120000) ; Is token valid for under two minutes?
)))
(def ^:private http-client (delay (hc/build-http-client {})))
(defn- update-token! [refresh-resp-body]
(swap! token assoc :token (get refresh-resp-body "access_token"))
(swap! token assoc :expires (let [calendar-instance (Calendar/getInstance)]
(.setTime calendar-instance (Date.))
(.add calendar-instance Calendar/SECOND (get refresh-resp-body "expires_in"))
(.getTime calendar-instance))))
(defn- request-new-token! []
(hc/post "https://accounts.spotify.com/api/token"
{:http-client @http-client
:throw-exceptions? false
:content-type "application/x-www-form-urlencoded"
:form-params {"grant_type" "refresh_token"
"refresh_token" (:refresh-token @token)}
:basic-auth {:user (env/env "SPOTIFY_CLIENT_ID")
:pass (env/env "SPOTIFY_CLIENT_SECRET")}
:as :json-string-keys}))
(defn- refresh-token! []
(when (time-to-refresh-token?)
(let [resp (request-new-token!)]
(if (= (:status resp) 200)
(do (update-token! (:body resp))
(println "refreshed token"))
(println "refreshing token failed")))))
(def ^:private at-pool (at/mk-pool))
(defn start-token-watcher! []
(at/every 60000 refresh-token! at-pool))
|