aboutsummaryrefslogtreecommitdiff
path: root/src/dionysus/spotify.clj
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))