Simplify input handling

Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
janherich 2018-02-17 12:48:05 +01:00 committed by Andrey Shovkoplyas
parent 526d11469a
commit 15f4c90caa
No known key found for this signature in database
GPG Key ID: EAAB7C8622D860A4
7 changed files with 116 additions and 207 deletions

View File

@ -26,7 +26,7 @@
content-command-name :content-command content-command-name :content-command
:keys [content-command-scope-bitmask bot scope-bitmask params type]} :content :keys [content-command-scope-bitmask bot scope-bitmask params type]} :content
:keys [chat-id group-id jail-id] :as message} :keys [chat-id group-id jail-id] :as message}
{:keys [data-type proceed-event-creator cache-data?] :as opts}] {:keys [data-type] :as opts}]
(let [{:accounts/keys [current-account-id] (let [{:accounts/keys [current-account-id]
:contacts/keys [contacts]} db :contacts/keys [contacts]} db
jail-id (or bot jail-id chat-id) jail-id (or bot jail-id chat-id)
@ -56,21 +56,9 @@
(handlers/register-handler-fx (handlers/register-handler-fx
::jail-command-data-response ::jail-command-data-response
[re-frame/trim-v] [re-frame/trim-v]
(fn [{:keys [db]} [{{:keys [returned]} :result} (fn [{:keys [db]} [{{:keys [returned]} :result} {:keys [chat-id]} {:keys [proceed-event-creator]}]]
{:keys [message-id chat-id]} (when proceed-event-creator
{:keys [data-type proceed-event-creator cache-data?]}]] {:dispatch (proceed-event-creator returned)})))
(let [existing-message (get-in db [:chats chat-id :messages message-id])]
(cond-> {}
(and cache-data? existing-message returned)
(as-> fx
(let [updated-message (assoc-in existing-message [:content data-type] returned)]
(assoc fx
:db (assoc-in db [:chats chat-id :messages message-id] updated-message)
:update-message (select-keys updated-message [:message-id :content]))))
proceed-event-creator
(assoc :dispatch (proceed-event-creator returned))))))
(handlers/register-handler-fx (handlers/register-handler-fx
:request-command-message-data :request-command-message-data

View File

@ -236,77 +236,50 @@
(min (count input-text)))] (min (count input-text)))]
(merge fx (update-text-selection new-db new-selection))))))) (merge fx (update-text-selection new-db new-selection)))))))
(defn- request-command-data ;; function creating "message shaped" data from command, because that's what `request-command-message-data` expects
"Requests command data from jail" (defn- command->message
[{:keys [bot-db] :contacts/keys [contacts] :as db} [{:keys [bot-db current-chat-id chats]} {:keys [command] :as command-params}]
{{:keys [command (cond-> {:chat-id current-chat-id
metadata :jail-id (:owner-id command)
args] :content {:command (:name command)
:as content} :content :type (:type command)
:keys [chat-id group-id jail-id data-type event-after-creator message-id current-time]}] :scope-bitmask (:scope-bitmask command)
(let [{:keys [dapp? dapp-url name]} (get contacts chat-id) :params (assoc (input-model/args->params command-params)
metadata (merge metadata :bot-db (get bot-db (:owner-id command)))}}
(when dapp? (get-in chats [current-chat-id :group-chat])
{:url (i18n/get-contact-translated chat-id :dapp-url dapp-url) (assoc :group-id current-chat-id)))
:name (i18n/get-contact-translated chat-id :name name)}))
owner-id (:owner-id command)
bot-db (get bot-db owner-id)
params (merge (input-model/args->params content)
{:bot-db bot-db
:metadata metadata})
command-message {:command command
:params params
:to-message (:to-message-id metadata)
:created-at current-time
:id message-id
:chat-id chat-id
:jail-id (or owner-id jail-id)}
request-data {:message-id message-id
:chat-id chat-id
:group-id group-id
:jail-id (or owner-id jail-id)
:content {:command (:name command)
:scope-bitmask (:scope-bitmask command)
:params params
:type (:type command)}}]
(commands-events/request-command-message-data db request-data
{:data-type data-type
:proceed-event-creator (partial event-after-creator
command-message)})))
;; TODO (janherich) request-command-data functions and event need to be refactored, they are needlessly complicated
(defn proceed-command (defn proceed-command
"Proceed with command processing by setting up and executing chain of events: "Proceed with command processing by creating command message + setting up and executing chain of events:
1. Params validation 1. Params validation
2. Short preview fetching 2. Short preview fetching
3. Preview fetching" 3. Preview fetching"
[{:keys [current-chat-id chats] :as db} {{:keys [bot]} :command :as content} message-id current-time] [{:keys [bot-db current-chat-id chats] :as db} {:keys [command metadata] :as command-params} message-id current-time]
(let [params-template {:content content (let [message (command->message db command-params)
:chat-id current-chat-id cmd-params {:command command
:group-id (when (get-in chats [current-chat-id :group-chat]) :params (get-in message [:content :params])
current-chat-id) :to-message (:to-message-id metadata)
:jail-id (or bot current-chat-id) :created-at current-time
:message-id message-id :id message-id
:current-time current-time} :chat-id current-chat-id
preview-params (merge params-template :jail-id (:jail-id message)}
{:data-type :preview event-chain {:data-type :validator
:event-after-creator (fn [command-message jail-response] :proceed-event-creator (fn [validation-response]
[::send-command [::proceed-validation
(assoc-in command-message [:command :preview] jail-response)])}) validation-response
short-preview-params (merge params-template [[:request-command-message-data
{:data-type :short-preview message
:event-after-creator (fn [_ jail-response] {:data-type :short-preview
[::request-command-data :proceed-event-creator (fn [short-preview]
(assoc-in preview-params [:content :command :short-preview] jail-response)])}) [:request-command-message-data
validation-params (merge params-template message
{:data-type :validator {:data-type :preview
:event-after-creator (fn [_ jail-response] :proceed-event-creator (fn [preview]
[::proceed-validation [::send-command
jail-response (update cmd-params :command merge
[[::request-command-data short-preview-params]]])})] {:short-preview short-preview
(request-command-data db validation-params))) :preview preview})])}])}]]])}]
(commands-events/request-command-message-data db message event-chain)))
;;;; Handlers ;;;; Handlers
@ -392,28 +365,22 @@
(validator params error-events-creator))] (validator params error-events-creator))]
{:dispatch-n (or error-events proceed-events)}))) {:dispatch-n (or error-events proceed-events)})))
(handlers/register-handler-fx
::request-command-data
[re-frame/trim-v]
(fn [{:keys [db]} [command-params]]
(request-command-data db command-params)))
(handlers/register-handler-fx (handlers/register-handler-fx
::send-command ::send-command
message-model/send-interceptors message-model/send-interceptors
(fn [cofx [{:keys [command] :as command-message}]] (fn [{:keys [db] :as cofx} [{:keys [command] :as command-message}]]
(let [{{:keys [current-public-key current-chat-id] (let [{:keys [current-public-key current-chat-id] :accounts/keys [current-account-id]} db
:accounts/keys [current-account-id] :as db} :db} cofx new-db (-> (model/set-chat-ui-props db {:sending-in-progress? false})
fx (message-model/process-command cofx (clear-seq-arguments)
(set-chat-input-metadata nil)
(set-chat-input-text nil))]
(merge {:db new-db}
(message-model/process-command (assoc cofx :db new-db)
{:message (get-in db [:chats current-chat-id :input-text]) {:message (get-in db [:chats current-chat-id :input-text])
:command command-message :command command-message
:chat-id current-chat-id :chat-id current-chat-id
:identity current-public-key :identity current-public-key
:address current-account-id})] :address current-account-id})))))
(update fx :db #(-> %
(clear-seq-arguments)
(set-chat-input-metadata nil)
(set-chat-input-text nil))))))
(defn command-complete? (defn command-complete?
[chat-command] [chat-command]
@ -443,8 +410,7 @@
(set-chat-input-text nil))) (set-chat-input-text nil)))
{:message-text input-text {:message-text input-text
:chat-id current-chat-id :chat-id current-chat-id
:identity current-public-key :identity current-public-key})))
:address (:accounts/current-account-id db)})))
(handlers/register-handler-fx (handlers/register-handler-fx
@ -490,15 +456,13 @@
seq-arguments (get-in chats [current-chat-id :seq-arguments]) seq-arguments (get-in chats [current-chat-id :seq-arguments])
command (-> (input-model/selected-chat-command db) command (-> (input-model/selected-chat-command db)
(assoc :args (into [] (conj seq-arguments text))))] (assoc :args (into [] (conj seq-arguments text))))]
(request-command-data db {:content command (commands-events/request-command-message-data db (command->message db command)
:chat-id current-chat-id {:data-type :validator
:jail-id (or (get-in command [:command :bot]) current-chat-id) :proceed-event-creator (fn [validation-response]
:data-type :validator [::proceed-validation
:event-after-creator (fn [_ jail-response] validation-response
[::proceed-validation [[::update-seq-arguments current-chat-id]
jail-response [:send-current-message]]])}))))
[[::update-seq-arguments current-chat-id]
[:send-current-message]]])}))))
(handlers/register-handler-db (handlers/register-handler-db
:set-chat-seq-arg-input-text :set-chat-seq-arg-input-text

View File

@ -12,7 +12,7 @@
;; Effects ;; Effects
(re-frame/reg-fx (re-frame/reg-fx
:chat-requests/mark-as-answered ::mark-as-answered
(fn [{:keys [chat-id message-id]}] (fn [{:keys [chat-id message-id]}]
(requests-store/mark-as-answered chat-id message-id))) (requests-store/mark-as-answered chat-id message-id)))
@ -21,15 +21,15 @@
(fn [request] (fn [request]
(requests-store/save request))) (requests-store/save request)))
;; Handlers ;; Functions
(handlers/register-handler-fx (defn request-answered
:request-answered "Takes fx, chat-id and message, updates fx with necessary data for markin request as answered"
[re-frame/trim-v] [fx chat-id message-id]
(fn [{:keys [db]} [chat-id message-id]] (-> fx
{:db (update-in db [:chats chat-id :requests] dissoc message-id) (update-in [:db :chats chat-id :requests] dissoc message-id)
:chat-requests/mark-as-answered {:chat-id chat-id (assoc ::mark-as-answered {:chat-id chat-id
:message-id message-id}})) :message-id message-id})))
(defn add-request (defn add-request
"Takes fx, chat-id and message, updates fx with necessary data for adding new request" "Takes fx, chat-id and message, updates fx with necessary data for adding new request"

View File

@ -37,7 +37,7 @@
:chat-send-message/send-command :chat-send-message/send-command
message-model/send-interceptors message-model/send-interceptors
(fn [cofx [add-to-chat-id params]] (fn [cofx [add-to-chat-id params]]
(message-model/send-command cofx nil add-to-chat-id params))) (message-model/send-command cofx add-to-chat-id params)))
(handlers/register-handler-fx (handlers/register-handler-fx
:chat-send-message/from-jail :chat-send-message/from-jail

View File

@ -4,10 +4,8 @@
[status-im.chat.events.console :as console-events] [status-im.chat.events.console :as console-events]
[status-im.chat.events.requests :as requests-events] [status-im.chat.events.requests :as requests-events]
[status-im.chat.models :as chat-model] [status-im.chat.models :as chat-model]
[status-im.chat.models.commands :as commands-model] [status-im.chat.models.commands :as commands-model]
[status-im.utils.datetime :as datetime-utils] [status-im.utils.clocks :as clocks-utils]))
[status-im.utils.clocks :as clocks-utils]
[status-im.utils.random :as random]))
(defn- get-current-account (defn- get-current-account
[{:accounts/keys [accounts current-account-id]}] [{:accounts/keys [accounts current-account-id]}]
@ -102,10 +100,10 @@
[(re-frame/inject-cofx :random-id) (re-frame/inject-cofx :random-id-seq) [(re-frame/inject-cofx :random-id) (re-frame/inject-cofx :random-id-seq)
(re-frame/inject-cofx :get-stored-chat) re-frame/trim-v]) (re-frame/inject-cofx :get-stored-chat) re-frame/trim-v])
(defn- handle-message-from-bot [cofx {:keys [message chat-id]}] (defn- handle-message-from-bot [{:keys [random-id] :as cofx} {:keys [message chat-id]}]
(when-let [message (cond (when-let [message (cond
(string? message) (string? message)
{:message-id (random/id) {:message-id random-id
:content (str message) :content (str message)
:content-type constants/text-content-type :content-type constants/text-content-type
:outgoing false :outgoing false
@ -114,7 +112,7 @@
:to "me"} :to "me"}
(= "request" (:type message)) (= "request" (:type message))
{:message-id (random/id) {:message-id random-id
:content (assoc (:content message) :bot chat-id) :content (assoc (:content message) :bot chat-id)
:content-type constants/content-type-command-request :content-type constants/content-type-command-request
:outgoing false :outgoing false
@ -140,38 +138,23 @@
:from current-account-id}}}))) :from current-account-id}}})))
(defn- generate-message (defn- generate-message
[{:keys [web3 current-public-key chats network-status]} [{:keys [network-status]} chat-id message]
{:keys [chat-id command message] :as args}] (assoc (select-keys message [:from :message-id])
(if command :payload (cond-> (select-keys message [:content :content-type :clock-value :timestamp :show?])
(let [payload (-> command (= :offline network-status)
(select-keys [:content :content-type (assoc :show? false))))
:clock-value :show?])
(assoc :timestamp (datetime-utils/now-ms)))
payload (if (= network-status :offline)
(assoc payload :show? false)
payload)]
{:from current-public-key
:message-id (:message-id command)
:payload payload})
(let [message' (select-keys message [:from :message-id])
payload (select-keys message [:timestamp :content :content-type
:clock-value :show?])
payload (if (= network-status :offline)
(assoc payload :show? false)
payload)]
(assoc message' :payload payload))))
(defn send (defn send
[{{:keys [web3 chats] [{{:keys [web3 chats]
:accounts/keys [accounts current-account-id] :accounts/keys [accounts current-account-id]
:contacts/keys [contacts] :as db} :db :as cofx} :contacts/keys [contacts] :as db} :db :as cofx}
{:keys [chat-id command] :as args}] {:keys [chat-id command message] :as args}]
(let [{:keys [dapp? fcm-token]} (get contacts chat-id)] (let [{:keys [dapp? fcm-token]} (get contacts chat-id)]
(if dapp? (if dapp?
(send-dapp-message! cofx args) (send-dapp-message! cofx args)
(let [{:keys [group-chat public?]} (get-in db [:chats chat-id]) (let [{:keys [group-chat public?]} (get-in db [:chats chat-id])
options {:web3 web3 options {:web3 web3
:message (generate-message db args)}] :message (generate-message db chat-id (or command message))}]
(cond (cond
(and group-chat (not public?)) (and group-chat (not public?))
(let [{:keys [public-key private-key]} (get chats chat-id)] (let [{:keys [public-key private-key]} (get chats chat-id)]
@ -190,16 +173,16 @@
:payload {:title "Status" :body "You have a new message"} :payload {:title "Status" :body "You have a new message"}
:tokens [fcm-token]}}))))))) :tokens [fcm-token]}})))))))
(defn- prepare-message [params chat] (defn- prepare-message [params chat now random-id]
(let [{:keys [chat-id identity message-text]} params (let [{:keys [chat-id identity message-text]} params
{:keys [group-chat public? last-clock-value]} chat {:keys [group-chat public? last-clock-value]} chat
message {:message-id (random/id) message {:message-id random-id
:chat-id chat-id :chat-id chat-id
:content message-text :content message-text
:from identity :from identity
:content-type constants/text-content-type :content-type constants/text-content-type
:outgoing true :outgoing true
:timestamp (datetime-utils/now-ms) :timestamp now
:clock-value (clocks-utils/send last-clock-value) :clock-value (clocks-utils/send last-clock-value)
:show? true}] :show? true}]
(cond-> message (cond-> message
@ -215,21 +198,17 @@
(not group-chat) (not group-chat)
(assoc :to chat-id :message-type :user-message)))) (assoc :to chat-id :message-type :user-message))))
(defn send-message [{{:keys [network-status] :as db} :db (defn send-message [{:keys [db now random-id] :as cofx} {:keys [chat-id] :as params}]
:keys [now]}
{:keys [chat-id] :as params}]
(let [chat (get-in db [:chats chat-id]) (let [chat (get-in db [:chats chat-id])
message (prepare-message params chat) message (prepare-message params chat now random-id)
params' (assoc params :message message) params' (assoc params :message message)
fx {:db (add-message-to-db db chat-id message true) fx (-> (chat-model/upsert-chat cofx {:chat-id chat-id})
:save-message message}] (update :db add-message-to-db chat-id message true)
(-> (merge fx (chat-model/upsert-chat (assoc fx :now now) (assoc :save-message message))]
{:chat-id chat-id})) (merge fx (send cofx params'))))
(as-> fx'
(merge fx' (send fx' params'))))))
(defn- prepare-command (defn- prepare-command
[identity chat-id clock-value [identity chat-id now clock-value
{request-params :params {request-params :params
request-command :command request-command :command
:keys [prefill prefillBotDb] :keys [prefill prefillBotDb]
@ -255,7 +234,7 @@
{:message-id id {:message-id id
:from identity :from identity
:to chat-id :to chat-id
:timestamp (datetime-utils/now-ms) :timestamp now
:content content' :content content'
:content-type (or content-type :content-type (or content-type
(if request (if request
@ -269,8 +248,7 @@
:show? true})) :show? true}))
(defn send-command (defn send-command
[{{:keys [current-public-key network-status chats] :as db} :db [{{:keys [current-public-key chats] :as db} :db :keys [now random-id-seq] :as cofx} add-to-chat-id params]
:keys [now random-id-seq]} result add-to-chat-id params]
(let [{{:keys [handler-data (let [{{:keys [handler-data
command] command]
:as content} :command :as content} :command
@ -280,29 +258,19 @@
hidden-params (->> (:params command) hidden-params (->> (:params command)
(filter :hidden) (filter :hidden)
(map :name)) (map :name))
command' (prepare-command current-public-key chat-id last-clock-value request content) command' (prepare-command current-public-key chat-id now last-clock-value request content)
params' (assoc params :command command') params' (assoc params :command command')
fx (-> (chat-model/upsert-chat cofx {:chat-id chat-id})
fx {:db (-> (merge db (:db result)) (update :db add-message-to-db chat-id command' true)
(add-message-to-db chat-id command' true)) (assoc :save-message (-> command'
:save-message (-> command' (assoc :chat-id chat-id)
(assoc :chat-id chat-id) (update-in [:content :params]
(update-in [:content :params] #(apply dissoc % hidden-params))
#(apply dissoc % hidden-params)) (dissoc :to-message :has-handler :raw-input))))]
(dissoc :to-message :has-handler :raw-input))}] (cond-> (merge fx (send cofx params'))
(cond-> (merge fx
(chat-model/upsert-chat (assoc fx :now now)
{:chat-id chat-id})
(dissoc result :db))
true
(as-> fx'
(merge fx' (send fx' params')))
(:to-message command') (:to-message command')
(assoc :chat-requests/mark-as-answered {:chat-id chat-id (requests-events/request-answered chat-id (:to-message command'))
:message-id (:to-message command')})
(= constants/console-chat-id chat-id) (= constants/console-chat-id chat-id)
(as-> fx' (as-> fx'
@ -313,8 +281,8 @@
(defn invoke-console-command-handler (defn invoke-console-command-handler
[{:keys [db] :as cofx} {:keys [chat-id command] :as command-params}] [{:keys [db] :as cofx} {:keys [chat-id command] :as command-params}]
(let [fx-fn (get console-events/console-commands->fx (-> command :command :name)) (let [fx-fn (get console-events/console-commands->fx (-> command :command :name))
result (fx-fn cofx command)] fx (fx-fn cofx command)]
(send-command cofx result chat-id command-params))) (merge fx (send-command (assoc cofx :db (or (:db fx) db)) chat-id command-params))))
(defn invoke-command-handlers (defn invoke-command-handlers
[{{:keys [bot-db] [{{:keys [bot-db]
@ -347,16 +315,13 @@
(defn process-command (defn process-command
[{:keys [db] :as cofx} {:keys [command message chat-id] :as params}] [{:keys [db] :as cofx} {:keys [command message chat-id] :as params}]
(let [{:keys [command] :as content} command] (let [{:keys [command] :as content} command]
(-> {:db (chat-model/set-chat-ui-props db {:sending-in-progress? false})} (cond
(and (= constants/console-chat-id chat-id)
(console-events/commands-names (:name command)))
(invoke-console-command-handler cofx params)
(as-> fx' (:has-handler command)
(cond (invoke-command-handlers cofx params)
(and (= constants/console-chat-id chat-id)
(console-events/commands-names (:name command)))
(invoke-console-command-handler (merge cofx fx') params)
(:has-handler command) :else
(merge fx' (invoke-command-handlers fx' params)) (send-command cofx chat-id params))))
:else
(merge fx' (send-command cofx fx' chat-id params)))))))

View File

@ -65,11 +65,7 @@
(defview message-content-command (defview message-content-command
[{:keys [content params] :as message}] [{:keys [content params] :as message}]
(letsubs [command [:get-command (:content-command-ref content)]] (letsubs [command [:get-command (:content-command-ref content)]]
{:component-will-mount #(when-not (:preview content)
(re-frame/dispatch [:request-command-message-data
message {:data-type :preview
:cache-data? true}]))}
(let [preview (:preview content) (let [preview (:preview content)
{:keys [type color] icon-path :icon} command] {:keys [type color] icon-path :icon} command]
[react/view style/content-command-view [react/view style/content-command-view

View File

@ -77,11 +77,7 @@
[{:keys [message-id content] :as message}] [{:keys [message-id content] :as message}]
(letsubs [command [:get-command (:content-command-ref content)] (letsubs [command [:get-command (:content-command-ref content)]
answered? [:is-request-answered? message-id] answered? [:is-request-answered? message-id]
status-initialized? [:get :status-module-initialized?]] status-initialized? [:get :status-module-initialized?]]
{:component-will-mount #(when-not (:preview content)
(dispatch [:request-command-message-data
message {:data-type :preview
:cache-data? true}]))}
(let [{:keys [prefill prefill-bot-db prefillBotDb params preview] (let [{:keys [prefill prefill-bot-db prefillBotDb params preview]
text-content :text} content text-content :text} content
command (if (and params command) command (if (and params command)