Created
November 27, 2013 04:02
-
-
Save hiredman/7670532 to your computer and use it in GitHub Desktop.
clojure roku control
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
#!/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