<commit_before>(ns braid.client.state.handlers
  (:require [clojure.string :as string]
            [braid.client.store :as store]
            [braid.client.sync :as sync]
            [braid.client.schema :as schema]
            [braid.common.util :as util]
            [braid.client.router :as router]
            [braid.client.xhr :refer [edn-xhr]]
            [braid.client.state.helpers :as helpers]
            [braid.client.dispatcher :refer [dispatch!]]
            [braid.client.state.handler :refer [handler]]))

(defn extract-tag-ids
  [text]
  (let [mentioned-names (->> (re-seq util/sigiled-tag-name-re text)
                             (map second))]
    (->> mentioned-names
         (map store/name->open-tag-id)
         (remove nil?))))

(defn extract-user-ids
  [text]
  (let [mentioned-names (->> (re-seq util/sigiled-nickname-re text)
                             (map second))
        nick->id (reduce (fn [m {:keys [id nickname]}] (assoc m nickname id))
                         {}
                         (store/all-users))]
    (->> mentioned-names
         (map nick->id)
         (filter store/user-in-open-group?)
         (remove nil?))))

(defn identify-mentions
  [content]
  (-> content
      (string/replace util/sigiled-nickname-re
                      (fn [[m nick]]
                        ; sometimes need leading whitespace, because javascript regex doesn't have lookbehind
                        (str (second (re-matches #"^(\s).*" m))
                             "@"
                             (if-let [user-id (:id (store/nickname->user nick))]
                                   (if (store/user-in-open-group? user-id)
                                     user-id
                                     nick)
                                   nick))))
      (string/replace util/sigiled-tag-name-re
                      (fn [[m tag-name]]
                        ; sometimes need leading whitespace, because javascript regex doesn't have lookbehind
                        (str (second (re-matches #"^(\s).*" m))
                             "#" (or (store/name->open-tag-id tag-name)
                                      tag-name))))))

(defmethod handler :clear-session [state _]
  (helpers/clear-session state))

(defmethod handler :new-message-text [state [_ {:keys [thread-id content]}]]
  (helpers/set-new-message state thread-id content))

(defmethod handler :display-error [state [_ args]]
  (apply helpers/display-error state args))

(defmethod handler :set-message-failed [state [_ message]]
  (helpers/set-message-failed! state message))

(defmethod handler :new-message [state [_ data]]
  (when-not (string/blank? (data :content))
    (let [message (schema/make-message
                    {:user-id (helpers/current-user-id state)
                     :content (identify-mentions (data :content))
                     :thread-id (data :thread-id)
                     :group-id (data :group-id)
                     :mentioned-tag-ids (concat (data :mentioned-tag-ids)
                                                (extract-tag-ids (data :content)))
                     :mentioned-user-ids (concat (data :mentioned-user-ids)
                                                 (extract-user-ids (data :content)))})]
      (sync/chsk-send!
        [:braid.server/new-message message]
        2000
        (fn [reply]
          (when (not= :braid/ok reply)
            (dispatch! :display-error [(str :failed-to-send (message :id)) "Message failed to send!"])
            (dispatch! :set-message-failed message))))
      (-> state
          (helpers/add-message message)
          (helpers/maybe-reset-new-thread-id (data :thread-id))))))

(defmethod handler :clear-error [state [_ err-key]]
  (helpers/clear-error state err-key))

(defmethod handler :resend-message [state [_ message]]
  (-> state
      (helpers/clear-error (str :failed-to-send (message :id)))
      (helpers/clear-message-failed message))
  (sync/chsk-send!
    [:braid.server/new-message message]<commit_msg>Fix handler not returning state in certain situations<commit_after>(ns braid.client.state.handlers
  (:require [clojure.string :as string]
            [braid.client.store :as store]
            [braid.client.sync :as sync]
            [braid.client.schema :as schema]
            [braid.common.util :as util]
            [braid.client.router :as router]
            [braid.client.xhr :refer [edn-xhr]]
            [braid.client.state.helpers :as helpers]
            [braid.client.dispatcher :refer [dispatch!]]
            [braid.client.state.handler :refer [handler]]))

(defn extract-tag-ids
  [text]
  (let [mentioned-names (->> (re-seq util/sigiled-tag-name-re text)
                             (map second))]
    (->> mentioned-names
         (map store/name->open-tag-id)
         (remove nil?))))

(defn extract-user-ids
  [text]
  (let [mentioned-names (->> (re-seq util/sigiled-nickname-re text)
                             (map second))
        nick->id (reduce (fn [m {:keys [id nickname]}] (assoc m nickname id))
                         {}
                         (store/all-users))]
    (->> mentioned-names
         (map nick->id)
         (filter store/user-in-open-group?)
         (remove nil?))))

(defn identify-mentions
  [content]
  (-> content
      (string/replace util/sigiled-nickname-re
                      (fn [[m nick]]
                        ; sometimes need leading whitespace, because javascript regex doesn't have lookbehind
                        (str (second (re-matches #"^(\s).*" m))
                             "@"
                             (if-let [user-id (:id (store/nickname->user nick))]
                                   (if (store/user-in-open-group? user-id)
                                     user-id
                                     nick)
                                   nick))))
      (string/replace util/sigiled-tag-name-re
                      (fn [[m tag-name]]
                        ; sometimes need leading whitespace, because javascript regex doesn't have lookbehind
                        (str (second (re-matches #"^(\s).*" m))
                             "#" (or (store/name->open-tag-id tag-name)
                                      tag-name))))))

(defmethod handler :clear-session [state _]
  (helpers/clear-session state))

(defmethod handler :new-message-text [state [_ {:keys [thread-id content]}]]
  (helpers/set-new-message state thread-id content))

(defmethod handler :display-error [state [_ args]]
  (apply helpers/display-error state args))

(defmethod handler :set-message-failed [state [_ message]]
  (helpers/set-message-failed! state message))

(defmethod handler :new-message [state [_ data]]
  (if-not (string/blank? (data :content))
    (let [message (schema/make-message
                    {:user-id (helpers/current-user-id state)
                     :content (identify-mentions (data :content))
                     :thread-id (data :thread-id)
                     :group-id (data :group-id)
                     :mentioned-tag-ids (concat (data :mentioned-tag-ids)
                                                (extract-tag-ids (data :content)))
                     :mentioned-user-ids (concat (data :mentioned-user-ids)
                                                 (extract-user-ids (data :content)))})]
      (sync/chsk-send!
        [:braid.server/new-message message]
        2000
        (fn [reply]
          (when (not= :braid/ok reply)
            (dispatch! :display-error [(str :failed-to-send (message :id)) "Message failed to send!"])
            (dispatch! :set-message-failed message))))
      (-> state
          (helpers/add-message message)
          (helpers/maybe-reset-new-thread-id (data :thread-id))))
    state))

(defmethod handler :clear-error [state [_ err-key]]
  (helpers/clear-error state err-key))

(defmethod handler :resend-message [state [_ message]]
  (-> state
      (helpers/clear-error (str :failed-to-send (message :id)))
      (helpers/clear-message-failed message))
  (sync/chsk-send!
    [:braid.server/new-message message]
{'fraction_non_alphanumeric': 0.13638601674052192, 'fraction_numerical': 0.0009847365829640572, 'mean_word_length': 1.6526281423441072, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2960626', 'n_tokens_mistral': 2354, 'n_tokens_neox': 2275, 'n_words': 531}