Accept {"token":"foo"} for private instances
Needs `status:read` permission; see https://docs.joinmastodon.org/methods/timelines/#tag
This commit is contained in:
parent
bac6645c9f
commit
69d969ca5c
1 changed files with 20 additions and 16 deletions
|
|
@ -1,9 +1,9 @@
|
||||||
(ns looptober
|
(ns looptober
|
||||||
(:require [clojure.string :as str]
|
(:require [clojure.string :as str]
|
||||||
[org.httpkit.client :as http]
|
[clojure.data.xml :as xml]
|
||||||
[org.httpkit.server :refer [run-server ]]
|
|
||||||
[cheshire.core :as json]
|
[cheshire.core :as json]
|
||||||
[clojure.data.xml :as xml]))
|
[org.httpkit.client :as http]
|
||||||
|
[org.httpkit.server :refer [run-server]]))
|
||||||
|
|
||||||
(xml/alias-uri 'xspf "http://xspf.org/ns/0/")
|
(xml/alias-uri 'xspf "http://xspf.org/ns/0/")
|
||||||
|
|
||||||
|
|
@ -16,23 +16,25 @@
|
||||||
|
|
||||||
(def update-interval (* 1000 60 30)) ;; 30 min
|
(def update-interval (* 1000 60 30)) ;; 30 min
|
||||||
|
|
||||||
(defn paginate!
|
(defn paginate
|
||||||
"Fetch all mastodon statuses where `min-id` < status < `max-id`.
|
"Fetch all mastodon statuses where `min-id` < status < `max-id`.
|
||||||
Takes a `pred` to filter statuses, will stop if no status matches the pred."
|
Takes a `pred` to filter statuses, will stop if no status matches the pred."
|
||||||
([url pred min-id] (paginate! url pred min-id nil))
|
([url token pred min-id] (paginate url token pred min-id nil))
|
||||||
([url pred min-id max-id]
|
([url token pred min-id max-id]
|
||||||
(println "calling paginate! with" min-id max-id)
|
(println "calling paginate with" min-id max-id)
|
||||||
(let [req (http/get url {:query-params {:min_id min-id
|
(let [opts (cond-> {:query-params {:min_id min-id
|
||||||
:max_id max-id}})
|
:max_id max-id}}
|
||||||
|
token (assoc :headers {"Authorization" (format "Bearer %s" token)}))
|
||||||
|
req (http/get url opts)
|
||||||
result (filterv pred (json/parse-string (:body @req) true))]
|
result (filterv pred (json/parse-string (:body @req) true))]
|
||||||
(concat result (when (seq result)
|
(concat result (when (seq result)
|
||||||
(paginate! url pred min-id (:id (last result))))))))
|
(paginate url token pred min-id (:id (last result))))))))
|
||||||
|
|
||||||
(defn audio-attachment [status]
|
(defn audio-attachment [status]
|
||||||
(find-in #(= (:type %) "audio") (-> status :media_attachments)))
|
(find-in #(= (:type %) "audio") (-> status :media_attachments)))
|
||||||
|
|
||||||
(defn fetch-loops!
|
(defn fetch-loops
|
||||||
([instance-url]
|
([instance-url token]
|
||||||
;; cache update logic
|
;; cache update logic
|
||||||
(let [now (System/currentTimeMillis)
|
(let [now (System/currentTimeMillis)
|
||||||
[last-fetch statuses] (get @response-cache instance-url)
|
[last-fetch statuses] (get @response-cache instance-url)
|
||||||
|
|
@ -41,10 +43,11 @@
|
||||||
(> (- now last-fetch) update-interval))
|
(> (- now last-fetch) update-interval))
|
||||||
(let [updated (swap! response-cache assoc instance-url
|
(let [updated (swap! response-cache assoc instance-url
|
||||||
[now
|
[now
|
||||||
(let [new-statuses (paginate! (format "%s/api/v1/timelines/tag/looptober" instance-url)
|
(let [new-statuses (paginate (format "%s/api/v1/timelines/tag/looptober" instance-url)
|
||||||
|
token
|
||||||
(fn [status]
|
(fn [status]
|
||||||
(and (neg? (compare (:id max-status) (:id status)))
|
(and (neg? (compare (:id max-status) (:id status)))
|
||||||
(neg? (compare (or (:created_at max-status) "2023-10-01T00:00:00.000Z") (:created_at status)))))
|
(neg? (compare (:created_at max-status "2023-10-01T00:00:00.000Z") (:created_at status)))))
|
||||||
(:id max-status))]
|
(:id max-status))]
|
||||||
(concat (filterv audio-attachment new-statuses) statuses))])
|
(concat (filterv audio-attachment new-statuses) statuses))])
|
||||||
[_ statuses] (get updated instance-url)]
|
[_ statuses] (get updated instance-url)]
|
||||||
|
|
@ -69,7 +72,7 @@
|
||||||
(:content status))]
|
(:content status))]
|
||||||
[::xspf/info (-> status :url)]
|
[::xspf/info (-> status :url)]
|
||||||
[::xspf/duration (-> file :meta :original :duration (* 1000) int)]
|
[::xspf/duration (-> file :meta :original :duration (* 1000) int)]
|
||||||
[::xspf/location (:remote_url file)]])) statuses)]]))
|
[::xspf/location (:url file)]])) statuses)]]))
|
||||||
|
|
||||||
(defn app [req]
|
(defn app [req]
|
||||||
(let [instance-url (if (not= "/" (:uri req))
|
(let [instance-url (if (not= "/" (:uri req))
|
||||||
|
|
@ -77,7 +80,8 @@
|
||||||
(-> (str/replace (:uri req) #"^/" "")
|
(-> (str/replace (:uri req) #"^/" "")
|
||||||
(str/replace #".xspf$" "")))
|
(str/replace #".xspf$" "")))
|
||||||
"https://post.lurk.org")
|
"https://post.lurk.org")
|
||||||
statuses (fetch-loops! instance-url)]
|
token (some-> (:body req) (slurp) (json/parse-string true) :token)
|
||||||
|
statuses (fetch-loops instance-url token)]
|
||||||
{:status 200
|
{:status 200
|
||||||
:headers {"Content-Type" "application/xspf+xml"}
|
:headers {"Content-Type" "application/xspf+xml"}
|
||||||
:body (xml/indent-str (->xspf statuses))}))
|
:body (xml/indent-str (->xspf statuses))}))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue