Skip to content

Instantly share code, notes, and snippets.

@alexyoung
Created June 17, 2009 18:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save alexyoung/131415 to your computer and use it in GitHub Desktop.
Save alexyoung/131415 to your computer and use it in GitHub Desktop.
;; 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?<title>(.*)</title>" 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)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment