Commits

Miki Tebeka committed 224c94e

Getting request

Comments (0)

Files changed (11)

-(defproject dude-remember "1.0.0-SNAPSHOT"
-  :description "Phone TODO list"
+(defproject tropo "1.0.0-SNAPSHOT"
+  :description ""
   :dependencies [[org.clojure/clojure "1.2.0"]
                  [org.clojure/clojure-contrib "1.2.0"]
-                 [compojure "0.4.1"]
-                 [ring/ring-servlet "0.2.5"]
-                 [hiccup "0.2.6"]
-                 [appengine "0.4-SNAPSHOT"]
-                 [clj-time "0.1.0-RC1"]]
+                 [compojure "0.5.1"]
+                 [ring/ring-servlet "0.3.1"]
+                 [hiccup "0.2.7"]
+                 [appengine "0.4-SNAPSHOT"]]
   :dev-dependencies [[com.google.appengine/appengine-api-labs "1.3.7"]
                      [com.google.appengine/appengine-api-stubs "1.3.7"]
-                     ;[com.google.appengine/appengine-local-runtime "1.3.7"]
                      [com.google.appengine/appengine-testing "1.3.7"]]
-  :namespaces [duderemember]
+  :namespaces [tropo]
   :compile-path "war/WEB-INF/classes"
   :library-path "war/WEB-INF/lib")
 #!/bin/bash
 
+# Exit on error
+set -e
+
 lein compile
 ~/appengine-java-sdk-1.3.7/bin/dev_appserver.sh -a 0.0.0.0 war

src/duderemember.clj

