Permalink
Browse files

First release

  • Loading branch information...
1 parent 7387428 commit 42ee32e2ca26cd43b743647fe0c6b677520cf8f7 Gregory Haskins committed Apr 4, 2011
Showing with 186 additions and 0 deletions.
  1. +48 −0 Makefile
  2. +71 −0 README.markdown
  3. +67 −0 tweet.py
View
@@ -0,0 +1,48 @@
+# Build an executable, standalone version of tweet.py using PyInstaller
+
+
+# These settings may change based on your system:
+# -----------------------------------------------------------------------------
+# The python interpreter
+PY = python
+
+# Executable file extension
+# POSIX: BINARY_EXT =
+# Windows: BINARY_EXT = .exe
+BINARY_EXT = .exe
+
+# The PyInstaller directory
+PYINST = pyinstaller-1.5-rc1
+# -----------------------------------------------------------------------------
+
+
+# PyInstaller scripts
+CONFIGURE = $(PYINST)/Configure.py
+CONFIGDAT = $(PYINST)/config.dat
+MAKESPEC = $(PYINST)/Makespec.py
+BUILDER = $(PYINST)/Build.py
+
+# BASENAME is the name of the python script
+BASENAME = tweet
+SOURCE = $(BASENAME).py
+SPECFILE = $(BASENAME).spec
+
+# compiled binary path
+BINARY = dist/$(BASENAME)$(BINARY_EXT)
+
+# output files created during build
+OUTFILES = build dist warn$(BASENAME).txt $(SPECFILE) *.log
+
+build: $(BINARY)
+
+$(BINARY): $(SPECFILE) $(CONFIGDAT)
+ $(PY) "$(BUILDER)" "$(SPECFILE)"
+
+$(CONFIGDAT):
+ $(PY) "$(CONFIGURE)"
+
+$(SPECFILE): $(SOURCE) $(CONFIGDAT)
+ $(PY) "$(MAKESPEC)" --onefile "$@"
+
+clean:
+ rm -rfv $(OUTFILES)
View
@@ -0,0 +1,71 @@
+Introduction
+============
+
+`cmdline_tweet` is a simple Python application that allows you to send messages
+to a Twitter account from the command line. It extends on the examples from
+Jeff Miller's [tutorial on the subject][1] by improving reusability since the
+same tool handles both authorization and tweeting.
+
+This tool allows you to create command-line programs tied to a single Twitter
+account with all the authorization, etc., handled behind the scenes.
+
+Setup
+=====
+
+Using `cmdline_tweet` first requires [registering an app with Twitter][2] to
+obtain an OAuth consumer key and secret. This is a one-time step, so just open
+up `tweet.py` and replace `__CONSUMER_KEY__` and `__CONSUMER_SECRET__` with
+your strings and forget about it.
+
+The included `Makefile` may be used to bundle `tweet.py` into a standalone
+binary with [PyInstaller][3], and only requires
+specifying the paths to PyInstaller and the Python executable on your system.
+Having standalone binaries can be helpful when deploying to machines without
+Python installed.
+
+Usage
+=====
+
+Each script/executable is tied to a single Twitter account, and all it does
+is send a tweet on behalf of that account. This can be useful for server logs
+or monitoring other automated processes. Or, simply issuing tweets without
+leaving the comfort of the shell environment.
+
+When first run, the program checks for a configuration file with the same name
+and path as itself. For instance, if the script was `/path/to/tweet.py`, then
+it would look for `/path/to/tweet.py.cfg`. If that file is invalid or can't be
+found, then the program opens up a browser window for you to authorize it with
+your Twitter credentials. Once that step is complete, tweeting is as simple as:
+
+ ./tweet.py "All your base are belong to us"
+
+If everything succeeds, the tweet will be posted and the script exits with no
+output. If there was an error (e.g. repeat tweet, network failure), it will be
+printed to standard output. Deleting the `.cfg` file or renaming the executable
+will re-trigger the setup process. This makes it possible to have several
+scripts which tweet to different accounts live side-by-side without conflict.
+
+If you'll be using the script in a headless/server environment, you'll want to
+copy the `.cfg` file from another machine with web browsing capabilities.
+
+Dependencies
+============
+
+- Python >= 2.7 (only minor changes required for further compatibility)
+- [tweepy][4]
+
+[1]: http://jeffmiller.github.com/2010/05/31/twitter-from-the-command-line-in-python-using-oauth
+[2]: http://dev.twitter.com/apps
+[3]: http://www.pyinstaller.org/
+[4]: https://github.com/joshthecoder/tweepy
+
+TODO
+====
+
+Ideas for future improvement:
+
+- Better backwards/forwards compatibility
+- Have `Makefile` call `sed` to replace the appropriate, app-specific params?
+- Integrate consumer key/secret into config file instead of hard-coding?
+- Tweet to multiple accounts with same script/executable? (e.g. `./tweet.py
+ ACCTNAME MESSAGE`)
View
@@ -0,0 +1,67 @@
+#!/usr/bin/env python
+"""A simple, reusable command-line twitter client.
+
+Inspired by the example from Jeff Miller at:
+http://jeffmiller.github.com/2010/05/31/twitter-from-the-command-line-in-python-using-oauth
+
+"""
+
+import os
+import sys
+import webbrowser
+import ConfigParser
+
+import tweepy
+
+CONSUMER_KEY = '__CONSUMER_KEY__'
+CONSUMER_SECRET = '__CONSUMER_SECRET__'
+CONFIG_FILE = os.path.join(os.path.dirname(__file__),
+ "{}.cfg".format(sys.argv[0]))
+
+def tweet(message, access_key, access_secret):
+ auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
+ auth.set_access_token(access_key, access_secret)
+ api = tweepy.API(auth)
+ try:
+ api.update_status(sys.argv[1])
+ except tweepy.error.TweepError as e:
+ print e
+ sys.exit(1)
+
+def setup():
+ auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
+ auth_url = auth.get_authorization_url()
+ print "Opening Twitter to get user authorization..."
+ print auth_url
+ webbrowser.open(auth_url)
+
+ verifier = raw_input('Verification PIN: ').strip()
+ auth.get_access_token(verifier)
+
+ config = ConfigParser.RawConfigParser()
+ config.add_section('OAuth')
+ config.set('OAuth', 'access_key', auth.access_token.key)
+ config.set('OAuth', 'access_secret', auth.access_token.secret)
+ with open(CONFIG_FILE, 'wb') as f:
+ config.write(f)
+
+ print "Setup complete."
+ print "You may now tweet using: {} MESSAGE\n".format(sys.argv[0])
+
+
+if __name__ == '__main__':
+ config = ConfigParser.RawConfigParser()
+ config.read(CONFIG_FILE)
+ try:
+ access_key = config.get('OAuth', 'access_key')
+ access_secret = config.get('OAuth', 'access_secret')
+ except ConfigParser.Error:
+ print "Bad/missing settings file '{}'".format(CONFIG_FILE)
+ setup()
+ sys.exit()
+ if len(sys.argv) > 1:
+ tweet(' '.join(sys.argv[1:]), access_key, access_secret)
+ else:
+ print "usage: {} MESSAGE\n".format(sys.argv[0])
+ print "Settings are read from '{}'".format(CONFIG_FILE)
+ print "Deleting this file will reset the current configuration"

0 comments on commit 42ee32e

Please sign in to comment.