Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Initial import

  • Loading branch information...
commit ac644b902cf15e506eedb4230b9eb16bd6374480 0 parents
Arnaud Berthomier authored
2  .gitignore
... ... @@ -0,0 +1,2 @@
  1 +node_modules/
  2 +tw.js
14 LICENSE
... ... @@ -0,0 +1,14 @@
  1 + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
  2 + Version 2, December 2004
  3 +
  4 +Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
  5 +
  6 +Everyone is permitted to copy and distribute verbatim or modified
  7 +copies of this license document, and changing it is allowed as long
  8 +as the name is changed.
  9 +
  10 + DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
  11 + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  12 +
  13 + 0. You just DO WHAT THE FUCK YOU WANT TO.
  14 +
8 Makefile
... ... @@ -0,0 +1,8 @@
  1 +all: clean
  2 + echo '#!/usr/bin/env node' >> tw.js
  3 + coffee -p tw.coffee >> tw.js
  4 +
  5 +clean:
  6 + rm -rf ./tw.js
  7 +
  8 +PHONY: all
23 README.md
Source Rendered
... ... @@ -0,0 +1,23 @@
  1 +tw
  2 +==
  3 +
  4 +tw is a tiny node script that I often use to avoid switching to a
  5 +browser when a Twitter status link is mentioned. It was written a long
  6 +time ago, is ugly, but does the job.
  7 +
  8 +What does it do?
  9 +
  10 + $ tw -h
  11 + Usage: tw <tweet url | tweet id>
  12 + -h show help
  13 + -u <nick> user's tweets
  14 + -s <search term> search tweets
  15 + -i <status id | status url> show status
  16 +
  17 +Really, that's it.
  18 +
  19 + $ tw 'https://twitter.com/#!/CodeWisdom/status/170178134015094784'
  20 + CodeWisdom (16/1/2012 16:10:3 UTC): "Larry Wall is right. Laziness should be a
  21 + virtue. So that's why I prefer automation." - Brendan Eich (creator of
  22 + JavaScript)
  23 +
24 package.json
... ... @@ -0,0 +1,24 @@
  1 +{
  2 + "author": "Arnaud Berthomier <oz@cyprio.net>",
  3 + "name": "tw",
  4 + "description": "Twitter helper",
  5 + "keywords": ["twitter", "client"],
  6 + "version": "0.1.0",
  7 + "repository": {
  8 + "type": "git",
  9 + "url": "http://github.com/oz/tw.git"
  10 + },
  11 + "engines": {
  12 + "node": "~0.6"
  13 + },
  14 + "bin" : {
  15 + "tw": "./tw.js"
  16 + },
  17 + "dependencies": {
  18 + "optimist": "~0.3"
  19 + },
  20 + "devDependencies": {
  21 + "coffee-script": "~1.2"
  22 + },
  23 + "optionalDependencies": {}
  24 +}
92 tw.coffee
... ... @@ -0,0 +1,92 @@
  1 +#!/usr/bin/env coffee
  2 +
  3 +argv = require('optimist').argv
  4 +http = require 'http'
  5 +URL = require 'url'
  6 +PROG_NAME = 'tw'
  7 +
  8 +if argv.h
  9 + console.log "Usage: "+PROG_NAME+" <tweet url | tweet id>"
  10 + console.log " -h show help"
  11 + console.log " -u <nick> user's tweets"
  12 + console.log " -s <search term> search tweets"
  13 + console.log " -i <status id | status url> show status\n"
  14 + process.exit()
  15 +
  16 +##
  17 +# Fetch JSON from Twitter API, and call cb with the parsed JSON object
  18 +# unless Twitter sends us an error...
  19 +#
  20 +# @param [String] path API Path or complete URL
  21 +# @param [Function] cb Callback receiving Twitter's response as an Object
  22 +fetch = (path, cb) ->
  23 + show_error = (obj) -> console.log "Error: " + (obj.message || obj.error)
  24 + if path.match(/^http/) && url = URL.parse(path)
  25 + options =
  26 + host: url.hostname
  27 + post: (url.protocol == 'https' ? 443 : 80)
  28 + path: url.pathname + url.search
  29 + else
  30 + options =
  31 + host: "api.twitter.com"
  32 + post: 443
  33 + path: path
  34 +
  35 + req = http.get options, (res) ->
  36 + res.setEncoding "utf8"
  37 + buf = ""
  38 + res.on "data", (chunk) -> buf += chunk
  39 + res.on "end", () ->
  40 + o = JSON.parse buf
  41 + if o.error
  42 + console.log "Error: " + o.error
  43 + else
  44 + cb o
  45 + req.on "error", (e) -> show_error e
  46 +
  47 +##
  48 +# Fetch a user's statuses
  49 +# @param [String] screen_name User's screen name
  50 +viewUserStatuses = (screen_name) ->
  51 + path = "/1/statuses/user_timeline.json?screen_name=" + screen_name
  52 + fetch path, (tweets) -> tweets.map (e) -> displayTweet e
  53 +
  54 +##
  55 +# Fetch one status by ID
  56 +# @param [String] status_id A status ID
  57 +viewStatus = (status_id) ->
  58 + path = "/1/statuses/show/" + status_id + ".json"
  59 + fetch path, (tweet) -> displayTweet tweet
  60 +
  61 +##
  62 +# Search tweets
  63 +# @param [String] query Search query
  64 +searchTweets = (query) ->
  65 + uri = 'https://search.twitter.com/search.json?q='+query
  66 + fetch uri, (response) ->
  67 + response.results ||= []
  68 + response.results.map (r) ->
  69 + displayTweet
  70 + created_at: r.created_at,
  71 + user:
  72 + screen_name: r.from_user,
  73 + text: r.text
  74 +
  75 +##
  76 +# Display a single tweet
  77 +# @param [Object] tweet A tweet object fresh from Twitter's API
  78 +displayTweet = (tweet) ->
  79 + d = new Date tweet.created_at
  80 + date = ['Date' , 'Month' , 'FullYear'].map (n) -> d['getUTC'+n]()
  81 + time = ['Hours', 'Minutes', 'Seconds' ].map (n) -> d['getUTC'+n]()
  82 + date_str = date.join('/') + ' ' + time.join(':') + ' UTC'
  83 + console.log tweet.user.screen_name + " (" + date_str + "): " + tweet.text + "\n"
  84 +
  85 +##
  86 +# Args dispatching's done here.
  87 +viewUserStatuses argv.u if argv.u
  88 +searchTweets argv.s if argv.s
  89 +viewStatus argv.i if argv.i
  90 +# Handle <tw 123123123> and/or <tw "http://..../status/123123213">
  91 +if argv._.length == 1 && matches = (""+argv._[0]).match(/(status\/)?(\d+)\/?/)
  92 + viewStatus matches[2]

0 comments on commit ac644b9

Please sign in to comment.
Something went wrong with that request. Please try again.