diff --git a/examples/whatsapp_counter.clj b/examples/whatsapp_counter.clj new file mode 100644 index 00000000..e48a1ef7 --- /dev/null +++ b/examples/whatsapp_counter.clj @@ -0,0 +1,64 @@ +;; USAGE: in whatsapp group chat, export your chat _without_ media, and store somewhere. +;; Then +;; $> cat chatfile.txt | bb -i -f whatsapp_counter.clj + +(require '[clojure.string :refer [lower-case includes? trim ] :as string]) + +(defn parse-line + "Returns the name of the message, or nil if it can't be found" + [l] + (->> (string/replace l #"\p{C}" "") + trim + (re-find #"\[.{19}\].(.+?):") + second)) + +(defn print-table + "NOTE: this is a verbatim copy from + https://github.com/clojure/clojure/blob/93d13d0c0671130b329863570080c72799563ac7/src/clj/clojure/pprint/print_table.clj#L11 + Prints a collection of maps in a textual table. Prints table headings + ks, and then a line of output for each row, corresponding to the keys + in ks. If ks are not specified, use the keys of the first item in rows." + ([ks rows] + (when (seq rows) + (let [widths (map + (fn [k] + (apply max (count (str k)) (map #(count (str (get % k))) rows))) + ks) + spacers (map #(apply str (repeat % "-")) widths) + fmts (map #(str "%" % "s") widths) + fmt-row (fn [leader divider trailer row] + (str leader + (apply str (interpose divider + (for [[col fmt] (map vector (map #(get row %) ks) fmts)] + (format fmt (str col))))) + trailer))] + (println) + (println (fmt-row "| " " | " " |" (zipmap ks ks))) + (println (fmt-row "|-" "-+-" "-|" (zipmap ks spacers))) + (doseq [row rows] + (println (fmt-row "| " " | " " |" row)))))) + ([rows] (print-table (keys (first rows)) rows))) + +(defn chats-by-user + ([lines] + (chats-by-user lines parse-line)) + ([lines filter-fn] + (let [ histogram (reduce + (fn [acc l] + (if-let [n (filter-fn l)] + (update acc n (fnil inc 0)) + ;;else ignore + acc)) + {} + lines)] + (->> histogram + (sort-by second) + reverse + (map (fn [[name amount]] + {:name name + :amount amount})) + print-table)))) + +(chats-by-user *input*) + +(System/exit 0)