enable unqalified keywords again
This commit is contained in:
parent
af85887931
commit
1ebb0e71f5
3 changed files with 57 additions and 69 deletions
65
README.md
65
README.md
|
@ -27,7 +27,6 @@ If you get a [permission failure](https://github.com/anmonteiro/lumo/issues/206)
|
||||||
with later timestamps to avoid duplicate posts. On the first run the timestamp will default to current time.
|
with later timestamps to avoid duplicate posts. On the first run the timestamp will default to current time.
|
||||||
|
|
||||||
```clojure
|
```clojure
|
||||||
#:mastodon-bot.core
|
|
||||||
{;; add Twitter config to mirror Twitter accounts
|
{;; add Twitter config to mirror Twitter accounts
|
||||||
:twitter {:access-keys
|
:twitter {:access-keys
|
||||||
{:consumer_key "XXXX"
|
{:consumer_key "XXXX"
|
||||||
|
@ -52,39 +51,37 @@ with later timestamps to avoid duplicate posts. On the first run the timestamp w
|
||||||
;; add RSS config to follow feeds
|
;; add RSS config to follow feeds
|
||||||
:rss {"Hacker News" "https://hnrss.org/newest"
|
:rss {"Hacker News" "https://hnrss.org/newest"
|
||||||
"r/Clojure" "https://www.reddit.com/r/clojure/.rss"}
|
"r/Clojure" "https://www.reddit.com/r/clojure/.rss"}
|
||||||
:mastodon
|
:mastodon {:access_token "XXXX"
|
||||||
#:mastodon-bot.mastodon-api
|
;; account number you see when you log in and go to your profile
|
||||||
{:access_token "XXXX"
|
;; e.g: https://mastodon.social/web/accounts/294795
|
||||||
;; account number you see when you log in and go to your profile
|
:account-id "XXXX"
|
||||||
;; e.g: https://mastodon.social/web/accounts/294795
|
:api_url "https://botsin.space/api/v1/"
|
||||||
:account-id "XXXX"
|
;; optional boolean to mark content as sensitive
|
||||||
:api_url "https://botsin.space/api/v1/"
|
:sensitive? true
|
||||||
;; optional boolean to mark content as sensitive
|
;; optional boolean defaults to false
|
||||||
:sensitive? true
|
;; only sources containing media will be posted when set to true
|
||||||
;; optional boolean defaults to false
|
:media-only? true
|
||||||
;; only sources containing media will be posted when set to true
|
;; optional visibility flag: direct, private, unlisted, public
|
||||||
:media-only? true
|
;; defaults to public
|
||||||
;; optional visibility flag: direct, private, unlisted, public
|
:visibility "unlisted"
|
||||||
;; defaults to public
|
;; optional limit for the post length
|
||||||
:visibility "unlisted"
|
:max-post-length 300
|
||||||
;; optional limit for the post length
|
;; optional flag specifying wether the name of the account
|
||||||
:max-post-length 300
|
;; will be appended in the post, defaults to false
|
||||||
;; optional flag specifying wether the name of the account
|
:append-screen-name? false
|
||||||
;; will be appended in the post, defaults to false
|
;; optional signature for posts
|
||||||
:append-screen-name? false
|
:signature "#newsbot"
|
||||||
;; optional signature for posts
|
;; optionally try to resolve URLs in posts to skip URL shorteners
|
||||||
:signature "#newsbot"
|
;; defaults to false
|
||||||
;; optionally try to resolve URLs in posts to skip URL shorteners
|
:resolve-urls? true
|
||||||
;; defaults to false
|
;; optional content filter regexes
|
||||||
:resolve-urls? true
|
;; any posts matching the regexes will be filtered out
|
||||||
;; optional content filter regexes
|
:content-filters [".*bannedsite.*"]
|
||||||
;; any posts matching the regexes will be filtered out
|
;; optional keyword filter regexes
|
||||||
:content-filters [".*bannedsite.*"]
|
;; any posts not matching the regexes will be filtered out
|
||||||
;; optional keyword filter regexes
|
:keyword-filters [".*clojure.*"]
|
||||||
;; any posts not matching the regexes will be filtered out
|
;; Replace Twitter links by Nitter
|
||||||
:keyword-filters [".*clojure.*"]
|
:nitter-urls? false}}
|
||||||
;; Replace Twitter links by Nitter
|
|
||||||
:nitter-urls? false}}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
* the bot looks for `config.edn` at its relative path by default, an alternative location can be specified either using the `MASTODON_BOT_CONFIG` environment variable or passing the path to config as an argument
|
* the bot looks for `config.edn` at its relative path by default, an alternative location can be specified either using the `MASTODON_BOT_CONFIG` environment variable or passing the path to config as an argument
|
||||||
|
|
|
@ -6,9 +6,7 @@
|
||||||
[clojure.spec.test.alpha :as st]
|
[clojure.spec.test.alpha :as st]
|
||||||
[orchestra.core :refer-macros [defn-spec]]
|
[orchestra.core :refer-macros [defn-spec]]
|
||||||
[cljs.core :refer [*command-line-args*]]
|
[cljs.core :refer [*command-line-args*]]
|
||||||
[cljs.reader :as edn]
|
|
||||||
[clojure.string :as string]
|
[clojure.string :as string]
|
||||||
["fs" :as fs]
|
|
||||||
["rss-parser" :as rss]
|
["rss-parser" :as rss]
|
||||||
["tumblr" :as tumblr]
|
["tumblr" :as tumblr]
|
||||||
["twitter" :as twitter]
|
["twitter" :as twitter]
|
||||||
|
@ -20,23 +18,14 @@
|
||||||
(s/def ::tumblr map?)
|
(s/def ::tumblr map?)
|
||||||
(s/def ::rss map?)
|
(s/def ::rss map?)
|
||||||
|
|
||||||
(def config? (s/keys :req [::mastodon-config]
|
(def config? (s/keys :req-un [::mastodon-config]
|
||||||
:opt [::twitter ::tumblr ::rss]))
|
:opt-un [::twitter ::tumblr ::rss]))
|
||||||
|
|
||||||
;this has to stay on top - only ns-keywords can be uses in spec
|
|
||||||
(defn-spec mastodon-config ::mastodon-config
|
(defn-spec mastodon-config ::mastodon-config
|
||||||
[config config?]
|
[config config?]
|
||||||
(::mastodon-config config))
|
(:mastodon-config config))
|
||||||
|
|
||||||
(defn find-config []
|
(def config (infra/load-config))
|
||||||
(let [config (or (first *command-line-args*)
|
|
||||||
(-> js/process .-env .-MASTODON_BOT_CONFIG)
|
|
||||||
"config.edn")]
|
|
||||||
(if (fs/existsSync config)
|
|
||||||
config
|
|
||||||
(infra/exit-with-error (str "failed to read config: " config)))))
|
|
||||||
|
|
||||||
(def config (-> (find-config) (fs/readFileSync #js {:encoding "UTF-8"}) edn/read-string))
|
|
||||||
|
|
||||||
(defn trim-text [text]
|
(defn trim-text [text]
|
||||||
(let [max-post-length (masto/max-post-length (mastodon-config config))]
|
(let [max-post-length (masto/max-post-length (mastodon-config config))]
|
||||||
|
@ -139,7 +128,7 @@
|
||||||
(fn [timeline]
|
(fn [timeline]
|
||||||
(let [last-post-time (-> timeline first :created_at (js/Date.))]
|
(let [last-post-time (-> timeline first :created_at (js/Date.))]
|
||||||
;;post from Twitter
|
;;post from Twitter
|
||||||
(when-let [twitter-config (::twitter config)]
|
(when-let [twitter-config (:twitter config)]
|
||||||
(let [{:keys [access-keys accounts include-replies? include-rts?]} twitter-config
|
(let [{:keys [access-keys accounts include-replies? include-rts?]} twitter-config
|
||||||
client (twitter-client access-keys)]
|
client (twitter-client access-keys)]
|
||||||
(doseq [account accounts]
|
(doseq [account accounts]
|
||||||
|
|
|
@ -29,33 +29,33 @@
|
||||||
|
|
||||||
(s/def ::content-filters (s/* ::content-filter))
|
(s/def ::content-filters (s/* ::content-filter))
|
||||||
(s/def ::keyword-filters (s/* ::keyword-filter))
|
(s/def ::keyword-filters (s/* ::keyword-filter))
|
||||||
(s/def ::mastodon-js-config (s/keys :req [::access_token ::api_url]))
|
(s/def ::mastodon-js-config (s/keys :req-un [::access_token ::api_url]))
|
||||||
(s/def ::mastodon-clj-config (s/keys :req [::account-id ::content-filters ::keyword-filters
|
(s/def ::mastodon-clj-config (s/keys :req-un [::account-id ::content-filters ::keyword-filters
|
||||||
::max-post-length ::signature ::visibility
|
::max-post-length ::signature ::visibility
|
||||||
::append-screen-name? ::sensitive? ::resolve-urls?
|
::append-screen-name? ::sensitive? ::resolve-urls?
|
||||||
::nitter-urls? ::replacements]))
|
::nitter-urls? ::replacements]))
|
||||||
(def mastodon-config? (s/merge ::mastodon-js-config ::mastodon-clj-config))
|
(def mastodon-config? (s/merge ::mastodon-js-config ::mastodon-clj-config))
|
||||||
|
|
||||||
(defn-spec content-filter-regexes ::content-filters
|
(defn-spec content-filter-regexes ::content-filters
|
||||||
[mastodon-config mastodon-config?]
|
[mastodon-config mastodon-config?]
|
||||||
(mapv re-pattern (::content-filters mastodon-config)))
|
(mapv re-pattern (:content-filters mastodon-config)))
|
||||||
|
|
||||||
(defn-spec keyword-filter-regexes ::keyword-filters
|
(defn-spec keyword-filter-regexes ::keyword-filters
|
||||||
[mastodon-config mastodon-config?]
|
[mastodon-config mastodon-config?]
|
||||||
(mapv re-pattern (::keyword-filters mastodon-config)))
|
(mapv re-pattern (:keyword-filters mastodon-config)))
|
||||||
|
|
||||||
(defn-spec append-screen-name? ::append-screen-name?
|
(defn-spec append-screen-name? ::append-screen-name?
|
||||||
[mastodon-config mastodon-config?]
|
[mastodon-config mastodon-config?]
|
||||||
(boolean (::append-screen-name? mastodon-config)))
|
(boolean (:append-screen-name? mastodon-config)))
|
||||||
|
|
||||||
(defn-spec max-post-length ::max-post-length
|
(defn-spec max-post-length ::max-post-length
|
||||||
[mastodon-config mastodon-config?]
|
[mastodon-config mastodon-config?]
|
||||||
(::max-post-length mastodon-config))
|
(:max-post-length mastodon-config))
|
||||||
|
|
||||||
(defn-spec perform-replacements string?
|
(defn-spec perform-replacements string?
|
||||||
[mastodon-config mastodon-config?
|
[mastodon-config mastodon-config?
|
||||||
text string?]
|
text string?]
|
||||||
(reduce-kv string/replace text (::replacements mastodon-config)))
|
(reduce-kv string/replace text (:replacements mastodon-config)))
|
||||||
|
|
||||||
(defn-spec mastodon-client any?
|
(defn-spec mastodon-client any?
|
||||||
[mastodon-config mastodon-config?]
|
[mastodon-config mastodon-config?]
|
||||||
|
@ -94,15 +94,15 @@
|
||||||
[mastodon-config mastodon-config?
|
[mastodon-config mastodon-config?
|
||||||
text string?]
|
text string?]
|
||||||
(cond-> text
|
(cond-> text
|
||||||
(::resolve-urls? mastodon-config)
|
(:resolve-urls? mastodon-config)
|
||||||
(string/replace shortened-url-pattern resolve-url)
|
(string/replace shortened-url-pattern resolve-url)
|
||||||
(::nitter-urls? mastodon-config)
|
(:nitter-urls? mastodon-config)
|
||||||
(string/replace #"https://twitter.com" "https://nitter.net")))
|
(string/replace #"https://twitter.com" "https://nitter.net")))
|
||||||
|
|
||||||
(defn-spec set-signature string?
|
(defn-spec set-signature string?
|
||||||
[mastodon-config mastodon-config?
|
[mastodon-config mastodon-config?
|
||||||
text string?]
|
text string?]
|
||||||
(if-let [signature (::signature mastodon-config )]
|
(if-let [signature (:signature mastodon-config )]
|
||||||
(str text "\n" signature)
|
(str text "\n" signature)
|
||||||
text))
|
text))
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@
|
||||||
([mastodon-config status-text media-ids]
|
([mastodon-config status-text media-ids]
|
||||||
(post-status mastodon-config status-text media-ids print))
|
(post-status mastodon-config status-text media-ids print))
|
||||||
([mastodon-config status-text media-ids callback]
|
([mastodon-config status-text media-ids callback]
|
||||||
(let [{:mastodon-bot.mastodon-api/keys [sensitive? signature visibility]} mastodon-config]
|
(let [{:keys [sensitive? signature visibility]} mastodon-config]
|
||||||
(-> (.post (mastodon-client mastodon-config) "statuses"
|
(-> (.post (mastodon-client mastodon-config) "statuses"
|
||||||
(clj->js (merge {:status (->> status-text
|
(clj->js (merge {:status (->> status-text
|
||||||
(resolve-urls mastodon-config)
|
(resolve-urls mastodon-config)
|
||||||
|
@ -134,22 +134,24 @@
|
||||||
|
|
||||||
(defn post-status-with-images
|
(defn post-status-with-images
|
||||||
([mastodon-config status-text urls]
|
([mastodon-config status-text urls]
|
||||||
(post-status-with-images mastodon-config status-text urls []))
|
(post-status-with-images mastodon-config status-text urls [] print))
|
||||||
([mastodon-config status-text [url & urls] ids]
|
([mastodon-config status-text urls ids]
|
||||||
|
(post-status-with-images mastodon-config status-text urls ids print))
|
||||||
|
([mastodon-config status-text [url & urls] ids callback]
|
||||||
(if url
|
(if url
|
||||||
(-> request
|
(-> request
|
||||||
(.get url)
|
(.get url)
|
||||||
(.on "response"
|
(.on "response"
|
||||||
(fn [image-stream]
|
(fn [image-stream]
|
||||||
(post-image mastodon-config image-stream status-text
|
(post-image mastodon-config image-stream status-text
|
||||||
#(post-status-with-images status-text urls (conj ids %))))))
|
#(post-status-with-images status-text urls (conj ids %) callback)))))
|
||||||
(post-status mastodon-config status-text (not-empty ids)))))
|
(post-status mastodon-config status-text (not-empty ids) callback))))
|
||||||
|
|
||||||
(defn-spec get-mastodon-timeline any?
|
(defn-spec get-mastodon-timeline any?
|
||||||
[mastodon-config mastodon-config?
|
[mastodon-config mastodon-config?
|
||||||
callback fn?]
|
callback fn?]
|
||||||
(.then (.get (mastodon-client mastodon-config)
|
(.then (.get (mastodon-client mastodon-config)
|
||||||
(str "accounts/" (::account-id mastodon-config)"/statuses") #js {})
|
(str "accounts/" (:account-id mastodon-config)"/statuses") #js {})
|
||||||
#(let [response (-> % .-data infra/js->edn)]
|
#(let [response (-> % .-data infra/js->edn)]
|
||||||
(if-let [error (::error response)]
|
(if-let [error (::error response)]
|
||||||
(infra/exit-with-error error)
|
(infra/exit-with-error error)
|
||||||
|
|
Reference in a new issue