status-mobile/src/status_im/bots/events.cljs

107 lines
3.8 KiB
Clojure

(ns status-im.bots.events
(:require [re-frame.core :as re-frame]
[status-im.utils.core :as utils]
[status-im.utils.handlers :as handlers]
[status-im.chat.models.input :as input-model]
[taoensso.timbre :as log]))
;;;; Helper fns
(defn- subscription-values [sub-params current-bot-db]
(reduce (fn [sub-values [sub-key sub-path]]
(assoc sub-values sub-key (get-in current-bot-db sub-path)))
{}
sub-params))
(defn- check-subscriptions-fx
[{:keys [bot-db] :contacts/keys [contacts] :as app-db} {:keys [bot path]}]
(when-let [subscriptions (and bot (get-in contacts (concat [bot :subscriptions] [path])))]
{:call-jail-function-n
(for [[sub-name sub-params] subscriptions]
{:chat-id bot
:function :subscription
:parameters {:name sub-name
:subscriptions (subscription-values sub-params (get bot-db bot))}
:callback-event-creator (fn [jail-response]
[::calculated-subscription
{:bot bot
:path [sub-name]
:result jail-response}])})}))
(defn set-in-bot-db
"Associates value at specified path in bot-db and checks if there are any subscriptions
dependent on that path, if yes, adds effects for calling jail-functions to recalculate
relevant subscriptions."
[app-db {:keys [bot path value] :as params}]
(let [new-db (assoc-in app-db (concat [:bot-db bot] path) value)]
(merge {:db new-db}
(check-subscriptions-fx new-db params))))
(defn update-bot-db
[app-db {:keys [bot db]}]
(update-in app-db [:bot-db bot] merge db))
(defn clear-bot-db
[app-db bot-id]
(assoc-in app-db [:bot-db bot-id] nil))
(def ^:private keywordize-vector (partial mapv keyword))
(defn transform-bot-subscriptions
"Transforms bot subscriptions as returned from jail in the following format:
`{:calculatedFee {:subscriptions {:value [\"sliderValue\"]
:tx [\"transaction\"]}}
:feeExplanation {:subscriptions {:value [\"sliderValue\"]}}}`
into data-structure better suited for subscription lookups based on changes
in `:bot-db`:
`{[:sliderValue] {:calculatedFee {:value [:sliderValue]
:tx [:transaction]}
:feeExplanation {:value [:sliderValue]}}
[:transaction] {:calculatedFee {:value [:sliderValue]
:tx [:transaction]}}}`
In the resulting data-structure, the top level keys are the (keywordized) paths
in the `:bot-db` data structure, so it's quick and easy to look-up all the
subscriptions which must be recalculated when something in their path changes."
[bot-subscriptions]
(reduce-kv (fn [acc sub-key {:keys [subscriptions]}]
(reduce-kv (fn [acc sub-param-key sub-param-path]
(update acc
(keywordize-vector sub-param-path)
assoc sub-key
(utils/map-values subscriptions keywordize-vector)))
acc
subscriptions))
{}
bot-subscriptions))
(defn calculated-subscription
[db {:keys [bot path]
{:keys [error result]} :result}]
(if error
db
(assoc-in db (concat [:bot-db bot] path) (:returned result))))
;;;; Handlers
(handlers/register-handler-fx
:set-in-bot-db
[re-frame/trim-v]
(fn [{:keys [db]} [params]]
(set-in-bot-db db params)))
(handlers/register-handler-db
:update-bot-db
[re-frame/trim-v]
(fn [db [params]]
(update-bot-db db params)))
(handlers/register-handler-db
::calculated-subscription
[re-frame/trim-v]
(fn [db [params]]
(calculated-subscription db params)))