;; I'm not saying this is good Clojure, but it was off the top of my head ;; It's a title bot for jschat.org (import '(java.io BufferedReader InputStreamReader PrintWriter)) (import '(java.net Socket)) (import '(java.net HttpURLConnection URL)) (use '[clojure.contrib.json.read :only (read-json)]) (use '[clojure.contrib.json.write :only (json-str)]) ;; Data structures (defstruct jschat-server :address :port) (defstruct message :message :channel) ;; Settings (def server (struct jschat-server "127.0.0.1" 6789)) (def username "titlebot") (def channel "#jschat") (def socket (new Socket (server :address) (server :port))) (def reader (new BufferedReader (new InputStreamReader (. socket (getInputStream))))) (def writer (new PrintWriter (. socket getOutputStream) true)) ;; HTTP requests with length (defn fetch-url "Fetches 1000 lines of text from a URL." [url] (let [connection (. (new URL url) openConnection)] (let [stream (new BufferedReader (new InputStreamReader (. connection getInputStream)))] (if (re-find #"html" (. connection getContentType)) (apply str (take 1000 (line-seq stream))))))) (defn title-url "Return the title of a web page" [url] (try (let [src (fetch-url url) title (second (re-find #"(?i)\s?(.*)" src))] (str "Title: " (.trim title))) (catch java.io.FileNotFoundException _ "Error: Page not found") (catch Exception _ false))) ;; Connection (defn write-jschat [data] (. writer println (json-str data))) (defn read-jschat [] (read-json (. reader readLine))) ;; JsChat commands (defn identify [name] (write-jschat { "identify" name })) (defn join [channel] (write-jschat { "join" channel })) (defn send-message [message channel] (write-jschat { "send" message "to" channel })) ;; Return the significant part of a response (defmulti jschat-response (fn [response] (response "display"))) (defmethod jschat-response "message" [message] ((message "message") "message")) (defmethod jschat-response "join" [message] (println "Joining room: " ((message "join") "room"))) (defn extract-url [text] (str "http://" (second (re-find #"http://([^\s]*)" text)))) (defn extract-url-from-response [response] (extract-url (jschat-response response))) (defn get-title [response] (try (title-url (extract-url-from-response response)) (catch Exception _ false))) (.start (Thread. (fn [] (while true (let [title (get-title (read-jschat))] (if title (send-message title channel))))))) ;; Identify and join a channel (identify username) (join channel)