-(ns duderemember
-  (:gen-class :extends javax.servlet.http.HttpServlet)
-  (:use appengine.datastore
-        appengine.users 
-        clojure.contrib.prxml
-        compojure.core
-        hiccup.core
-        hiccup.form-helpers
-        hiccup.page-helpers
-        ring.util.response
-        ring.util.servlet)
-  (:require [compojure.route :as route]
-            [clojure.contrib.logging :as log]))
-
-(defn digits-only [phone]
-  (apply str (re-seq #"[0-9]+" phone)))
-
-(defentity User ()
-  ((user-id) ; We call it user-id to match Google user object
-   (phone)))
-
-(defentity Message ()
-  ((user-id)
-   (time)
-   (text)
-   (url)))
-
-(defn phone->user [phone]
-  (let [users (find-users-by-phone phone)]
-    (if (zero? (count users))
-      nil
-      (first users))))
-
-(defn user->phone [user]
-  (let [entities (find-users-by-user-id (:user-id user))]
-    (if (zero? (count entities))
-      nil
-      (:phone (first entities)))))
-
-(defn new-user? [user]
-  (nil? (user->phone user)))
-
-(defn update-user [u phone]
-  (let [phone (digits-only phone)]
-    (if (new-user? u)
-      (save-entity (user {:user-id (:user-id u) :phone phone}))
-      (let [entity (first (find-users-by-user-id (:user-id u)))]
-        (update-entity entity {:phone phone})
-        (save-entity entity)))))
-
-(defn now []
-  (System/currentTimeMillis))
-
-(defn add-sms [user text]
-  (let [entity (message {:user-id (:user-id user) :text text :time (now)})]
-    (save-entity entity)))
-
-(defn add-voice [user url]
-  (let [entity (message {:user-id (:user-id user) :url url :time (now)})]
-    (save-entity entity)))
-
-(defn user-messages [user]
-  (select "message"
-    where (= :user-id (:user-id user))
-    order-by (:time :desc)))
-
-(def *title* "Dude! ... Remember!")
-
-(defn header-link []
-  (if (nil? (current-user))
-    [:a {:href (login-url "/")} "Login"]
-    [:a {:href (logout-url "/")} "Logout"]))
-
-(def *jquery-url* 
-  "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js")
-
-(defn page [& content]
-  (html
-    [:head
-     (include-css "/static/dude.css")
-     (include-js *jquery-url*)
-     (include-js "/static/dude.js")
-     [:title *title*]]
-    [:body 
-     [:div {:class "header"} (header-link)]
-     [:h1 [:a {:href "/"} [:img {:src "/static/sms.png"}]] *title*]
-     content]))
-
-(defn format-time [t]
-  (let [date (new java.util.Date)]
-    (.setTime date t)
-    (str date)))
-
-(defn render-messages [messages]
-  (if (zero? (count messages))
-    "No messages for you!"
-    (for [message messages]
-      [:div {:class "message" :id (key->string (:key message))}
-       "Time: " (format-time (:time message)) 
-       ; FIXME: I'll leave it to Sean to make it nice ;)
-       [:button {:class "delete"} "[X]"] [:br]
-       (if (nil? (:url message))
-         ["Text:" [:br] (:text message)]
-         [:a {:href (:url message)} "Play"])])))
-
-(defn format-phone [phone]
-  (format "%s-%s-%s" (subs phone 0 3) (subs phone 3 6) (subs phone 6)))
-
-(defn user-page [user]
-  (let [messages (user-messages user)
-        phone (format-phone (user->phone user))]
-    (page
-      [:h2 "Messages for " (:nickname user) " (" 
-           [:a {:href "/phone" } phone] ")"]
-      (render-messages messages))))
-
-(defn eval-page [expr]
-  (page
-    (str (load-string (str "(in-ns 'duderemember)" expr)))
-    (form-to [:post]
-      [:br]
-      [:input {:type "text" :name "expr" :value expr :size "100"}]
-      (submit-button "Eval"))))
-
-(defn phone-page []
-  (page
-    "Please update your phone number" [:br]
-    (form-to [:post]
-       (text-field :phone)
-       (submit-button "Update"))))
-
-(defn twilio-response [& params]
-  (with-out-str (prxml [:Response params])))
-
-; Remove the +1 suffix
-(defn normalize-phone [phone]
-  (subs phone 2))
-
-(defn twilio-sms [params]
-  (log/info (str "SMS: " params))
-  (let [phone (normalize-phone (params "From"))
-        text (params "Body")
-        user (phone->user phone)]
-    (if user
-      (do (add-sms user text)
-        (twilio-response))
-      ; Can't find user, SMS back how to register
-      (twilio-response [:Sms "Dude, I don't know you! "
-                            "Check out http://dude-remember.appspot.com"]))))
-
-(defn twilio-voice [params]
-  (log/info (str "VOICE: " params))
-  (let [phone (normalize-phone (params "From"))
-        user (phone->user phone)]
-    (if (nil? user)
-      (twilio-response [:Say {:voice "woman"} "Dude, I don't know you. Ciao!"]
-                      [:Hangup])
-      (let [url (params "RecordingUrl")]
-        (if (nil? url) ; New call
-          (twilio-response [:Say {:voice "woman"} "Talk to me babe!"]
-                          [:Record {:maxLength "30"}])
-          (do (add-voice user url)
-            (twilio-response [:Say {:voice "woman"} "Gotcha! Later dude."]
-                            [:Hangup])))))))
-(defn general-index []
-  (page
-    [:div "This is a simple service where you send notifications to yourself
-          via voice calls or SMS"]
-    [:div "All you need to do is to " [:a {"href" (login-url "/")} "login"]
-          " using your Google account and update your phone."]))
-
-(defn can-delete [user message]
-  (let [user-id (:user-id user)]
-    (and (not (nil? user-id)) (= user-id (:user-id message)))))
-
-(defn delete-message [id]
-  (let [message-key (string->key id)
-        message (find-entity {:key message-key})]
-    (if (nil? message)
-      (do (log/error (format "DELETE %s - not found" id))
-        {:status 404 :body (format "Eeek, can't find %s!" id)})
-      (if (not (can-delete (current-user) message))
-        (do 
-          (log/error (format "Unauthorized: %s delete %s" (current-user) id))
-          {:status 401 :body "No DELETE for you!"})
-        (do (delete-entity message-key)
-          {:status 200 :body "OK"})))))
-             
-(defn welcome-page []
-  (let [user (current-user)]
-    (if (nil? user)
-      (general-index)
-      (if (new-user? user)
-        (redirect "/phone")
-        (user-page user)))))
-
-(defroutes duderemeber-routes
-  (GET "/" [] (welcome-page))
-
-  (GET "/phone" [] (phone-page))
-  (POST "/phone" {params :params}
-        (let [phone (params "phone")]
-          (update-user (current-user) phone)
-          (redirect "/")))
-  (DELETE "/message/:id" [id] (delete-message id))
-
-  (POST "/twilio/sms" {params :params} (twilio-sms params))
-  (POST "/twilio/voice" {params :params} (twilio-voice params))
-
-; Uncomment these when debugging, *don't* let them slip to production           
-;  (GET "/_eval" [] (eval-page "0"))
-;  (POST "/_eval" {params :params} (eval-page (params "expr")))
-
-  (route/not-found "Dude! I can't find it."))
-
-(defservice duderemeber-routes)
+(ns tropo
+  (:gen-class :extends javax.servlet.http.HttpServlet)
+  (:use appengine.datastore
+        appengine.users 
+        clojure.contrib.prxml
+        [clojure.contrib.json :only [json-str]]
+        [clojure.contrib.io :only [slurp*]]
+        compojure.core
+        hiccup.core
+        hiccup.form-helpers
+        hiccup.page-helpers
+        ring.util.response
+        ring.util.servlet)
+  (:require [compojure.route :as route]
+            [clojure.contrib.logging :as log]))
+
+(def *title* "Tropo Playground")
+
+(defn header-link []
+  (if (nil? (current-user))
+    [:a {:href (login-url "/")} "Login"]
+    [:a {:href (logout-url "/")} "Logout"]))
+
+(def *jquery-url* 
+  "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js")
+
+(defn page [& content]
+  (html
+    [:head
+     (include-css "/static/site.css")
+     (include-js *jquery-url*)
+     (include-js "/static/site.js")
+     [:title *title*]]
+    [:body 
+     [:div {:class "header"} (header-link)]
+     [:h1 *title*]
+     content]))
+
+
+(defn tropo-resonse [& params]
+  (json-str {:tropo [{:say [{:value "OMG, it works!"}]} {:hangup nil}]}))
+
+(defn tropo-sms [params]
+  (log/info (str "SMS: " params))
+  (tropo-resonse))
+
+(defn tropo-voice [params]
+  (log/info (str "VOICE: " params))
+  (tropo-resonse))
+
+(defn welcome-page []
+  (page "Playing with Tropo"))
+
+(defroutes tropo-routes
+  (GET "/" [] (welcome-page))
+
+  (POST "/tropo/sms" {params :params} (tropo-sms params))
+  (POST "/tropo/voice" {body :body} (tropo-voice (slurp* body)))
+
+; Uncomment these when debugging, *don't* let them slip to production           
+;  (GET "/_eval" [] (eval-page "0"))
+;  (POST "/_eval" {params :params} (eval-page (params "expr")))
+
+  (route/not-found "Dude! I can't find it."))
+
+(defservice tropo-routes)

war/WEB-INF/appengine-web.xml

 <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
-  <application>dude-remember</application>
+  <application>tropo</application>
   <version>1</version>
   <static-files />
   <resource-files />

war/WEB-INF/web.xml

     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
     version="2.5">
-  <display-name>Dude, Remember!</display-name>
+  <display-name>Tropo</display-name>
   <servlet>
-    <servlet-name>dr</servlet-name>
-    <servlet-class>duderemember</servlet-class>
+    <servlet-name>tr</servlet-name>
+    <servlet-class>tropo</servlet-class>
   </servlet>
   <servlet-mapping>
-    <servlet-name>dr</servlet-name>
+    <servlet-name>tr</servlet-name>
     <url-pattern>/*</url-pattern>
   </servlet-mapping>
 </web-app>

war/static/dude.css

-body {
-    border: 5px solid blue;
-    margin: 20px;
-    padding: 10px;
-    font-family: Georgia;
-}
-
-div.message {
-    border: 1px dashed silver;
-}
-
-div.header {
-    width: 100%;
-    text-align: right;
-}
-
-h1 > a > img {
-    border: none;
-    padding-right: 5px;
-}
-

war/static/dude.js

-function delete_message (id) {
-    $.ajax({
-        success: function(data, status, request) {
-            $("#" + id).remove();
-        },
-        data: {id: id},
-        /* FIXME: error: function(request, status, error) { ... } */
-        type: "DELETE",
-        url: "/message/" + id
-    });
-}
-
-function on_ready() {
-    $("button.delete").click(function () { 
-            delete_message($(this).parent().attr("id"));
-    });
-}
-
-$(document).ready(on_ready);

war/static/site.css

+body {
+    border: 5px solid blue;
+    margin: 20px;
+    padding: 10px;
+    font-family: Georgia;
+}
+
+div.message {
+    border: 1px dashed silver;
+}
+
+div.header {
+    width: 100%;
+    text-align: right;
+}
+
+h1 > a > img {
+    border: none;
+    padding-right: 5px;
+}
+

war/static/site.js

+function delete_message (id) {
+    $.ajax({
+        success: function(data, status, request) {
+            $("#" + id).remove();
+        },
+        data: {id: id},
+        /* FIXME: error: function(request, status, error) { ... } */
+        type: "DELETE",
+        url: "/message/" + id
+    });
+}
+
+function on_ready() {
+    $("button.delete").click(function () { 
+            delete_message($(this).parent().attr("id"));
+    });
+}
+
+$(document).ready(on_ready);

war/static/sms.png

Removed
Old image