]> jfr.im git - z_archive/twitter.git/blobdiff - twitter/cmdline.py
Merge branch 'invert'
[z_archive/twitter.git] / twitter / cmdline.py
index c627a5e1b4d01e7decec451aa533f95b9d65ad05..aafe262b8279f90c74bad2e7a35491895ae9ec6a 100644 (file)
@@ -22,6 +22,7 @@ ACTIONS:
  search         search twitter (Beware: octothorpe, escape it)
  set            set your twitter status
  shell          login to the twitter shell
+ rate           get your current rate limit status (remaining API reqs)
 
 
 OPTIONS:
@@ -61,6 +62,8 @@ prompt: <twitter_shell_prompt e.g. '[cyan]twitter[R]> '>
  home directory.
 """
 
+from __future__ import print_function
+
 CONSUMER_KEY='uS6hO2sV6tDKIOeVjhnFnQ'
 CONSUMER_SECRET='MEYTOS97VvlHX7K1rwHPEqVpTSqZ71HtvoK4sVuYk'
 
@@ -70,16 +73,25 @@ from getopt import gnu_getopt as getopt, GetoptError
 from getpass import getpass
 import re
 import os.path
-from configparser import SafeConfigParser
+import locale
+import string
+
+try:
+    from ConfigParser import SafeConfigParser
+except ImportError:
+    from configparser import ConfigParser as SafeConfigParser
 import datetime
-from urllib.parse import quote
+try:
+    from urllib.parse import quote
+except ImportError:
+    from urllib2 import quote
 import webbrowser
 
 from .api import Twitter, TwitterError
 from .oauth import OAuth, write_token_file, read_token_file
 from .oauth_dance import oauth_dance
 from . import ansi
-from .util import smrt_input
+from .util import smrt_input, printNicely
 
 OPTIONS = {
     'action': 'friends',
@@ -94,6 +106,7 @@ OPTIONS = {
     'datestamp': False,
     'extra_args': [],
     'secure': True,
+    'invert_split': False,
 }
 
 def parse_args(args, options):
@@ -102,6 +115,8 @@ def parse_args(args, options):
                  'datestamp', 'no-ssl']
     short_opts = "e:p:f:h?rR:c:l:td"
     opts, extra_args = getopt(args, short_opts, long_opts)
+    extra_args = [arg.decode(locale.getpreferredencoding())
+                  for arg in extra_args]
 
     for opt, arg in opts:
         if opt in ('-f', '--format'):
@@ -338,6 +353,7 @@ class Action(object):
             if (options['refresh'] and isinstance(action, StatusAction)):
                 while True:
                     doAction()
+                    sys.stdout.flush()
                     time.sleep(options['refresh_rate'])
             else:
                 doAction()
@@ -352,10 +368,6 @@ class NoSuchAction(Action):
     def __call__(self, twitter, options):
         raise NoSuchActionError("No such action: %s" %(options['action']))
 
-def printNicely(string):
-    sys.stdout.buffer.write(string.encode('utf8'))
-    print()
-
 class StatusAction(Action):
     def __call__(self, twitter, options):
         statuses = self.getStatuses(twitter, options)
@@ -454,7 +466,35 @@ class SetStatusAction(Action):
         statusTxt = (" ".join(options['extra_args'])
                      if options['extra_args']
                      else str(input("message: ")))
-        twitter.statuses.update(status=statusTxt)
+        replies = []
+        ptr = re.compile("@[\w_]+")
+        while statusTxt:
+            s = ptr.match(statusTxt)
+            if s and s.start() == 0:
+                replies.append(statusTxt[s.start():s.end()])
+                statusTxt = statusTxt[s.end()+1:]
+            else:
+                break
+        replies = " ".join(replies)
+        if len(replies) >= 140:
+            # just go back
+            statusTxt = replies
+            replies = ""
+
+        splitted = []
+        while statusTxt:
+            limit = 140 - len(replies)
+            if len(statusTxt) > limit:
+                end = string.rfind(statusTxt, ' ', 0, limit)
+            else:
+                end = limit
+            splitted.append(" ".join((replies,statusTxt[:end])))
+            statusTxt = statusTxt[end:]
+
+        if options['invert_split']:
+            splitted.reverse()
+        for status in splitted:
+            twitter.statuses.update(status=status)
 
 class TwitterShell(Action):
 
@@ -519,6 +559,13 @@ class DoNothingAction(Action):
     def __call__(self, twitter, options):
         pass
 
+class RateLimitStatus(Action):
+    def __call__(self, twitter, options):
+        rate = twitter.account.rate_limit_status()
+        print("Remaining API requests: %s / %s (hourly limit)" % (rate['remaining_hits'], rate['hourly_limit']))
+        print("Next reset in %ss (%s)" % (int(rate['reset_time_in_seconds']-time.time()),
+                                          time.asctime(time.localtime(rate['reset_time_in_seconds']))))
+
 actions = {
     'authorize' : DoNothingAction,
     'follow'    : FollowAction,
@@ -533,6 +580,7 @@ actions = {
     'search'    : SearchAction,
     'set'       : SetStatusAction,
     'shell'     : TwitterShell,
+    'rate'      : RateLimitStatus,
 }
 
 def loadConfig(filename):
@@ -543,6 +591,10 @@ def loadConfig(filename):
         for option in ('format', 'prompt'):
             if cp.has_option('twitter', option):
                 options[option] = cp.get('twitter', option)
+        # process booleans
+        for option in ('invert_split',):
+            if cp.has_option('twitter', option ):
+                options[option] = cp.getboolean('twitter', option)
     return options
 
 def main(args=sys.argv[1:]):