102 lines
4 KiB
Clojure
102 lines
4 KiB
Clojure
(ns micro-blog.pocket-base
|
|
(:require
|
|
[clojure.pprint :refer [pprint]]
|
|
[clojure.string :as str]
|
|
[clj-http.client :as http-client]
|
|
[malli.core :as m]
|
|
[micro-blog.utils :as utils]
|
|
[micro-blog.config :refer [config]]))
|
|
|
|
(defonce token-cache ^:private (atom {:token nil :fetched-at nil}))
|
|
(defn- now []
|
|
(java.time.Instant/now))
|
|
|
|
(defn older-then-a-day? [fetched-at]
|
|
(when fetched-at
|
|
(let [duration (java.time.Duration/between fetched-at (now))]
|
|
(> (.toHours duration) 23)))) ; 23 to be safe, or use 24
|
|
|
|
(defn get-login-token []
|
|
(let [user-name (@config :pocket-base-user)
|
|
pw (@config :pocket-base-pw)
|
|
body {:identity user-name :password pw}
|
|
url (str (@config :pocket-base-host) "/api/collections/users/auth-with-password")]
|
|
(->
|
|
(http-client/post url
|
|
{:form-params body
|
|
:content-type :json
|
|
:as :json})
|
|
:body
|
|
:token)))
|
|
|
|
(defn get-login-token-with-cache []
|
|
(let [{:keys [token fetched-at]} @token-cache]
|
|
(if (and token (not (older-then-a-day? fetched-at)))
|
|
token
|
|
(let [new-token (get-login-token)]
|
|
(println "Getting new login token")
|
|
(reset! token-cache {:token new-token :fetched-at (now)})
|
|
new-token))))
|
|
|
|
(def source-enum [:enum :pleroma :blue_sky :mastodon :pixelfed :nostr])
|
|
(defn valid-source? [source]
|
|
(m/validate source-enum source))
|
|
|
|
(defn get-latest-post-remote-id-by-source [source]
|
|
(let [res-schema
|
|
[:map
|
|
[:items
|
|
[:vector
|
|
[:map
|
|
[:id string?]
|
|
[:remoteId string?]]]]]]
|
|
(when (not (valid-source? source))
|
|
(throw (ex-info "Invalid source" {:source source})))
|
|
(as->
|
|
(http-client/get (str (@config :pocket-base-host) "/api/collections/micro_blog_posts/records")
|
|
{:headers {"Authorization" (get-login-token-with-cache)}
|
|
:query-params {:page 1
|
|
"perPage" 1
|
|
:sort "-posted"
|
|
:filter (str "source = '" (name source) "'")
|
|
:fields (str/join "," ["remoteId" "id"])
|
|
"skipTotal" true}
|
|
:content-type :json
|
|
:as :json}) x
|
|
(:body x)
|
|
(if (m/validate res-schema x)
|
|
x
|
|
(do
|
|
(m/explain res-schema x)
|
|
(throw (ex-info "Res does not follow schema" {:res x}))))
|
|
(-> x :items first :remoteId))))
|
|
|
|
(defn post-with-remote-id-already-saved? [remote-id]
|
|
(->
|
|
(http-client/get (str (@config :pocket-base-host) "/api/collections/micro_blog_posts/records")
|
|
{:headers {"Authorization" (get-login-token-with-cache)}
|
|
:query-params {:page 1
|
|
"perPage" 1
|
|
:filter (str "remoteId = '" remote-id "'")
|
|
:fields "id"
|
|
"skipTotal" true}
|
|
:content-type :json
|
|
:as :json})
|
|
:body :items count (> 0)))
|
|
|
|
(defn save-post [post]
|
|
(printf "Saving %s post with remoteId: %s\n" (name (:source post)) (:remoteId post))
|
|
(let [save-post-schema [:map
|
|
[:source source-enum]
|
|
[:fullPost :any]
|
|
[:remoteId :string]
|
|
[:authorId :string]
|
|
[:posted :string]]]
|
|
(utils/validate-with-throw post save-post-schema)
|
|
(if (post-with-remote-id-already-saved? (:remoteId post))
|
|
(println "post already saved")
|
|
(http-client/post (str (@config :pocket-base-host) "/api/collections/micro_blog_posts/records")
|
|
{:headers {"Authorization" (get-login-token-with-cache)}
|
|
:form-params post
|
|
:content-type :json
|
|
:as :json}))))
|