There's life in the old shell yet.  Now you can use bash and your favorite
text editor to let everyone know what you had for breakfast this morning...
Put it on cron and ... um, well I dunno, use it kind of like a deadman's
tweet if something goes wrong?

Just edit the variables at the top of the file to taste, make sure MY_HOME
and ARCHIVE exist, save and then source it into your current shell
  % . twitter.sh
  % h # For help
Try
  % post
to test it.

  % edit # To edit a message
  % send # To send edited message

'send' is a bit more clever, launches your editor and breaks up long posts
into the 140 char limit (uses gnu's 'fold' utility for the black magic bit).

'send.reverse' reverses the lines which has the effect of making long
broken-up posts read top to bottom on the twitter website but probably
breaks some basic idea about how you're supposed to use it or something...

Here's the file (half of which is the help message):
--
# Requirements: curl, less, fold (gnu coreutils)

# Variables here:

MY_HOME=/home/danb/twitter
TMP_FILE=$MY_HOME/tmp_file.txt
  # File you use to write your tweets.
TEST_FILE=$MY_HOME/lorem.para1
  # For testing 'send'.  See test.* functions.
USERNAME=twitter_username
PASSWORD=twitter_password
COOKIEJAR=$MY_HOME/cookie.txt
ARCHIVE=$MY_HOME/archive/previous
  # File to dump previous tweets.
EDITOR=vim
  # Editor shouldn't detach from the shell.
POST_URL=https://twitter.com/statuses/update.xml
  # The url you post your updates to.
  # I use https, probably should be http.
STATUS_URL=http://twitter.com/statuses/user_timeline
  # Used to fetch your tweets or someone else
  # STATUS_URL.format # you
  # STATUS_URL/username.format # someone else
FOLLOWING=$MY_HOME/following.db
  # Text file listing people you follow.
  # See h() below.
DEFAULT_FORMAT=xml
  # Default format of output from twitter REST api.
  # Options are: xml|json|rss|atom


delete_blank_lines='sed -e /^$/d'
  # Deletes blank lines which are of no use to us.
html_entities='sed -e s/</\&lt;/g;s/>/\&gt;/g'
  # Twitter api will convert '>','<' to html entities which
  # count towards 140 char limit.  We do it instead.
xml_filter='egrep <text>|<created_at>'

h() {
less <<-EOF
  Twitter via the REST API


  See:
  http://apiwiki.twitter.com/Things-Every-Developer-Should-Know
    See point 8.
  http://www.sakana.fr/blog/2007/03/18/scripting-twitter-with-curl/
    See "status update" for normal twitter posting.

  Functions:
  go
    last    - edit your tmp_file without sending anything
    browser - open twitter in firefox
    recent  - view recent tweets in ARCHIVE

  format [format]
    Display current output format that will be requested from twitter.
    Options: xml|json|atom|rss
    If [format] given, set format to this.
    Use with 'status' or 'checkon' to get your twitter posts in various
    formats.  You could pipe json into javascript, ruby, python etc...
  Current output format from twitter is: $DEFAULT_FORMAT

  status
    Get your twitter posts in xml

  checkon nickname
    Get status on someone else.
    You first need to add someone to the FOLLOWING file.
    See 'following' herein.

  following
    Edits FOLLOWING; a text file listing people you follow.
    Format:
      nickname:username
    nickname must be unique; is your shorthand for username
    which is the name used by twitter.

  edit
    edit message
    Also use: 'go last'
  send
    Send a message.
    Long messages will be broken up to meet the 140 char limit.
    Currently <,> will be converted to html entities.
    Uses 'post'.
  send.reverse
    Reverses the lines you are sending which has the effect of making long
    broken-up posts read from top to bottom on the twitter website.
    Uses 'tac' instead of cat which will reverse lines.

  post "your message"
    If no message given, post will post a test message to twitter for you to
    check.
    NOTE: 'post' doesn't check the 140 character limit, or html entities
etc.
    In general, use 'send' to post your stuff.

  test.send
  test.send.dry
    Send TEST_FILE to twitter.
    'dry' doesn't send to twitter; just prints output

  test.send.reverse
  test.send.reverse.dry
    Test send.reverse.

  test.entities
    Test html entities.

EOF
}

go() {
  case "$1" in
  last) $EDITOR $TMP_FILE;;
  browser) firefox http://twitter.com;;
  recent) less $ARCHIVE;;
  *) cd $MY_HOME ;;
  esac
}

edit() {
  go last
}

format() {
  case "$1" in
    atom) DEFAULT_FORMAT=atom;;
    rss)  DEFAULT_FORMAT=rss;;
    xml)  DEFAULT_FORMAT=xml;;
    json) DEFAULT_FORMAT=json;;
    "") echo "Current format is: $DEFAULT_FORMAT";;
    *) echo "Don't know this format." ;;
  esac
}

status() {
  test -n "$1" && format="$1" || format=$DEFAULT_FORMAT
  curl --basic --user $USERNAME:$PASSWORD \
    $STATUS_URL.$format | less
}

following() {
  $EDITOR $FOLLOWING
}

checkon() {
  test ! -f $FOLLOWING && echo "Need to setup $FOLLOWING." \
    && return 1
  format=$DEFAULT_FORMAT
  nickname=$1
  test -z "$nickname" && echo "Need a nickname." && return 1
  line=$(grep '\<'$nickname'\>' $FOLLOWING)
  test -z "$line" && echo "Don't know '$nickname'." && return 1
  username=${line/#*:/}
  curl $STATUS_URL/$username.$format | less
}

post() {
  test -z "$1" && status="cURL test!" || status="$1"
  curl --basic --user $USERNAME:$PASSWORD \
       --data status="$status" \
       $POST_URL
  return $?  # If http error, curl returns >0
}

send() {

  testing=no
  order=cat
  file=$TMP_FILE

  while true; do
    test -z "$1" && break
    case "$1" in
      # Don't send to twitter.
      dry) file=$TEST_FILE; testing=dry ;;
      # Send to twitter.
      test) file=$TEST_FILE; testing=yes ;;
      reverse) order="tac";;
    esac
    shift
  done

  if ask $file; then
    echo "POSTing...."
    cat $file | $html_entities | fold -s -b -w 140 $file | \
    $delete_blank_lines | $order | \
    while read line; do
      case "$testing" in
      dry) echo $line; continue ;;
      *)
      if post "$line"; then
        echo "(posted a line!)"
      else
        echo "(might have been an error posting this line: $line)"
      fi
      ;;
      esac
    done;
    test "$testing" = "no" && (echo '-'; date; cat $file) >>$ARCHIVE
  else
    echo "NOT posting!"
  fi

}

send.reverse() {
  send reverse
}

ask() {
  echo '--------------'
  cat $1
  echo '--------------'
  echo -n "Post to twitter? [y] "
  read r
  case "$r" in
  n*|N*) return 1;;
  *) return 0;;
  esac
}

test.send() {
  send test
}
test.send.dry() {
  send dry
}

test.send.reverse() {
  send test reverse
}
test.send.reverse.dry() {
  send dry reverse
}

test.entities() {
 echo "><" | $html_entities
 echo 'should be: &gt;&lt;'
}



-- end of file

-- 
Daniel Bush
-- 
SLUG - Sydney Linux User's Group Mailing List - http://slug.org.au/
Subscription info and FAQs: http://slug.org.au/faq/mailinglists.html

Reply via email to