X-Git-Url: https://vcs.fsf.org/?p=rainbowstream.git;a=blobdiff_plain;f=rainbowstream%2Frainbow.py;h=14e469ed093944efb353d01b31f32044dc79a46b;hp=765ce389d6eb03ff7841ffa5e0436d8e4551e32e;hb=bf766c7b94931dc3d0f32ecb6aea79208a6e412a;hpb=eb9b6273dc3f382b20ee055dc7ed4d3116532874 diff --git a/rainbowstream/rainbow.py b/rainbowstream/rainbow.py index 765ce38..14e469e 100644 --- a/rainbowstream/rainbow.py +++ b/rainbowstream/rainbow.py @@ -9,7 +9,10 @@ import requests import webbrowser import traceback import pkg_resources +import socks +import socket +from io import BytesIO from twitter.stream import TwitterStream, Timeout, HeartbeatTimeout, Hangup from twitter.api import * from twitter.oauth import OAuth, read_token_file @@ -58,9 +61,48 @@ def parse_arguments(): '--image-on-term', action='store_true', help='Display all image on terminal.') + parser.add_argument( + '-ph', + '--proxy-host', + help='Use HTTP/SOCKS proxy for network connections.') + parser.add_argument( + '-pp', + '--proxy-port', + default=8080, + help='HTTP/SOCKS proxy port (Default: 8080).') + parser.add_argument( + '-pt', + '--proxy-type', + default='SOCKS5', + help='Proxy type (HTTP, SOCKS4, SOCKS5; Default: SOCKS5).') return parser.parse_args() +def proxy_connect(args): + """ + Connect to specified proxy + """ + if args.proxy_host: + # Setup proxy by monkeypatching the standard lib + if args.proxy_type.lower() == "socks5" or not args.proxy_type: + socks.set_default_proxy( + socks.SOCKS5, args.proxy_host, + int(args.proxy_port)) + elif args.proxy_type.lower() == "http": + socks.set_default_proxy( + socks.HTTP, args.proxy_host, + int(args.proxy_port)) + elif args.proxy_type.lower() == "socks4": + socks.set_default_proxy( + socks.SOCKS4, args.proxy_host, + int(args.proxy_port)) + else: + printNicely( + magenta("Sorry, wrong proxy type specified! Aborting...")) + sys.exit() + socket.socket = socks.socksocket + + def authen(): """ Authenticate with Twitter OAuth @@ -136,6 +178,8 @@ def upgrade_center(): notice += light_magenta('You should upgrade with ') notice += light_green('pip install -U rainbowstream') printNicely(notice) + else: + printNicely(yellow('You are runnig latest ' + current + ' version.')) except: pass @@ -183,6 +227,13 @@ def init(args): # Image on term c['IMAGE_ON_TERM'] = args.image_on_term set_config('IMAGE_ON_TERM', str(c['IMAGE_ON_TERM'])) + # Check type of ONLY_LIST and IGNORE_LIST + if not isinstance(c['ONLY_LIST'], list): + printNicely(red('ONLY_LIST is not a valid list value.')) + c['ONLY_LIST'] = [] + if not isinstance(c['IGNORE_LIST'], list): + printNicely(red('IGNORE_LIST is not a valid list value.')) + c['IGNORE_LIST'] = [] # Mute dict c['IGNORE_LIST'] += build_mute_dict() @@ -489,10 +540,10 @@ def share(): t = Twitter(auth=authen()) try: id = int(g['stuff'].split()[0]) + tid = c['tweet_dict'][id] except: - printNicely(red('Sorry I can\'t understand.')) + printNicely(red('Tweet id is not valid.')) return - tid = c['tweet_dict'][id] tweet = t.statuses.show(id=tid) url = 'https://twitter.com/' + \ tweet['user']['screen_name'] + '/status/' + str(tid) @@ -903,7 +954,7 @@ def list_home(t): owner_screen_name=owner, count=c['LIST_MAX'], include_entities=False) - for tweet in res: + for tweet in reversed(res): draw(t=tweet) printNicely('') @@ -1177,9 +1228,6 @@ def switch(): ignore = raw_input('Ignore nicks [Ex: @xxx,@yy]: ') args.filter = filter(None, only.split(',')) args.ignore = filter(None, ignore.split(',')) - elif g['stuff'].split()[-1] == '-d': - args.filter = c['ONLY_LIST'] - args.ignore = c['IGNORE_LIST'] except: printNicely(red('Sorry, wrong format.')) return @@ -1191,6 +1239,8 @@ def switch(): # Kill old thread g['stream_stop'] = True args.track_keywords = keyword + # Reset prefix + g['PREFIX'] = u2str(emojize(c['PREFIX'])) # Start new thread th = threading.Thread( target=stream, @@ -1203,6 +1253,8 @@ def switch(): elif target == 'mine': # Kill old thread g['stream_stop'] = True + # Reset prefix + g['PREFIX'] = u2str(emojize(c['PREFIX'])) # Start new thread th = threading.Thread( target=stream, @@ -1216,7 +1268,7 @@ def switch(): elif target == 'list': owner, slug = get_slug() # Force python 2 not redraw readline buffer - g['cmd'] = '/'.join([owner, slug]) + g['PREFIX'] = g['cmd'] = '/'.join([owner, slug]) printNicely(light_yellow('getting list members ...')) # Get members t = Twitter(auth=authen()) @@ -1251,7 +1303,7 @@ def switch(): if args.ignore: printNicely(red('Ignore: ' + str(len(args.ignore)) + ' people.')) printNicely('') - except Exception: + except: debug_option() printNicely(red('Sorry I can\'t understand.')) @@ -1326,16 +1378,18 @@ def config(): value = get_default_config(key) line = ' ' * 2 + green(key) + ': ' + light_magenta(value) printNicely(line) - except Exception as e: - printNicely(red(e)) + except: + debug_option() + printNicely(red('Just can not get the default.')) # Delete specific config key in config file elif len(g['stuff'].split()) == 2 and g['stuff'].split()[-1] == 'drop': key = g['stuff'].split()[0] try: delete_config(key) printNicely(green('Config key is dropped.')) - except Exception as e: - printNicely(red(e)) + except: + debug_option() + printNicely(red('Just can not drop the key.')) # Set specific config elif len(g['stuff'].split()) == 3 and g['stuff'].split()[1] == '=': key = g['stuff'].split()[0] @@ -1345,15 +1399,18 @@ def config(): return try: set_config(key, value) - # Apply theme immediately + # Keys that needs to be apply immediately if key == 'THEME': c['THEME'] = reload_theme(value, c['THEME']) g['decorated_name'] = lambda x: color_func( c['DECORATED_NAME'])('[' + x + ']: ') + elif key == 'PREFIX': + g['PREFIX'] = u2str(emojize(c['PREFIX'])) reload_config() printNicely(green('Updated successfully.')) - except Exception as e: - printNicely(red(e)) + except: + debug_option() + printNicely(red('Just can not set the key.')) else: printNicely(light_magenta('Sorry I can\'s understand.')) @@ -1417,8 +1474,8 @@ def help_tweets(): light_green('ufav 12 ') + ' will unfavorite tweet with ' + \ light_yellow('[id=12]') + '.\n' usage += s * 2 + \ - light_green('share 12 ') + ' will copy the url of the tweet with ' + \ - light_yellow('[id=12]') + ' to your clipboard.\n' + light_green('share 12 ') + ' will get the direct link of the tweet with ' + \ + light_yellow('[id=12]') + '.\n' usage += s * 2 + \ light_green('del 12 ') + ' will delete tweet with ' + \ light_yellow('[id=12]') + '.\n' @@ -1536,8 +1593,6 @@ def help_stream(): ' filter will decide nicks will be INCLUDE ONLY.\n' usage += s * 3 + light_yellow('Ignore nicks') + \ ' filter will decide nicks will be EXCLUDE.\n' - usage += s * 2 + light_green('switch mine -d') + \ - ' will use the config\'s ONLY_LIST and IGNORE_LIST.\n' usage += s * 2 + light_green('switch list') + \ ' will switch to a Twitter list\'s stream. You will be asked for list name\n' printNicely(usage) @@ -1725,7 +1780,8 @@ cmdset = [ 'p', 'r', 'c', - 'q' + 'q', + 'version', ] # Handle function set @@ -1771,7 +1827,8 @@ funcset = [ pause, replay, clear, - quit + quit, + upgrade_center, ] @@ -1944,6 +2001,7 @@ def stream(domain, args, name='Rainbow Stream'): # Block new stream until other one exits StreamLock.acquire() g['stream_stop'] = False + last_tweet_time = time.time() for tweet in tweet_iter: if tweet is None: printNicely("-- None --") @@ -1964,6 +2022,10 @@ def stream(domain, args, name='Rainbow Stream'): StreamLock.release() break elif tweet.get('text'): + # Slow down the stream by STREAM_DELAY config key + if time.time() - last_tweet_time < c['STREAM_DELAY']: + continue + last_tweet_time = time.time() # Check the semaphore pause and lock (stream process only) if g['pause']: continue @@ -2013,7 +2075,9 @@ def fly(): # Initial args = parse_arguments() try: + proxy_connect(args) init(args) + # Twitter API connection problem except TwitterHTTPError: printNicely('') printNicely( @@ -2021,6 +2085,15 @@ def fly(): printNicely(magenta("Let's try again later.")) save_history() sys.exit() + # Proxy connection problem + except (socks.ProxyConnectionError, URLError): + printNicely( + magenta("There seems to be a connection problem.")) + printNicely( + magenta("You might want to check your proxy settings (host, port and type)!")) + save_history() + sys.exit() + # Spawn stream thread th = threading.Thread( target=stream,