<commit_before>(ns chat.server.email-digest
  (:require [clojurewerkz.quartzite
             [triggers :as t]
             [jobs :as j :refer [defjob]]
             [scheduler :as qs]]
            [clojurewerkz.quartzite.schedule.cron :as cron]
            [clj-time
             [core :as time]
             [coerce :refer [to-date-time]]]
            [environ.core :refer [env]]
            [clostache.parser :refer [render-resource]]
            [inliner.core :refer [inline-css]]
            [org.httpkit.client :as http]
            [taoensso.timbre :as timbre]
            [chat.server.db :as db]))

; finding data

(defn thread-unseen?
  "A thread is unseen if it's last-open-at is prior to any of the messages' created-at"
  [thread]
  (let [last-open (to-date-time (thread :last-open-at))]
    (some (fn [{:keys [created-at]}]
            (time/before? last-open (to-date-time created-at)))
          (thread :messages))))

(defn last-message-after?
  [cutoff thread]
  (some (fn [{:keys [created-at]}]
          (time/after? (to-date-time created-at) cutoff))
        (thread :messages)))

(defn updates-for-user-since
  [user-id cutoff]
  (into ()
        (comp (filter thread-unseen?)
              (filter (partial last-message-after? cutoff)))
        (db/with-conn
          (db/get-open-threads-for-user user-id))))

(defn daily-update-users
  "Find all ids for users that want daily digest updates"
  []
  (db/user-search-preferences :email-frequency :daily))

(defn weekly-update-users
  "Find all ids for users that want weekly digest updates"
  []
  (db/user-search-preferences :email-frequency :weekly))<commit_msg>pre-compute nickname->user<commit_after>(ns chat.server.email-digest
  (:require [clojurewerkz.quartzite
             [triggers :as t]
             [jobs :as j :refer [defjob]]
             [scheduler :as qs]]
            [clojurewerkz.quartzite.schedule.cron :as cron]
            [clj-time
             [core :as time]
             [coerce :refer [to-date-time]]]
            [environ.core :refer [env]]
            [clostache.parser :refer [render-resource]]
            [inliner.core :refer [inline-css]]
            [org.httpkit.client :as http]
            [taoensso.timbre :as timbre]
            [chat.server.db :as db]))

; finding data

(defn thread-unseen?
  "A thread is unseen if it's last-open-at is prior to any of the messages' created-at"
  [thread]
  (let [last-open (to-date-time (thread :last-open-at))]
    (some (fn [{:keys [created-at]}]
            (time/before? last-open (to-date-time created-at)))
          (thread :messages))))

(defn last-message-after?
  [cutoff thread]
  (some (fn [{:keys [created-at]}]
          (time/after? (to-date-time created-at) cutoff))
        (thread :messages)))

(defn updates-for-user-since
  [user-id cutoff]
  (db/with-conn
    (let [id->nick (into {} (map (juxt :id :nickname))
                         (db/fetch-users-for-user user-id))]
      (into ()
            (comp (filter thread-unseen?)
                  (filter (partial last-message-after? cutoff))
                  (map (fn [t]
                         (map (fn [m]
                                (assoc m :sender (-> (m :user-id) id->nick)))
                              (t :messages)))))
            (db/get-open-threads-for-user user-id)))))

(defn daily-update-users
  "Find all ids for users that want daily digest updates"
  []
  (db/user-search-preferences :email-frequency :daily))

(defn weekly-update-users
  "Find all ids for users that want weekly digest updates"
  []
  (db/user-search-preferences :email-frequency :weekly))
{'fraction_non_alphanumeric': 0.1437291897891232, 'fraction_numerical': 0.0, 'mean_word_length': 2.118512110726644, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4916894', 'n_tokens_mistral': 1193, 'n_tokens_neox': 1174, 'n_words': 297}