devth/yetibot

View on GitHub
src/yetibot/commands/emoji.clj

Summary

Maintainability
Test Coverage
(ns yetibot.commands.emoji
  (:require
    [taoensso.timbre :refer [info warn error]]
    [yetibot.core.hooks :refer [cmd-hook]]
    [clojure.core.memoize :as m])
  (:import
   [com.vdurmont.emoji EmojiManager]))

(defn get-all-emojis
  "get all emoji java objects"
  []
  (EmojiManager/getAll))

(defn parse-all-emojis
  "create sequence of emojis"
  []
  (map (fn [emoji] {:unicode (.getUnicode emoji)
                    :description (.getDescription emoji)
                    :aliases (into [] (.getAliases emoji))
                    :tags (into [] (.getTags emoji))
                    }) (get-all-emojis)))

(defonce emojis (parse-all-emojis))

(defn all-tags
  "emoji tags # return all known tags"
  {:yb/cat #{:fun :img :emoji}}
  [_]
  (-> (reduce (fn [return-set emoji]
                (let [tag-vector (:tags emoji)
                      tag-hash-set (set tag-vector)]
                  (clojure.set/union return-set tag-hash-set)))
              #{}
              emojis)
      sort))

(defn list-emojis
  "emoji list [-i] # list all known emojis

   [-i (info)] is optional, if set will return the unicode
   as well as a vector of its aliases"
  {:yb/cat #{:fun :img :emoji}}
  [{[_ info-flag] :match}]
  (let [emoji-keys (filter identity [:unicode (if info-flag :aliases)])
        select-values (comp vals select-keys)
        map-fn (fn [emoji]
                    (clojure.string/join " " (select-values emoji emoji-keys)))]
    (map map-fn emojis)))

(defn filter-by-tag
  "filter emojis by tag"
  [tag]
  (filter (fn [emoji] (some #{tag} (:tags emoji))) emojis))

(defn filter-by-description
  "filter emojis by description"
  [description]
  (if-let [sanitized-desc (if (or (empty? description)
                                  (coll? description))
                            nil
                            (str description))]
    (filter (fn [emoji]
              (re-find (re-pattern sanitized-desc)
                       (:description emoji)))
            emojis)
    '()))

(defn filter-by-alias
  "filter emojis by alias"
  [alias]
  (if-let [sanitized-alias (if (coll? alias)
                             nil
                             (str alias))]
    (filter (fn [emoji]
              (->
               (filter (fn [aliases]
                         (re-find (re-pattern
                                   (str "^" sanitized-alias "$"))
                                  aliases))
                       (:aliases emoji))
               empty?
               not))
            emojis)
    '()))

(defn search-by-tag
  "emoji tag <query> # query emojis by their tag

   [-i (info)] is optional, if set will return the unicode
   as well as a vector of its aliases"
  {:yb/cat #{:fun :img :emoji}}
  ([{[_ info-flag tag] :match}]
   (if-let [found-emojis (filter-by-tag tag)]
     (let [emoji-keys (filter identity [:unicode (if info-flag :aliases)])
           select-values (comp vals select-keys) 
           map-fn (fn [emoji]
                    (clojure.string/join " " (select-values emoji emoji-keys)))]
       (map map-fn found-emojis))
     (str "Couldn't find any emojis with: \"" tag "\" tag"))))

(defn search
  "emoji search [-i] <query> # search emojis by their description

   [-i (info)] is optional, if set will return the unicode
   as well as a vector of its aliases"
  {:yb/cat #{:fun :img :emoji}}
  ([{[_ info-flag description] :match}]
   (if-let [found-emojis (filter-by-description description)]
     (let [emoji-keys (filter identity [:unicode (if info-flag :aliases)])
           select-values (comp vals select-keys)
           map-fn (fn [emoji]
                    (clojure.string/join " " (select-values emoji emoji-keys)))]
       (map map-fn found-emojis))
     (str "Couldn't find any emojis with: \"" description "\" description"))))

(defn search-by-alias
  "emoji alias <query> # query an emoji by its alias (meant to return 1 emoji)"
  {:yb/cat #{:fun :img :emoji}}
  ([{[_ alias] :match}]
   (if-let [found-emoji (first (filter-by-alias alias))]
     [(:unicode found-emoji)]
     (str "Couldn't find any emojis with: \"" alias "\" alias"))))

(defn find-by-slack-emoji
  "Take an emoji in the Slack format, e.g.
  :smile: and return the emoji object"
  [slack-emoji]
  (let [emoji-name (re-find #":(.+):" slack-emoji)]
    (filter-by-alias (last emoji-name))))

(comment
  (find-by-slack-emoji ":smile:")
  (drop-first ":smile")

  (filter-by-alias ":smile:")

  (all-tags nil)
  )

(cmd-hook ["emoji" #"^emoji$"]
          #"^tags$" all-tags
          #"^list(\s-i)?$" list-emojis
          #"^tag\s(-i\s)?(.+)$" search-by-tag
          #"^search\s(-i\s)?(.+)$" search
          #"^alias\s(.+)$" search-by-alias)