diff --git a/doc/examples.md b/doc/examples.md index 3f193c3a..a42ece92 100644 --- a/doc/examples.md +++ b/doc/examples.md @@ -267,3 +267,8 @@ $ examples/which.clj rg A script to retrieve the version from a `pom.xml` file. See [examples/pom_version.clj](examples/pom_version.clj). Written by [@wilkerlucio](https://github.com/wilkerlucio). + +### Whatsapp frequencies + +Show frequencies of messages by user in Whatsapp group chats. +See [examples/whatsapp_frequencies.clj](examples/whatsapp_frequencies.clj) diff --git a/examples/whatsapp_counter.clj b/examples/whatsapp_counter.clj deleted file mode 100644 index e48a1ef7..00000000 --- a/examples/whatsapp_counter.clj +++ /dev/null @@ -1,64 +0,0 @@ -;; 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) diff --git a/examples/whatsapp_frequencies.clj b/examples/whatsapp_frequencies.clj new file mode 100644 index 00000000..bb108db3 --- /dev/null +++ b/examples/whatsapp_frequencies.clj @@ -0,0 +1,30 @@ +;; USAGE: in whatsapp group chat, export your chat _without_ media, and store somewhere. +;; Then +;; $ cat chatfile.txt | bb -i -f whatsapp_counter.clj + +(ns whatsapp-frequencies + {:author "Marten Sytema"} + (:require [clojure.java.io :as io] + [clojure.pprint :refer [print-table]] + [clojure.string :refer [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 #"\[.*\] (.+?):") + second)) + +(defn chats-by-user + ([lines] + (chats-by-user lines parse-line)) + ([lines keep-fn] + (->> (frequencies (keep keep-fn lines)) + (sort-by second >) + (map (fn [[name amount]] + {:name name + :amount amount})) + (print-table [:name :amount])))) + +(chats-by-user (line-seq (io/reader *in*)))