Skip to content

Instantly share code, notes, and snippets.

@hiredman
Created November 27, 2013 04:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hiredman/7670532 to your computer and use it in GitHub Desktop.
Save hiredman/7670532 to your computer and use it in GitHub Desktop.
clojure roku control
#!/usr/bin/java -jar /Users/hiredman/src/clojure/target/clojure-1.6.0-master-SNAPSHOT.jar
(let [pom-uber-jar
(str "http://thelibraryofcongress.s3.amazonaws.com/"
"pomegranate-0.0.13-SNAPSHOT-jar-with-dependencies.jar")
cl (java.net.URLClassLoader. (into-array [(java.net.URL. pom-uber-jar)]))
cx (.getContextClassLoader (Thread/currentThread))]
(push-thread-bindings {clojure.lang.Compiler/LOADER cl})
(.setContextClassLoader (Thread/currentThread) cl)
(try
(require '[cemerick.pomegranate :as pom])
(finally
(.setContextClassLoader (Thread/currentThread) cx)
(pop-thread-bindings))))
(pom/add-dependencies :coordinates '[[clj-http "0.6.5"]]
:repositories (merge cemerick.pomegranate.aether/maven-central
{"clojars" "http://clojars.org/repo"}))
(require '[clj-http.client :as http])
(import '(java.net DatagramSocket
InetAddress
DatagramPacket))
(defn explorer []
(let [add (InetAddress/getByName "239.255.255.250")
sock (DatagramSocket. 1900)
p (DatagramPacket. (byte-array 1024) 1024)
state (atom {})
f (fn [p]
(let [[good & headers] (.split (.trim (String. (.getData p))) "\r\n")
data (into {:updated (System/currentTimeMillis)}
(for [head headers
:when (.contains head ":")
:let [colon (.indexOf head ":")]]
[(.trim (subs head 0 colon)) (.trim (subs head (inc colon)))]))]
(swap! state assoc (get data "USN") data)))
n (atom 0)
data (str "M-SEARCH * HTTP/1.1\r\n"
"Host: 239.255.255.250:1900\r\n"
"Man: \"ssdp:discover\"\r\n"
"ST: roku:ecp\r\n")
data-bytes (.getBytes data)
disco-p (DatagramPacket. data-bytes (count data-bytes) add 1900)
l (future
(while true
(when (> (System/currentTimeMillis)
(+ @n (* 1000 60 10)))
(reset! n (System/currentTimeMillis))
(.send sock disco-p))
(.receive sock p)
(f p)))]
(reify
java.io.Closeable
(close [_]
(future-cancel l)
(.close sock))
clojure.lang.IDeref
(deref [_]
(set (vals @state))))))
(def e (explorer))
(defn wait-for [{:keys [fun timeout sleep]}]
(let [start (System/currentTimeMillis)]
(loop [now (System/currentTimeMillis)]
(if (>= (- now start) timeout)
(fun)
(if (fun)
true
(do
(Thread/sleep sleep)
(recur (System/currentTimeMillis))))))))
(prn "Find Roku" (wait-for {:fun (fn [] (some #(.contains (get % "USN") "roku") @e))
:timeout (* 1000 60)
:sleep 1000}))
(def roku (first (filter #(.contains (get % "USN") "roku") @e)))
(def roku-url (get roku "Location"))
(println roku-url)
(require 'clojure.xml)
(def hulu-app-id (->> (http/get (str roku-url "query/apps")
{:as :stream})
:body
clojure.xml/parse
(tree-seq map? :content)
(filter #(some #{"Hulu Plus"} (:content %)))
first
:attrs
:id))
(println hulu-app-id)
(http/post (str roku-url "keypress/Home"))
(Thread/sleep (* 1000 30))
(http/post (str roku-url "launch/" hulu-app-id))
(Thread/sleep (* 1000 35))
(http/post (str roku-url "keypress/Up"))
(Thread/sleep 1000)
(http/post (str roku-url "keypress/Select"))
(Thread/sleep 1000)
(defn hulu-keyboard
([]
(hulu-keyboard \m))
([initial-letter]
{:location initial-letter}))
(defn type-letter [kb letter]
(let [letter (if (= \space letter)
(dec (int \a))
(int letter))
diff (- (int (:location kb))
letter)]
(if (pos? diff)
(dotimes [_ diff]
(Thread/sleep 200)
(http/post (str roku-url "keypress/Left")))
(dotimes [_ (* -1 diff)]
(Thread/sleep 200)
(http/post (str roku-url "keypress/Right"))))
(Thread/sleep 200)
(http/post (str roku-url "keypress/Select"))
{:location letter}))
(defn type-string [kb string]
(reduce type-letter kb string))
(if (= (first *command-line-args*) "colbert")
(type-string (hulu-keyboard) "colbert report")
(type-string (hulu-keyboard) "daily show"))
(Thread/sleep (* 1000 10))
(http/post (str roku-url "keypress/Down"))
(Thread/sleep 500)
(http/post (str roku-url "keypress/Select"))
(Thread/sleep (* 1000 10))
(http/post (str roku-url "keypress/Select"))
(.close e)
(shutdown-agents)
(System/exit 0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment