Christoph tries to get a handle on his #clojure tweet-stream habit.
- NOT tic-tac-toe
- Follow
#clojure
tweet stream and see it print out in the terminal
- "We like reinventing things."
- "The terminal is the best UI out there."
- Does Twitter have an API?
- Websocket? Nope! Requires a big "E" plan: "enterprise".
- PubSub? Nope! Not from Twitter.
- Alas, we must poll the
/search/tweets.json
endpoint
- Problem: we're going to keep getting results we've already seen
- Avoid duplicates? Let's use core cache.
- Once again, we use
loop
and recur
for our main loop
- Time for an API wrapper, but what does the wrapper do?
- HTTP POST form-encoded parameters
- Ack!
401 Access Denied
- "An important step in any API exploration is your first 401 response."
- "OAuth?" "Oh....auth..."
- Meet OAuth, the API bouncer.
- Make an
auth
function to call the OAuth endpoint and get an auth token
- Have
auth
return a "handle" with the auth token. Other wrapper functions will need handle
.
- Need to keep
handle
around. Put that in the app state too.
- Let the exceptions fly!
- "Exceptions are an exceptionally accepted way of handling exceptional circumstances."
- "I caught what you meant."
- Make a
fetch
function that does the I/O work.
- Create a
search
function that takes handle
and query
- Look for pure logic and move it into its own function, then it's easy to test.
- Transform args to
search
into a "request description" and have fetch
operate on that.
- "Twitch, I mean Twitter. You know, that Internet thing that starts with t-w-i-t."
- Different layers of the wrapper:
- Top-level functions used by the application. Sole job: sequence internal functions
- Pure transforms from args to "request description"
- A
fetch
function that follows the "orders" of the "request description"
- "The point of testing this code is not to test if Aleph works or Twitter works. The logic is in the translation function, so that's why we test it."
- "Our hero, the Twitch wrapper, is poised and ready to fetch data on our behalf. What will happen next?"
Clojure in this episode:
loop
, recur
Thread.sleep
get
try
, catch
->
Related projects: