Source

messageme-clj / src / messageme / core.clj

(ns messageme.core)

(def message-box (agent ()))

(def connected-users (agent []))

(defn do-connect-user [user]
  (send-off connected-users (fn [connected-users]
                              (conj connected-users user))))

(defn do-insert-message [message]
  (send-off message-box (fn [box]
                          (conj box message))))

(defn do-notify-recipient [msg]
  (send-off connected-users
            (fn [users]
              (if (some #{(:recipient msg)} users)
                (println " ** Notification:" (:recipient msg)
                         "has a new message from" (:sender msg))) users)))

(defn mark-inbox-read
  "Takes a message box and a user ands the message box with the user's messages
  marked read."
  [box user]
  (let [other-msgs (remove #(= (% :recipent) user) box)
        user-inbox (filter #(= (% :recipient) user) box)]
    (concat other-msgs (map
                         #({:sender (:sender %), :recipient (:recipient %),
                            :body (:body %), :read true}) user-inbox))))

(defn inbox-data [user]
  (send-off message-box mark-inbox-read)
  (filter (fn [msg] (= (:recipient msg) user)) @message-box))

(defn send-message [sender recipient body]
  (let [msg {:sender sender, :recipient recipient, :body body :read false}]
    (do-insert-message msg)
    (do-notify-recipient msg)))

(defn display-msg [msg]
  (println (str "  From: " (:sender msg) " | Message: " (:body msg))))

(defn display-inbox [user msgs]
  (println (str "Inbox for " user " contains " (count msgs) " messages:"))
  (loop [[msg & remaining] msgs]
    (if msg
      (do (display-msg msg) (recur remaining))
      (println))))

(defn do-display-unread [usr]
  (let [unread (filter #(% :read) (inbox-data usr))]
    (println (count unread) "messages arrived since you last connected:")
    (loop [[msg & remaining] unread]
      (if msg
        (do (display-msg msg) (recur remaining))
        (println)))))

(defn connect [arg-str]
  (do-display-unread arg-str)
  (do-connect-user arg-str))

(defn send [arg-str]
  (let [[sender recipient body] (seq (.split arg-str " " 3))
        stripped-body (.replace body "'" "")]
    (send-message sender recipient stripped-body)))

(defn inbox [arg-str]
  (display-inbox arg-str (inbox-data arg-str)))

(defn exit []
  (java.lang.System/exit 0))