biggieurl / src / biggieurl.clj

(ns biggieurl
  (:gen-class :extends javax.servlet.http.HttpServlet)
  (:use appengine.datastore
        appengine.users 
        compojure.core
        hiccup.core
        hiccup.form-helpers
        [hiccup.page-helpers :only (include-css include-js)]
        ring.util.response
        ring.util.servlet)
  (:require [compojure.route :as route]
            [clojure.contrib.logging :as log])
  (:import java.util.UUID))

(defn uuid []
  (apply str (re-seq #"[0-9a-f]+" (str (UUID/randomUUID)))))

(defentity Url ()
  ((short :key identity)
   (original)))

(def *title* "BiggieURL: The not-so-small URL Shortener")
(def *jquery-url* 
  "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js")

(defn header-link []
  (if (nil? (current-user))
    [:a {:href (login-url "/")} "Login"]
    [:a {:href (logout-url "/")} "Logout"]))

(defn user-name []
  (let [user (current-user)]
    (if (nil? user)
      "Stragner"
      (:nickname user))))

(defn original-url [short-url]
  (let [u (find-entity (make-key "url" short-url))]
    (when u
      (redirect (:original u)))))

(defn full-url [url]
  (if (re-matches #"^[a-z]{3,5}://.*" url)
    url
    (str "http://" url)))

(defn create-new-url [original-url]
  (let [short-url (uuid)
        u (url {:short short-url :original (full-url original-url)})]
    (save-entity u)
    short-url))

(defn shorten-url [params]
  (let [original-url (full-url (params "url"))
        urls (find-urls-by-original original-url)]
    (if (empty? urls) ; New URL
      (create-new-url original-url)
      (:short (first urls)))))

(defn home-page []
  (html
    [:head
     (include-css "/static/site.css")
     [:title *title*]]
    [:body 
     [:a {:href "http://clj-la.org"} 
      [:img {:id "logo" :src "/static/clj-la-logo-grungy.png"}]]
     [:div {:class "header"} "Hello " (user-name) " [" (header-link) "]"]
     [:h1 *title*]
     "URL: " [:input {:type "text" :id "url" :size "100"}]
     [:button {:id "shorten"} "Shorten"]
     [:div {:id "shortened" :class "shortened"}]]
     (include-js *jquery-url*)
     (include-js "/static/site.js")))

(defroutes biggieurl-routes
  (GET "/" [] (home-page))
  (POST "/shorten" {params :params} (shorten-url params))
  (GET "/:url" [url] (or (original-url url) :next))
  (route/not-found "Sorry, can't find it."))

(defservice biggieurl-routes)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.