X-Git-Url: https://vcs.fsf.org/?p=rainbowstream.git;a=blobdiff_plain;f=rainbowstream%2Frainbow.py;h=53fcd639f4ef2b83929f899fa74a53a8d8c3b879;hp=7480e2a566402399f9c5236187c131cb6594da13;hb=bb68c6872988e8bcb1f125dc86dba67ceb8a1415;hpb=742266f882369a1a617aebc63190c7a61ba7815a diff --git a/rainbowstream/rainbow.py b/rainbowstream/rainbow.py index 7480e2a..53fcd63 100644 --- a/rainbowstream/rainbow.py +++ b/rainbowstream/rainbow.py @@ -27,7 +27,7 @@ from .interactive import * from .c_image import * from .py3patch import * from .emoji import * -from .util import printTwitterErrors +from .util import * # Global values g = {} @@ -41,6 +41,11 @@ def parse_arguments(): Parse the arguments """ parser = argparse.ArgumentParser(description=__doc__ or "") + parser.add_argument( + '-s', + '--stream', + default="mine", + help='Default stream after program start. (Default: mine)') parser.add_argument( '-to', '--timeout', @@ -99,7 +104,7 @@ def proxy_connect(args): int(args.proxy_port)) else: printNicely( - magenta("Sorry, wrong proxy type specified! Aborting...")) + magenta('Sorry, wrong proxy type specified! Aborting...')) sys.exit() socket.socket = socks.socksocket @@ -115,7 +120,7 @@ def authen(): 'USERPROFILE', '')) + os.sep + '.rainbow_oauth' if not os.path.exists(twitter_credential): - oauth_dance("Rainbow Stream", + oauth_dance('Rainbow Stream', CONSUMER_KEY, CONSUMER_SECRET, twitter_credential) @@ -167,10 +172,10 @@ def upgrade_center(): Check latest and notify to upgrade """ try: - current = pkg_resources.get_distribution("rainbowstream").version + current = pkg_resources.get_distribution('rainbowstream').version url = 'https://raw.githubusercontent.com/DTVD/rainbowstream/master/setup.py' readme = requests.get(url).text - latest = readme.split("version = \'")[1].split("\'")[0] + latest = readme.split('version = \'')[1].split('\'')[0] if current != latest: notice = light_magenta('RainbowStream latest version is ') notice += light_green(latest) @@ -179,6 +184,11 @@ def upgrade_center(): notice += light_magenta('You should upgrade with ') notice += light_green('pip install -U rainbowstream') printNicely(notice) + else: + notice = light_yellow('You are running latest version (') + notice += light_green(current) + notice += light_yellow(')') + printNicely(notice) except: pass @@ -197,11 +207,9 @@ def init(args): credential = t.account.verify_credentials() screen_name = '@' + credential['screen_name'] name = credential['name'] - if not get_config('PREFIX'): - set_config('PREFIX', screen_name) - c['PREFIX'] = emojize(c['PREFIX']) - g['PREFIX'] = u2str(c['PREFIX']) c['original_name'] = g['original_name'] = screen_name[1:] + g['listname'] = g['keyword'] = '' + g['PREFIX'] = u2str(emojize(format_prefix())) g['full_name'] = name g['decorated_name'] = lambda x: color_func( c['DECORATED_NAME'])('[' + x + ']: ', rl=True) @@ -316,7 +324,11 @@ def whois(): Show profile of a specific user """ t = Twitter(auth=authen()) - screen_name = g['stuff'].split()[0] + try: + screen_name = g['stuff'].split()[0] + except: + printNicely(red('Sorry I can\'t understand.')) + return if screen_name.startswith('@'): try: user = t.users.show( @@ -335,7 +347,11 @@ def view(): Friend view """ t = Twitter(auth=authen()) - user = g['stuff'].split()[0] + try: + user = g['stuff'].split()[0] + except: + printNicely(red('Sorry I can\'t understand.')) + return if user[0] == '@': try: num = int(g['stuff'].split()[1]) @@ -356,6 +372,9 @@ def search(): t = Twitter(auth=authen()) # Setup query query = g['stuff'].strip() + if not query: + printNicely(red('Sorry I can\'t understand.')) + return type = c['SEARCH_TYPE'] if type not in ['mixed', 'recent', 'popular']: type = 'mixed' @@ -498,6 +517,29 @@ def reply(): t.statuses.update(status=status, in_reply_to_status_id=tid) +def reply_all(): + """ + Reply to all + """ + t = Twitter(auth=authen()) + try: + id = int(g['stuff'].split()[0]) + except: + printNicely(red('Sorry I can\'t understand.')) + return + tid = c['tweet_dict'][id] + original_tweet = t.statuses.show(id=tid) + text = original_tweet['text'] + nick_ary = [original_tweet['user']['screen_name']] + for user in list(original_tweet['entities']['user_mentions']): + if user['screen_name'] not in nick_ary \ + and user['screen_name'] != g['original_name']: + nick_ary.append(user['screen_name']) + status = ' '.join(g['stuff'].split()[1:]) + status = ' '.join(['@' + nick for nick in nick_ary]) + ' ' + str2u(status) + t.statuses.update(status=status, in_reply_to_status_id=tid) + + def favorite(): """ Favorite @@ -751,6 +793,7 @@ def ls(): target = g['stuff'].split()[0] except: printNicely(red('Omg some syntax is wrong.')) + return # Init cursor d = {'fl': 'followers', 'fr': 'friends'} next_cursor = -1 @@ -932,6 +975,22 @@ def get_slug(): raise Exception('Wrong list name') +def check_slug(list_name): + """ + Check slug + """ + # Get list name and owner + try: + owner, slug = list_name.split('/') + if slug.startswith('@'): + slug = slug[1:] + return owner, slug + except: + printNicely( + light_magenta('List name should follow "@owner/list_name" format.')) + raise Exception('Wrong list name') + + def show_lists(t): """ List list @@ -1230,78 +1289,19 @@ def switch(): except: printNicely(red('Sorry, wrong format.')) return - # Public stream - if target == 'public': - keyword = g['stuff'].split()[1] - if keyword[0] == '#': - keyword = keyword[1:] - # 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, - args=( - c['PUBLIC_DOMAIN'], - args)) - th.daemon = True - th.start() - # Personal stream - 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, - args=( - c['USER_DOMAIN'], - args, - g['original_name'])) - th.daemon = True - th.start() - # Stream base on list - elif target == 'list': - owner, slug = get_slug() - # Force python 2 not redraw readline buffer - g['PREFIX'] = g['cmd'] = '/'.join([owner, slug]) - printNicely(light_yellow('getting list members ...')) - # Get members - t = Twitter(auth=authen()) - members = [] - next_cursor = -1 - while next_cursor != 0: - m = t.lists.members( - slug=slug, - owner_screen_name=owner, - cursor=next_cursor, - include_entities=False) - for u in m['users']: - members.append('@' + u['screen_name']) - next_cursor = m['next_cursor'] - printNicely(light_yellow('... done.')) - # Build thread filter array - args.filter = members - # Kill old thread - g['stream_stop'] = True - # Start new thread - th = threading.Thread( - target=stream, - args=( - c['USER_DOMAIN'], - args, - slug)) - th.daemon = True - th.start() - printNicely('') - if args.filter: - printNicely(cyan('Include: ' + str(len(args.filter)) + ' people.')) - if args.ignore: - printNicely(red('Ignore: ' + str(len(args.ignore)) + ' people.')) - printNicely('') + # Kill old thread + g['stream_stop'] = True + try: + stuff = g['stuff'].split()[1] + except: + stuff = None + # Spawn new thread + spawn_dict = { + 'public': spawn_public_stream, + 'list': spawn_list_stream, + 'mine': spawn_personal_stream, + } + spawn_dict.get(target)(args, stuff) except: debug_option() printNicely(red('Sorry I can\'t understand.')) @@ -1404,7 +1404,10 @@ def config(): g['decorated_name'] = lambda x: color_func( c['DECORATED_NAME'])('[' + x + ']: ') elif key == 'PREFIX': - g['PREFIX'] = u2str(emojize(c['PREFIX'])) + g['PREFIX'] = u2str(emojize(format_prefix( + listname=g['listname'], + keyword=g['keyword'] + ))) reload_config() printNicely(green('Updated successfully.')) except: @@ -1464,7 +1467,10 @@ def help_tweets(): usage += s * 2 + light_green('conversation 12') + ' will show the chain of ' + \ 'replies prior to the tweet with ' + light_yellow('[id=12]') + '.\n' usage += s * 2 + light_green('rep 12 oops') + ' will reply "' + \ - light_yellow('oops') + '" to tweet with ' + \ + light_yellow('oops') + '" to the owner of the tweet with ' + \ + light_yellow('[id=12]') + '.\n' + usage += s * 2 + light_green('repall 12 oops') + ' will reply "' + \ + light_yellow('oops') + '" to all people in the tweet with ' + \ light_yellow('[id=12]') + '.\n' usage += s * 2 + \ light_green('fav 12 ') + ' will favorite the tweet with ' + \ @@ -1661,6 +1667,7 @@ def help(): usage += s * 2 + light_green('p') + ' will pause the stream.\n' usage += s * 2 + light_green('r') + ' will unpause the stream.\n' usage += s * 2 + light_green('c') + ' will clear the screen.\n' + usage += s * 2 + light_green('v') + ' will show version info.\n' usage += s * 2 + light_green('q') + ' will quit.\n' # End usage += '\n' @@ -1751,6 +1758,7 @@ cmdset = [ 'conversation', 'fav', 'rep', + 'repall', 'del', 'ufav', 'share', @@ -1779,7 +1787,8 @@ cmdset = [ 'p', 'r', 'c', - 'q' + 'v', + 'q', ] # Handle function set @@ -1797,6 +1806,7 @@ funcset = [ conversation, favorite, reply, + reply_all, delete, unfavorite, share, @@ -1825,7 +1835,8 @@ funcset = [ pause, replay, clear, - quit + upgrade_center, + quit, ] @@ -1856,6 +1867,7 @@ def listen(): [], # conversation [], # favorite [], # reply + [], # reply_all [], # delete [], # unfavorite [], # url @@ -1903,6 +1915,7 @@ def listen(): [], # pause [], # reconnect [], # clear + [], # version [], # quit ] )) @@ -1948,14 +1961,14 @@ def reconn_notice(): """ Notice when Hangup or Timeout """ - guide = light_magenta("You can use ") + \ - light_green("switch") + \ - light_magenta(" command to return to your stream.\n") - guide += light_magenta("Type ") + \ - light_green("h stream") + \ - light_magenta(" for more details.") + guide = light_magenta('You can use ') + \ + light_green('switch') + \ + light_magenta(' command to return to your stream.\n') + guide += light_magenta('Type ') + \ + light_green('h stream') + \ + light_magenta(' for more details.') printNicely(guide) - sys.stdout.write(g['decorated_name'](c['PREFIX'])) + sys.stdout.write(g['decorated_name'](g['PREFIX'])) sys.stdout.flush() @@ -1966,11 +1979,11 @@ def stream(domain, args, name='Rainbow Stream'): # The Logo art_dict = { c['USER_DOMAIN']: name, - c['PUBLIC_DOMAIN']: args.track_keywords, + c['PUBLIC_DOMAIN']: args.track_keywords or 'Global', c['SITE_DOMAIN']: name, } if c['ASCII_ART']: - ascii_art(art_dict[domain]) + ascii_art(art_dict.get(domain, name)) # These arguments are optional: stream_args = dict( timeout=0.5, # To check g['stream_stop'] after each 0.5 s @@ -2001,7 +2014,7 @@ def stream(domain, args, name='Rainbow Stream'): last_tweet_time = time.time() for tweet in tweet_iter: if tweet is None: - printNicely("-- None --") + printNicely('-- None --') elif tweet is Timeout: # Because the stream check for each 0.3s # so we shouldn't output anything here @@ -2009,12 +2022,12 @@ def stream(domain, args, name='Rainbow Stream'): StreamLock.release() break elif tweet is HeartbeatTimeout: - printNicely("-- Heartbeat Timeout --") + printNicely('-- Heartbeat Timeout --') reconn_notice() StreamLock.release() break elif tweet is Hangup: - printNicely("-- Hangup --") + printNicely('-- Hangup --') reconn_notice() StreamLock.release() break @@ -2044,10 +2057,10 @@ def stream(domain, args, name='Rainbow Stream'): # the 1st character of that word if current_buffer and g['cmd'] != current_buffer: sys.stdout.write( - g['decorated_name'](c['PREFIX']) + str2u(current_buffer)) + g['decorated_name'](g['PREFIX']) + current_buffer) sys.stdout.flush() elif not c['HIDE_PROMPT']: - sys.stdout.write(g['decorated_name'](c['PREFIX'])) + sys.stdout.write(g['decorated_name'](g['PREFIX'])) sys.stdout.flush() elif tweet.get('direct_message'): # Check the semaphore pause and lock (stream process only) @@ -2062,8 +2075,110 @@ def stream(domain, args, name='Rainbow Stream'): except TwitterHTTPError as e: printNicely('') printNicely( - magenta("We have maximum connection problem with twitter'stream API right now :(")) - printTwitterErrors(e) + magenta('We have connection problem with twitter stream API right now :(')) + detail_twitter_error(e) + sys.stdout.write(g['decorated_name'](g['PREFIX'])) + sys.stdout.flush() + except (URLError): + printNicely( + magenta('There seems to be a connection problem.')) + save_history() + sys.exit() + + +def spawn_public_stream(args, keyword=None): + """ + Spawn a new public stream + """ + # Only set keyword if specified + if keyword: + if keyword[0] == '#': + keyword = keyword[1:] + args.track_keywords = keyword + g['keyword'] = keyword + else: + g['keyword'] = 'Global' + g['PREFIX'] = u2str(emojize(format_prefix(keyword=g['keyword']))) + g['listname'] = '' + # Start new thread + th = threading.Thread( + target=stream, + args=( + c['PUBLIC_DOMAIN'], + args)) + th.daemon = True + th.start() + + +def spawn_list_stream(args, stuff=None): + """ + Spawn a new list stream + """ + try: + owner, slug = check_slug(stuff) + except: + owner, slug = get_slug() + + # Force python 2 not redraw readline buffer + listname = '/'.join([owner, slug]) + # Set the listname variable + # and reset tracked keyword + g['listname'] = listname + g['keyword'] = '' + g['PREFIX'] = g['cmd'] = u2str(emojize(format_prefix( + listname=g['listname'] + ))) + printNicely(light_yellow('getting list members ...')) + # Get members + t = Twitter(auth=authen()) + members = [] + next_cursor = -1 + while next_cursor != 0: + m = t.lists.members( + slug=slug, + owner_screen_name=owner, + cursor=next_cursor, + include_entities=False) + for u in m['users']: + members.append('@' + u['screen_name']) + next_cursor = m['next_cursor'] + printNicely(light_yellow('... done.')) + # Build thread filter array + args.filter = members + # Start new thread + th = threading.Thread( + target=stream, + args=( + c['USER_DOMAIN'], + args, + slug)) + th.daemon = True + th.start() + printNicely('') + if args.filter: + printNicely(cyan('Include: ' + str(len(args.filter)) + ' people.')) + if args.ignore: + printNicely(red('Ignore: ' + str(len(args.ignore)) + ' people.')) + printNicely('') + + +def spawn_personal_stream(args, stuff=None): + """ + Spawn a new personal stream + """ + # Reset the tracked keyword and listname + g['keyword'] = g['listname'] = '' + # Reset prefix + g['PREFIX'] = u2str(emojize(format_prefix())) + # Start new thread + th = threading.Thread( + target=stream, + args=( + c['USER_DOMAIN'], + args, + g['original_name'])) + th.daemon = True + th.start() def fly(): @@ -2079,29 +2194,34 @@ def fly(): except TwitterHTTPError as e: printNicely('') printNicely( - magenta("We have connection problem with twitter'stream API right now :(")) - printTwitterErrors(e) - printNicely(magenta("Let's try again later.")) + magenta('We have connection problem with twitter REST API right now :(')) + detail_twitter_error(e) save_history() sys.exit() # Proxy connection problem except (socks.ProxyConnectionError, URLError): printNicely( - magenta("There seems to be a connection problem.")) + magenta('There seems to be a connection problem.')) printNicely( - magenta("You might want to check your proxy settings (host, port and type)!")) + 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, - args=( - c['USER_DOMAIN'], - args, - g['original_name'])) - th.daemon = True - th.start() + target = args.stream.split()[0] + if target == 'mine' : + spawn_personal_stream(args) + else: + try: + stuff = args.stream.split()[1] + except: + stuff = None + spawn_dict = { + 'public': spawn_public_stream, + 'list': spawn_list_stream, + } + spawn_dict.get(target)(args, stuff) + # Start listen process time.sleep(0.5) g['reset'] = True