]> jfr.im git - z_archive/twitter.git/blobdiff - twitter/archiver.py
Improve OAuth2 app-only code and documentation
[z_archive/twitter.git] / twitter / archiver.py
index 1be6d6d217004bda793c24e412a4524a76ea1ab0..ef2dc1fb882a30a47ed0f26e277841cf25debca4 100644 (file)
@@ -97,8 +97,11 @@ def load_tweets(filename):
 
     tweets = {}
     for line in archive.readlines():
-        tid, text = line.strip().split(" ", 1)
-        tweets[int(tid)] = text.decode("utf-8")
+        try:
+            tid, text = line.strip().split(" ", 1)
+            tweets[int(tid)] = text.decode("utf-8")
+        except Exception as e:
+            err("loading tweet %s failed due to %s" % (line, unicode(e)))
 
     archive.close()
     return tweets
@@ -125,7 +128,10 @@ def save_tweets(filename, tweets):
         return
 
     for k in sorted(tweets.keys()):
-        archive.write("%i %s\n" % (k, tweets[k].encode('utf-8')))
+        try:
+            archive.write("%i %s\n" % (k, tweets[k].encode('utf-8')))
+        except Exception as ex:
+            err("archiving tweet %s failed due to %s" % (k, unicode(ex)))
 
     archive.close()
 
@@ -133,11 +139,14 @@ def format_date(utc, isoformat=False):
     """Parse Twitter's UTC date into UTC or local time."""
     u = datetime.strptime(utc.replace('+0000','UTC'), '%a %b %d %H:%M:%S %Z %Y')
     # This is the least painful way I could find to create a non-naive
-    # datetime that included a timezone of UTC. Alternative suggestions
+    # datetime including a UTC timezone. Alternative suggestions
     # welcome.
     unew = datetime.combine(u.date(), time(u.time().hour,
         u.time().minute, u.time().second, tzinfo=UTC))
 
+    # Convert to localtime
+    unew = unew.astimezone(Local)
+
     if isoformat:
         return unew.isoformat()
     else:
@@ -239,15 +248,15 @@ def statuses(twitter, screen_name, tweets, mentions=False, favorites=False, rece
                 err("Fail: %i Unauthorized (tweets of that user are protected)"
                     % e.e.code)
                 break
-            elif e.e.code == 400:
+            elif e.e.code == 429:
                 err("Fail: %i API rate limit exceeded" % e.e.code)
-                rate = twitter.account.rate_limit_status()
-                reset = rate['reset_time_in_seconds']
-                reset = time.asctime(time.localtime(reset))
-                delay = int(rate['reset_time_in_seconds']
-                            - time.time()) + 5 # avoid race
-                err("Hourly limit of %i requests reached, next reset on %s: "
-                    "going to sleep for %i secs" % (rate['hourly_limit'],
+                rls = twitter.application.rate_limit_status()
+                reset = rls.rate_limit_reset
+                reset = _time.asctime(_time.localtime(reset))
+                delay = int(rls.rate_limit_reset
+                            - _time.time()) + 5 # avoid race
+                err("Interval limit of %i requests reached, next reset on %s: "
+                    "going to sleep for %i secs" % (rls.rate_limit_limit,
                                                     reset, delay))
                 fail.wait(delay)
                 continue
@@ -282,12 +291,12 @@ def statuses(twitter, screen_name, tweets, mentions=False, favorites=False, rece
 
 def rate_limit_status(twitter):
     """Print current Twitter API rate limit status."""
-    r = twitter.account.rate_limit_status()
-    print("Remaining API requests: %i/%i (hourly limit)"
-          % (r['remaining_hits'], r['hourly_limit']))
+    rls = twitter.application.rate_limit_status()
+    print("Remaining API requests: %i/%i (interval limit)"
+          % (rls.rate_limit_remaining, rls.rate_limit_limit))
     print("Next reset in %is (%s)"
-          % (int(r['reset_time_in_seconds'] - time.time()),
-             time.asctime(time.localtime(r['reset_time_in_seconds']))))
+          % (int(rls.rate_limit_reset - _time.time()),
+             _time.asctime(_time.localtime(rls.rate_limit_reset))))
 
 def main(args=sys.argv[1:]):
     options = {
@@ -319,8 +328,11 @@ def main(args=sys.argv[1:]):
 
     # authenticate using OAuth, asking for token if necessary
     if options['oauth']:
-        oauth_filename = (os.getenv("HOME", "") + os.sep
-                          + ".twitter-archiver_oauth")
+        oauth_filename = (os.environ.get('HOME', 
+                          os.environ.get('USERPROFILE', '')) 
+                          + os.sep
+                          + '.twitter-archiver_oauth')
+        
         if not os.path.exists(oauth_filename):
             oauth_dance("Twitter-Archiver", CONSUMER_KEY, CONSUMER_SECRET,
                         oauth_filename)