This repository has been archived on 2023-07-28. You can view files and clone it, but cannot push or open issues or pull requests.
mastodon-bot/src/main/mastodon_bot/core.cljs

145 lines
4.7 KiB
Text
Raw Normal View History

2020-05-12 16:17:37 +00:00
#!/usr/bin/env lumo
(ns mastodon-bot.core
(:require
[clojure.spec.alpha :as s]
[clojure.spec.test.alpha :as st]
[orchestra.core :refer-macros [defn-spec]]
[cljs.core :refer [*command-line-args*]]
[clojure.string :as string]
["rss-parser" :as rss]
["tumblr" :as tumblr]
[mastodon-bot.infra :as infra]
2020-05-15 17:25:31 +00:00
[mastodon-bot.mastodon-api :as masto]
2020-05-15 17:31:36 +00:00
[mastodon-bot.twitter-api :as twitter]))
2020-05-12 16:17:37 +00:00
(s/def ::mastodon-config masto/mastodon-config?)
2020-05-15 17:31:36 +00:00
(s/def ::twitter twitter/twitter-config?)
2020-05-13 15:41:27 +00:00
(s/def ::tumblr map?)
(s/def ::rss map?)
2020-05-13 15:49:37 +00:00
2020-05-14 06:56:50 +00:00
(def config? (s/keys :req-un [::mastodon-config]
:opt-un [::twitter ::tumblr ::rss]))
2020-05-12 16:17:37 +00:00
(defn-spec mastodon-config ::mastodon-config
[config config?]
2020-05-14 06:56:50 +00:00
(:mastodon-config config))
2020-05-12 16:17:37 +00:00
2020-05-15 17:25:31 +00:00
(defn-spec twitter-config ::twitter
[config config?]
(:twitter config))
2020-05-14 06:56:50 +00:00
(def config (infra/load-config))
2020-05-12 16:17:37 +00:00
(defn trim-text [text]
(let [max-post-length (masto/max-post-length (mastodon-config config))]
(cond
(nil? max-post-length)
text
(> (count text) max-post-length)
(reduce
(fn [text word]
(if (> (+ (count text) (count word)) (- max-post-length 3))
(reduced (str text "..."))
(str text " " word)))
""
(string/split text #" "))
:else text)))
(defn in [needle haystack]
(some (partial = needle) haystack))
; If the text ends in a link to the media (which is uploaded anyway),
; chop it off instead of including the link in the toot
(defn chop-tail-media-url [text media]
(string/replace text #" (\S+)$" #(if (in (%1 1) (map :url media)) "" (%1 0))))
(defn parse-tweet [{created-at :created_at
text :full_text
{:keys [media]} :extended_entities
{:keys [screen_name]} :user :as tweet}]
{:created-at (js/Date. created-at)
:text (trim-text (str (chop-tail-media-url text media)
(if (masto/append-screen-name? (mastodon-config config))
2020-05-13 16:23:17 +00:00
(str "\n - " screen_name) "")))
2020-05-12 16:17:37 +00:00
:media-links (keep #(when (= (:type %) "photo") (:media_url_https %)) media)})
(defmulti parse-tumblr-post :type)
(defmethod parse-tumblr-post "text" [{:keys [body date short_url]}]
{:created-at (js/Date. date)
:text (str (trim-text body) "\n\n" short_url)})
(defmethod parse-tumblr-post "photo" [{:keys [caption date photos short_url] :as post}]
{:created-at (js/Date. date)
:text (string/join "\n" [(string/replace caption #"<[^>]*>" "") short_url])
:media-links (mapv #(-> % :original_size :url) photos)})
(defmethod parse-tumblr-post :default [post])
(defn post-tumblrs [last-post-time]
(fn [err response]
(->> response
infra/js->edn
:posts
(mapv parse-tumblr-post)
(masto/post-items
(mastodon-config config)
last-post-time))))
(defn post-tweets [last-post-time]
(fn [error tweets response]
(if error
(infra/exit-with-error error)
(->> (infra/js->edn tweets)
(map parse-tweet)
(masto/post-items
(mastodon-config config)
last-post-time)))))
(defn parse-feed [last-post-time parser [title url]]
(-> (.parseURL parser url)
(.then #(masto/post-items
(mastodon-config config)
last-post-time
(for [{:keys [title isoDate pubDate content link]} (-> % infra/js->edn :items)]
{:created-at (js/Date. (or isoDate pubDate))
2020-05-15 17:31:36 +00:00
:text (str (trim-text title) "\n\n" (twitter/strip-utm link))})))))
2020-05-12 16:17:37 +00:00
(defn tumblr-client [access-keys account]
(try
(tumblr/Blog. account (clj->js access-keys))
(catch js/Error e
(infra/exit-with-error
(str "failed to connect to Tumblr account " account ": " (.-message e))))))
(defn -main []
(masto/get-mastodon-timeline
(mastodon-config config)
(fn [timeline]
(let [last-post-time (-> timeline first :created_at (js/Date.))]
;;post from Twitter
2020-05-14 06:56:50 +00:00
(when-let [twitter-config (:twitter config)]
2020-05-15 17:25:31 +00:00
(let [{:keys [accounts]} twitter-config]
2020-05-12 16:17:37 +00:00
(doseq [account accounts]
2020-05-15 17:31:36 +00:00
(twitter/user-timeline
2020-05-15 17:25:31 +00:00
twitter-config
account
(post-tweets last-post-time)))))
2020-05-12 16:17:37 +00:00
;;post from Tumblr
(when-let [{:keys [access-keys accounts limit]} (:tumblr config)]
(doseq [account accounts]
(let [client (tumblr-client access-keys account)]
(.posts client #js {:limit (or limit 5)} (post-tumblrs last-post-time)))))
;;post from RSS
(when-let [feeds (some-> config :rss)]
(let [parser (rss.)]
(doseq [feed feeds]
(parse-feed last-post-time parser feed))))))))
(set! *main-cli-fn* -main)
2020-05-13 15:49:37 +00:00
(st/instrument 'mastodon-config)