(ns memento (:require [cheshire.core :as json] [org.httpkit.client :as http] [clojure.string :as str]) (:import [java.time LocalDateTime Instant ZoneId Duration] [java.net URLEncoder])) (def acct (System/getenv "MASTODON_ACCOUNT")) (def auth-token (System/getenv "MASTODON_AUTH_TOKEN")) (def assert-msg "Please set the MASTODON_ACCOUNT, MASTODON_AUTH_TOKEN and MEMENTO_ACCOUNT env vars.") (assert (not (empty? acct)) assert-msg) (assert (not (empty? auth-token)) assert-msg) (def instance-url (format "https://%s" (last (str/split acct #"@")))) (defn mastodon-api [path params] (-> @(http/request (merge-with #(if (map? %1) (merge %1 %2) %2) {:url (format "%s/%s" instance-url path) :method :get :headers {"Authorization" (format "Bearer %s" auth-token)}} params)) (update :body #(json/parse-string % true)))) (defn prn-res [res] (prn (assoc-in res [:opts :headers "Authorization"] "Bearer XXX"))) (println "Requesting account details for" acct) (def account-details (mastodon-api "api/v1/accounts/lookup" {:query-params {:acct acct}})) (prn-res account-details) (def cutoff (.. (Instant/now) (minus (Duration/ofDays 1)))) (println "cutoff" cutoff) (def delete-xf (comp (filter #(. (Instant/parse (:created_at %)) isBefore cutoff)) (remove #(= (:visibility %) "direct")))) (def to-delete (-> (mastodon-api (format "api/v1/accounts/%s/statuses" (-> account-details :body :id)) {:query-params {:tagged "today" :exclude_reblogs true}}) (update :body #(into [] delete-xf %)))) (defn sleep [ms] (future (Thread/sleep ms))) (doseq [status (:body to-delete)] (try (print "Deleting post ") (prn (select-keys status [:created_at :url])) (let [deleted (mastodon-api (format "api/v1/statuses/%s" (:id status)) {:method :delete})] (print "Deleted ") (prn-res deleted) @(sleep 2500) ; we need to wait, otherwise media_ids are still "attached" and can't be reused (print "Recreating ") (prn-res (mastodon-api (format "api/v1/statuses" #_(:id refiled)) {:method :post :headers {"Content-Type" "application/json"} :body (json/encode {:visibility "direct" :media_ids (map :id (-> deleted :body :media_attachments)) :status (-> deleted :body :text)})}))) (catch Exception e (println "Error deleting " (:url status)) (throw e))))