ACTIONS:
follow add the specified user to your follow list
friends get latest tweets from your friends (default action)
- leave remove the specified user from your following list
+ help print this help text that you are currently reading
+ leave remove the specified user from your following list
public get latest public tweets
replies get latest replies
set set your twitter status
default one line per status
verbose multiple lines per status, more verbose status info
urls nothing but URLs. Dare you click them?
-
+
CONFIG FILES
- The config file should contain your email and password like so:
+ The config file should contain a [twitter] header, your email and password
+ like so:
[twitter]
email: <username>
import sys
import time
-from getopt import getopt
+from getopt import getopt, GetoptError
from getpass import getpass
import re
import os.path
from api import Twitter, TwitterError
+# Please don't change this, it was provided by the fine folks at Twitter.
+# If you change it, it will not work.
+AGENT_STR = "twittercommandlinetoolpy"
+
options = {
'email': None,
'password': None,
long_opts = ['email', 'password', 'help', 'format', 'refresh',
'refresh-rate', 'config']
short_opts = "e:p:f:h?rR:c:"
- opts, extra_args = getopt(args, short_opts, long_opts)
-
+ opts, extra_args = getopt(args, short_opts, long_opts)
+
for opt, arg in opts:
if opt in ('-e', '--email'):
options['email'] = arg
sys.exit(0)
elif opt in ('-c', '--config'):
options['config_filename'] = arg
-
+
if extra_args:
options['action'] = extra_args[0]
options['extra_args'] = extra_args[1:]
return u'\n'.join(urls) if urls else ""
class AdminFormatter(object):
- def __call__(self, action, user):
- return(u"%s: %s" %(
- "Following" if action == "follow" else "Leaving", user['name']))
-
+ def __call__(self, action, user):
+ user_str = u"%s (%s)" %(user['screen_name'], user['name'])
+ if action == "follow":
+ return u"You are now following %s.\n" %(user_str)
+ else:
+ return u"You are no longer following %s.\n" %(user_str)
+
class VerboseAdminFormatter(object):
- def __call__(self, action, user):
- return(u"-- %s: %s (%s): %s" % (
- "Following" if action == "follow" else "Leaving",
- user['screen_name'],
- user['name'],
- user['url']))
-
+ def __call__(self, action, user):
+ return(u"-- %s: %s (%s): %s" % (
+ "Following" if action == "follow" else "Leaving",
+ user['screen_name'],
+ user['name'],
+ user['url']))
+
class URLAdminFormatter(object):
- def __call__(self, action, user):
- return("Admin actions do not support the URL formatter")
+ def __call__(self, action, user):
+ return("Admin actions do not support the URL formatter")
status_formatters = {
'default': StatusFormatter,
}
admin_formatters = {
- 'default': AdminFormatter,
- 'verbose': VerboseAdminFormatter,
- 'urls': URLAdminFormatter
+ 'default': AdminFormatter,
+ 'verbose': VerboseAdminFormatter,
+ 'urls': URLAdminFormatter
}
-
+
def get_status_formatter(options):
sf = status_formatters.get(options['format'])
if (not sf):
return sf()
def get_admin_formatter(options):
- sf = admin_formatters.get(options['format'])
- if (not sf):
- raise TwitterError(
- "Unknown formatter '%s'" %(options['format']))
- return sf()
-
+ sf = admin_formatters.get(options['format'])
+ if (not sf):
+ raise TwitterError(
+ "Unknown formatter '%s'" %(options['format']))
+ return sf()
+
class Action(object):
pass
print statusStr.encode(sys.stdout.encoding, 'replace')
class AdminAction(Action):
- def __call__(self, twitter, options):
- if (not options['extra_args'][0]):
- raise TwitterError("You need to specify a User (Screen Name)")
- af = get_admin_formatter(options)
- user = self.getUser(twitter, options['extra_args'][0])
- if(user):
- print af(options['action'], user).encode(sys.stdout.encoding, 'replace')
-
+ def __call__(self, twitter, options):
+ if not options['extra_args'][0]:
+ raise TwitterError("You need to specify a user (screen name)")
+ af = get_admin_formatter(options)
+ try:
+ user = self.getUser(twitter, options['extra_args'][0])
+ except TwitterError, e:
+ print "There was a problem following or leaving the specified user."
+ print " You may be trying to follow a user you are already following;"
+ print " Leaving a user you are not currently following;"
+ print " Or the user may not exist."
+ print " Sorry."
+ print
+ print e
+ else:
+ print af(options['action'], user).encode(sys.stdout.encoding, 'replace')
+
class FriendsAction(StatusAction):
def getStatuses(self, twitter):
return reversed(twitter.statuses.friends_timeline())
-
+
class PublicAction(StatusAction):
def getStatuses(self, twitter):
return reversed(twitter.statuses.public_timeline())
return reversed(twitter.statuses.replies())
class FollowAction(AdminAction):
- def getUser(self, twitter, user):
- # Twitter wants /notifications/follow/user.json?id=user
- return twitter.notifications.follow.__getattr__(user)(id=user)
-
+ def getUser(self, twitter, user):
+ return twitter.notifications.follow(id=user)
+
class LeaveAction(AdminAction):
- def getUser(self, twitter, user):
- return twitter.notifications.leave.__getattr__(user)(id=user)
+ def getUser(self, twitter, user):
+ return twitter.notifications.leave(id=user)
class SetStatusAction(Action):
def __call__(self, twitter, options):
status = (statusTxt.encode('utf8', 'replace'))
twitter.statuses.update(status=status)
+class HelpAction(Action):
+ def __call__(self, twitter, options):
+ print __doc__
+
actions = {
- 'follow': FollowAction,
+ 'follow': FollowAction,
'friends': FriendsAction,
+ 'help': HelpAction,
'leave': LeaveAction,
'public': PublicAction,
'replies': RepliesAction,
def main():
return main_with_args(sys.argv[1:])
-
+
def main_with_args(args):
- parse_args(args, options)
+ try:
+ parse_args(args, options)
+ except GetoptError, e:
+ print >> sys.stderr, "I can't do that, %s." %(e)
+ print >> sys.stderr
+ sys.exit(1)
email, password = loadConfig(options['config_filename'])
if not options['email']: options['email'] = email
if not options['password']: options['password'] = password
-
- #Maybe check for AdminAction here, but whatever you do, don't write TODO
- if options['refresh'] and options['action'] == 'set':
- print >> sys.stderr, "You can't repeatedly set your status, silly"
+
+ if options['refresh'] and options['action'] not in (
+ 'friends', 'public', 'replies'):
+ print >> sys.stderr, "You can only refresh the friends, public, or replies actions."
print >> sys.stderr, "Use 'twitter -h' for help."
sys.exit(1)
+
if options['email'] and not options['password']:
options['password'] = getpass("Twitter password: ")
- twitter = Twitter(options['email'], options['password'])
+
+ twitter = Twitter(options['email'], options['password'], agent=AGENT_STR)
action = actions.get(options['action'], NoSuchAction)()
+
try:
doAction = lambda : action(twitter, options)
-
+
if (options['refresh'] and isinstance(action, StatusAction)):
- while True:
- doAction()
- time.sleep(options['refresh_rate'])
+ while True:
+ doAction()
+ time.sleep(options['refresh_rate'])
else:
- doAction()
-
+ doAction()
+
except TwitterError, e:
print >> sys.stderr, e.args[0]
print >> sys.stderr, "Use 'twitter -h' for help."
sys.exit(1)
except KeyboardInterrupt:
pass
-
+