Skip to content

Instantly share code, notes, and snippets.

@jethrokuan
Created April 18, 2016 01:39
Show Gist options
  • Save jethrokuan/4f7553644ec90eb1fbd78795cf1b8700 to your computer and use it in GitHub Desktop.
Save jethrokuan/4f7553644ec90eb1fbd78795cf1b8700 to your computer and use it in GitHub Desktop.
(ns ttagenda.api
(:require [ttagenda.db :as db]
[ttagenda.util :refer :all]
[ttagenda.keytable :as kt]
[ttagenda.shouter :as s]
[ttagenda.print :as p]
[clojure.string :as st]
[ring.util.response :refer [response]]))
(def FAILURE_TEXT "We couldn't process your request at this time, please try again later")
(def COMMANDS {:list #{"list" "l" "show"}
:arrow #{"assign" "arrow"}
:add #{"add" "a"}
:delete #{"delete" "d"}
:restore #{"restore" "r"}
:toggle #{"toggle" "t"}
:clear #{"clear" "c"}
:confirm #{"confirm"}
:help #{"help" "h"}
:me #{"me"}})
(defn process-cmd-dispatch [params]
(reduce-kv (fn [_ k v]
(when (v (:cmd params))
(reduced k))) [] COMMANDS))
(defmulti process-cmd process-cmd-dispatch)
(defmethod process-cmd :list [{:keys [team_id channel_id cmd_params channel_name] :as params}]
(let [tag (st/trim cmd_params)]
(if (is-tag? tag)
(if-let [todos (db/list-todo-by-tag {:team_id team_id :tag tag})]
(s/whisper (p/print todos {:pretext (format "Todos tagged with %s:\n" tag) :show-tags? true :show-id? false}))
(response FAILURE_TEXT))
(if-let [todos (db/list-todo {:channel channel_id})]
(s/whisper (p/print todos {:pretext (format "#%s:\n" channel_name) :show-tags? true}))
(response FAILURE_TEXT)))))
(defmethod process-cmd :add [{:keys [cmd_params channel_id user_name team_id] :as params}]
(let [text-tag-map (-> cmd_params
st/trim
cmd-params->text-tags)]
(cond
(not (:text text-tag-map)) (response (format "%s is not valid syntax." cmd_params))
(st/blank? (:text text-tag-map)) (response "Your item cannot be blank. Please try again.")
:else (if-let [todo (db/insert-todo {:todo (:text text-tag-map)
:channel channel_id
:owner (str "@" user_name)
:team_id team_id})]
(if (:tags text-tag-map)
(let [id (:id todo)
tagarr (reduce #(conj % [id %2]) [] (:tags text-tag-map))]
(if-let [inserted-tags (db/insert-tags {:tags tagarr})]
(s/shout {:pretext "New item added:"
:author_name (:owner todo)
:fallback (:todo todo)
:fields [{:title "Todo" :value (:todo todo) :short true}
{:title "Tags" :value (tags->str inserted-tags) :short true}]})
(response FAILURE_TEXT)))
(s/shout {:pretext "New item added:"
:author_name (:owner todo)
:fallback (:todo todo)
:text (:todo todo)}))))))
(defmethod process-cmd :delete [{:keys [cmd_params channel_id response_url team_id user_name] :as params}]
(if-let [[[_ id? num]] (re-seq #"(^#)?([0-9]+)$" (st/trim cmd_params))]
(if id?
(if-let [todo (db/delete-todo-with-tag {:id (Integer. num)
:team_id team_id
:tag (str "@" user_name)})] ;;delete by id
(s/shout {:pretext (format "Todo successfully deleted. To restore, type: *%s*" (str "/aa restore #" (:id todo)))
:fallback (:todo todo)
:author_name (:owner todo)
:text (:todo todo)
:color "#FF0000"})
(response (format "There is no todo of id %s that can be deleted." num)))
(let [d_id (Integer. cmd_params) ;; Delete by display id
id (dec d_id)
todos (db/list-todo {:channel channel_id})]
(if-let [todel (nth todos id nil)]
(when-let [todo (db/delete-todo {:id (:id todel)
:team_id team_id})]
(s/shout {:pretext (format "Todo successfully deleted. To restore, type: *%s*" (str "/aa restore #" (:id todo)))
:fallback (:todo todo)
:author_name (:owner todo)
:text (:todo todo)
:color "#FF0000"}))
(response (format "There is no todo at index %d." d_id)))))
(response (format "%s is not valid syntax." cmd_params))))
(defmethod process-cmd :restore [{:keys [cmd_params channel_id team_id] :as params}]
(let [[[_ i]] (re-seq #"^#(\d+)$" (st/trim cmd_params))]
(if-let [id (Integer. i)]
(if-let [todo (db/restore-todo {:id id
:team_id team_id})]
(s/shout {:pretext "Todo successfully restored!"
:fallback (:todo todo)
:author_name (:owner todo)
:text (:todo todo)
:color "#7CD197"})
(response "There is no todo with this id that can be restored."))
(response (format "%s is not valid syntax." cmd_params)))))
(defmethod process-cmd :toggle [{:keys [user_name cmd_params channel_id team_id] :as params}]
(if-let [[[_ id? num]] (re-seq #"(^#)?([0-9]+)$" (st/trim cmd_params))]
(if id?
(if-let [todo (db/toggle-todo-with-tag {:id (Integer. num)
:team_id team_id
:tag user_name})] ;;toggle by id
(s/shout {:pretext (format "Todo successfully marked %s" (if (:completed todo) "complete" "incomplete"))
:fallback (:todo todo)
:author_name (:owner todo)
:text (:todo todo)})
(response (format "There is no todo of id %s that you can toggle." num)))
(let [todos (db/list-todo {:channel channel_id})]
(if-let [totoggle (nth todos (dec (Integer. cmd_params)) false)]
(if-let [todo (db/toggle-todo {:id (:id totoggle)
:team_id team_id})]
(response (format "\"%s\" has been marked %s!"
(:todo todo)
(if (:completed todo)
"completed"
"incomplete"))))
(s/whisper {:text "Your todo list have fewer items than your selected index."}))))
(response (format "%s is not valid syntax." cmd_params))))
(defmethod process-cmd :clear [{:keys [cmd_params channel_id user_name channel_name] :as params}]
(condp = cmd_params
"all" (let [todos (db/list-todo {:channel channel_id})]
(if (= 0 (count todos))
(s/whisper {:text "There's nothing to clear."})
(if-let [keytable (kt/create-keytable channel_id true)]
(s/shout (p/print todos {:pretext (format ":warning: Danger! About to clear the following todos in #%s. To confirm, type: */aaa confirm %s*" channel_name (:kw keytable))
:show-id? false
:show-tags? true
:color "#F9D423"}))
(s/whisper {:text "An error occured. Please try again later."}))))
"completed" (let [todos (db/list-completed-todo {:channel channel_id})]
(if (= 0 (count todos))
(s/whisper {:text "There's nothing to clear."})
(if-let [keytable (kt/create-keytable channel_id false)]
(s/shout (p/print todos {:pretext (format ":warning: Danger! About to clear the following todos in #%s. To confirm, type: */aaa confirm %s*" channel_name (:kw keytable))
:show-id? false
:show-tags? true
:color "#F9D423"}))
(s/whisper {:text "An error occured. Please try again later."}))))
"" (response "please indicate an option: *add* or *completed*")
(response (format "*%s* is not a valid option. Accepted options: all, completed" cmd_params))))
(defmethod process-cmd :confirm [{:keys [user_name team_id cmd_params] :as params}]
(if-let [keytable (db/delete-keytable {:kw cmd_params})]
(if (:clear_scope keytable)
(if-let [cleared (db/clear-todo {:channel_id (:item keytable)})]
(s/shout (p/print cleared {:pretext "The following todos have been cleared:\n" :show-id? false :show-tags? false}))
(s/whisper {:text "No todos to clear."}))
(if-let [cleared (db/clear-completed-todo {:channel_id (:item keytable)})]
(s/shout (p/print cleared {:pretext "The following todos have been cleared:\n" :show-id? false :show-tags? false}))
(s/whisper {:text "No todos to clear."})))
(s/whisper {:pretext ":warning: Error!" :text (format "No table found with key \"*%s*\". Please double check your key." cmd_params)})))
(defmethod process-cmd :me [{:keys [user_name team_id] :as params}]
(let [todos (db/list-user-todo {:user_name (str "@" user_name) :team_id team_id})]
(s/whisper (p/print todos {:pretext "My todos:\n" :show-id? true :show-tags? false}))))
(defmethod process-cmd :arrow [{:keys [user_name cmd_params channel_id team_id] :as params}]
(if-let [[[_ id? num tags_arr]] (re-seq #"(^#)?([0-9+])\s([\@\w+\s?]+)" (st/trim cmd_params))]
(if id?
(response "Assigning todos by id is not supported.")
(let [todos (db/list-todo {:channel channel_id})]
(if-let [todo (nth todos (dec (Integer. num)) false)]
(let [tags (st/split tags_arr #" ")
id (:id todo)
tag-tuple (reduce (fn [v s] (into v [[id s]])) [] tags)]
(if-let [inserted-tags (db/insert-tags {:tags tag-tuple})]
(response (format "The tags %s have been inserted successfully!" (tags->str inserted-tags)))
(response "Something went wrong. Please try again later.")))
(s/whisper { :text "Your todo list have fewer items than your selected index."}))))
(response (format "%s is not valid syntax." cmd_params))))
(defmethod process-cmd :help [_]
(let [txt "
1. `/aa list` \tShows all tags in this channel\n
2. `/aa list t` \tShows all tags in this channel with tag \"t\"\n
3. `/aa add foo` \tAdd \"foo\" item to current channel, with no tags\n
4. `/aa add foo [tag1, tag2]` \tAdd \"foo\" item to current channel, with tags tag1, and tag2\n
5. `/aa toggle 8` \tChange state of 8th item in channel (as in `/aa list`)\n
6. `/aa toggle #8` \tChange state of item with id 8.\n
7. `/aa delete 8` \tDelete 8th item in channel (as in `/aa list`)\n
8. `/aa delete #8` \tDelete item with id 8.\n
9. `/aa me` \tList todos tagged to me (equivalent to `/aa list @myusername`)\n
10. `/aa help` \tShows help information"]
(s/whisper {:pretext "AA usage information:" :text txt})))
(defmethod process-cmd :default [params] (response (format "*%s* is not a valid command. Please type */aa help* for usage info." (:cmd params))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment