Created
November 5, 2009 02:36
-
-
Save hiredman/226651 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns socialmetrics.servlet | |
(:gen-class :extends javax.servlet.http.HttpServlet) | |
(:use compojure.html compojure.http) | |
(:import (java.util Properties Date) | |
(java.io File FileInputStream OutputStreamWriter | |
BufferedReader InputStreamReader) | |
(java.net URL) | |
(java.text SimpleDateFormat ParsePosition FieldPosition) | |
(org.apache.commons.codec.digest DigestUtils))) | |
(defmacro load-properties | |
"macroexpand/compile time loading of a properties file into a clojure map" | |
[filename] | |
(let [p (Properties.) | |
is (-> filename File. FileInputStream.)] | |
(.load p is) | |
(into {} p))) | |
(def facebook (load-properties "facebook.properties")) | |
(defn call-id | |
"many facebook api calls require a call-id and call-ids must be in ascending | |
order per session" | |
[] | |
(.getTime (Date.))) | |
(def now (Date.)) | |
(defn name|str | |
"name on Named things and .toString otherwise" | |
[x] | |
(if (instance? clojure.lang.Named x) | |
(name x) | |
(.toString x))) | |
(defn post | |
"post stuff to url, clojure.xml/parse output" | |
[url stuff] | |
(let [con (doto (.openConnection (URL. url)) | |
(.setDoInput true) | |
(.setDoOutput true))] | |
(with-open [wrt (-> con .getOutputStream OutputStreamWriter.)] | |
(.write wrt stuff)) | |
(with-open [a (-> con .getInputStream)] | |
(clojure.xml/parse a)))) | |
(defn md5 [string] | |
(DigestUtils/md5Hex string)) | |
(defn sig | |
"facebook api calls require a signature (md5 hash) of the call the api secret" | |
[params] | |
(md5 | |
(.concat | |
(reduce #(format "%s%s=%s" %1 (name|str (first %2)) (second %2)) | |
"" | |
(sort-by key params)) | |
(facebook "api.secret")))) | |
(defn call | |
"takes a map representing a facebook api call and makes the call" | |
[bag] | |
(post "http://api.facebook.com/restserver.php" | |
(format "%s&sig=%s" | |
(reduce | |
#(format "%s%s=%s&" %1 (name|str (first %2)) (second %2)) | |
"" | |
bag) | |
(sig bag)))) | |
(defn string->date | |
[string] | |
(.parse (SimpleDateFormat. "MM/dd/yyyy") | |
string | |
(ParsePosition. 0))) | |
(defn date->age [date] | |
(let [cy (.getYear now) | |
oy (.getYear date)] | |
(- cy oy))) | |
(defn select-birthday_date [foo] | |
(-> foo :content | |
((partial filter #(= :birthday_date (:tag %)))) | |
first | |
:content | |
first | |
((fn [x] | |
(when x (when-let [t (string->date x)] (date->age t))))))) | |
(defn chart [map-] | |
(format "http://chart.apis.google.com/chart?chtt=%s&cht=bvg&chd=t:%s&chs=900x250&chl=%s" | |
"Your friends' ages:" | |
(reduce #(format "%s,%s" %1 %2) (vals map-)) | |
(reduce #(format "%s|%s" (or %1 "unknown") (or %2 "unknown")) (keys map-)))) | |
(defn main [request] | |
(let [session (-> request :params :fb_sig_session_key) ;facebook passes me a session key | |
friends (-> request :params :fb_sig_friends) ; and a list of friends | |
foo (call {:api_key (facebook "api.key") ;get the birthday_date profile field from all the friends | |
:method "Users.getInfo" | |
:call_id (call-id) | |
:v "1.0" | |
:uids friends | |
:fields "birthday_date" | |
:session_key session}) | |
foo (-> foo :content | |
((partial map select-birthday_date)) | |
((partial map #(array-map %1 1))) | |
((partial apply (partial merge-with +))) | |
((partial into (sorted-map))) | |
chart)] | |
(format | |
" | |
<fb:if-is-app-user> | |
<img style=\"width:750px;\" src=\"%s\" /> | |
<fb:else> | |
<fb:redirect url=\"http://www.facebook.com/login.php?v=1.0&api_key=%s&next=%s&canvas=\"/></fb:else> | |
</fb:if-is-app-user> | |
" | |
foo | |
(facebook "api.key") | |
"http://apps.facebook.com/agegraph/"))) | |
(defroutes socialmetrics | |
(ANY "/" main)) | |
(defservice socialmetrics) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment