status-react/src/status_im/data_store/messages.cljs

122 lines
4.3 KiB
Plaintext
Raw Normal View History

(ns status-im.data-store.messages
2017-10-19 13:58:21 +00:00
(:require [cljs.reader :as reader]
[re-frame.core :as re-frame]
2017-10-19 13:58:21 +00:00
[status-im.constants :as constants]
[status-im.data-store.realm.core :as core]
2018-05-02 16:44:58 +00:00
[status-im.utils.core :as utils]))
(defn- command-type?
[type]
(contains?
2017-12-05 13:03:25 +00:00
#{constants/content-type-command constants/content-type-command-request}
type))
2018-05-02 16:44:58 +00:00
(defn- transform-message [{:keys [content-type] :as message}]
(cond-> (update message :message-type keyword)
2018-05-02 16:44:58 +00:00
(command-type? content-type)
(update :content reader/read-string)))
2018-05-02 16:44:58 +00:00
(defn- get-by-chat-id
([chat-id]
(get-by-chat-id chat-id 0))
([chat-id from]
2018-05-02 16:44:58 +00:00
(let [messages (-> (core/get-by-field @core/account-realm :message :chat-id chat-id)
(core/sorted :timestamp :desc)
(core/page from (+ from constants/default-number-of-messages))
(core/all-clj :message))]
(map transform-message messages))))
;; TODO janherich: define as cofx once debug handlers are refactored
(defn get-log-messages
[chat-id]
(->> (get-by-chat-id chat-id 0)
(filter #(= (:content-type %) constants/content-type-log-message))
(map #(select-keys % [:content :timestamp]))))
(def default-values
[fixes #4745] Don't query mailserver on restored account When creating a new account / recovery we don't poll the mailserver anymore for historic messages, which solves the immediate issue of fetching only received messages Handle messages sent from a different device in public chat / restore history. The message will be added, shown correctly as sent by the user, and the status will be set as sent ( need to check for seen race condition, as messages will now be added twice). This means that multidevice should now work for public chats. Move contact updates to discovery topic. This is necessary as there is a pre-existing bug whereby contact updates would not work anymore after wallet recovery, as the code relies on the initial contact request being stored on the mailserver, which we cannot guarantee (we only pull 7 days of data). Not pulling history anymore exacerbate the problems but does not introduce it. To make sure that contact updates will work after wallet recovery, we also need to consider a ContactUpdate in the same way we consider a ContactRequest (the other peer has no idea that the user has recovered the wallet). This does not change any behaviour in terms of obscurity/security as ContactRequest are automatically processed (in both case the contact will be set as pending?, not as accepted) At this stage ContactRequest, ContactRequestConfirmed, ContactUpdate have all the same logic, i.e. update the contact information, leave the pending flag alone. Only 1 day of history is fetched for newly joined chats, if catching up 7 days is the cap as before. Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
2018-06-19 11:43:47 +00:00
{:to nil})
(re-frame/reg-cofx
:data-store/get-messages
(fn [cofx _]
(assoc cofx :get-stored-messages get-by-chat-id)))
(re-frame/reg-cofx
:data-store/message-ids
(fn [cofx _]
2018-05-02 16:44:58 +00:00
(assoc cofx :stored-message-ids (let [chat-id->message-id (volatile! {})]
(-> @core/account-realm
(.objects "message")
(.map (fn [msg _ _]
(vswap! chat-id->message-id
#(update %
(aget msg "chat-id")
(fnil conj #{})
(aget msg "message-id"))))))
@chat-id->message-id))))
(defn- get-unviewed-messages
[public-key]
(into {}
(map (fn [[chat-id user-statuses]]
[chat-id (into #{} (map :message-id) user-statuses)]))
(group-by :chat-id
(-> @core/account-realm
(core/get-by-fields
:user-status
:and {:whisper-identity public-key
:status "received"})
(core/all-clj :user-status)))))
(re-frame/reg-cofx
:data-store/get-unviewed-messages
(fn [cofx _]
(assoc cofx
:get-stored-unviewed-messages
get-unviewed-messages)))
(defn- prepare-content [content]
2017-12-05 13:03:25 +00:00
(if (string? content)
content
(pr-str
;; TODO janherich: this is ugly and not systematic, define something like `:not-persisent`
2017-12-23 20:27:04 +00:00
;; option for command params instead
2017-12-05 13:03:25 +00:00
(update content :params dissoc :password :password-confirmation))))
2017-12-23 20:27:04 +00:00
(defn- prepare-message [message]
(utils/update-if-present message :content prepare-content))
2017-12-23 20:27:04 +00:00
2018-05-02 16:44:58 +00:00
(defn save-message-tx
"Returns tx function for saving message"
[{:keys [message-id from] :as message}]
(fn [realm]
(core/create realm
:message
(prepare-message (merge default-values
message
{:from (or from "anonymous")}))
true)))
2018-05-02 16:44:58 +00:00
(defn delete-message-tx
"Returns tx function for deleting message"
[message-id]
2018-05-02 16:44:58 +00:00
(fn [realm]
(when-let [message (core/get-by-field realm :message :message-id message-id)]
(core/delete realm message)
(core/delete realm (core/get-by-field realm :user-status :message-id message-id)))))
2018-05-02 16:44:58 +00:00
(defn delete-messages-tx
"Returns tx function for deleting messages with user statuses for given chat-id"
[chat-id]
(fn [realm]
(core/delete realm (core/get-by-field realm :message :chat-id chat-id))
(core/delete realm (core/get-by-field realm :user-status :chat-id chat-id))))
(defn hide-messages-tx
"Returns tx function for hiding messages for given chat-id"
[chat-id]
(fn [realm]
(.map (core/get-by-field realm :message :chat-id chat-id)
(fn [msg _ _]
(aset msg "show?" false)))))