X-Git-Url: https://vcs.fsf.org/?p=rainbowstream.git;a=blobdiff_plain;f=rainbowstream%2Frainbow.py;h=7671143b5812d068ee94de0e347fe84d67a14a69;hp=bc7d85ad5e8e481ecaffbb6ebc65dcfe3cb1994e;hb=66fe9f758d24e00cc7f4264a420e2a1507aac0af;hpb=841260feb5d0bc4d556b3fab34d2f7efbeb78a51 diff --git a/rainbowstream/rainbow.py b/rainbowstream/rainbow.py index bc7d85a..7671143 100644 --- a/rainbowstream/rainbow.py +++ b/rainbowstream/rainbow.py @@ -8,6 +8,7 @@ import threading import requests import webbrowser import traceback +import pkg_resources from twitter.stream import TwitterStream, Timeout, HeartbeatTimeout, Hangup from twitter.api import * @@ -52,11 +53,6 @@ def parse_arguments(): '-ig', '--ignore', help='Ignore specific screen_name.') - parser.add_argument( - '-dg', - '--debug', - action='store_true', - help='Run in debug mode.') parser.add_argument( '-iot', '--image-on-term', @@ -123,6 +119,27 @@ def debug_option(): g['traceback'].append(traceback.format_exc()) +def upgrade_center(): + """ + Check latest and notify to upgrade + """ + try: + 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] + if current != latest: + notice = light_magenta('RainbowStream latest version is ') + notice += light_green(latest) + notice += light_magenta(' while your current version is ') + notice += light_yellow(current) + '\n' + notice += light_magenta('You should upgrade with ') + notice += light_green('pip install -U rainbowstream') + printNicely(notice) + except: + pass + + def init(args): """ Init function @@ -130,6 +147,8 @@ def init(args): # Handle Ctrl C ctrl_c_handler = lambda signum, frame: quit() signal.signal(signal.SIGINT, ctrl_c_handler) + # Upgrade notify + upgrade_center() # Get name t = Twitter(auth=authen()) credential = t.account.verify_credentials() @@ -142,21 +161,19 @@ def init(args): c['original_name'] = g['original_name'] = screen_name[1:] g['full_name'] = name g['decorated_name'] = lambda x: color_func( - c['DECORATED_NAME'])('[' + x + ']: ') + c['DECORATED_NAME'])('[' + x + ']: ', rl=True) # Theme init files = os.listdir(os.path.dirname(__file__) + '/colorset') themes = [f.split('.')[0] for f in files if f.split('.')[-1] == 'json'] g['themes'] = themes g['pause'] = False g['message_threads'] = {} - # Events - g['events'] = [] # Startup cmd g['cmd'] = '' - # Debug option - g['debug'] = args.debug + # Debug option default = True + g['debug'] = True g['traceback'] = [] - # Retweet of mine events + # Events c['events'] = [] # Semaphore init c['lock'] = False @@ -223,9 +240,8 @@ def notification(): """ Show notifications """ - g['events'] = g['events'] + c['events'] - if g['events']: - for e in g['events']: + if c['events']: + for e in c['events']: print_event(e) printNicely('') else: @@ -275,7 +291,8 @@ def view(): num = int(g['stuff'].split()[1]) except: num = c['HOME_TWEET_NUM'] - for tweet in reversed(t.statuses.user_timeline(count=num, screen_name=user[1:])): + for tweet in reversed( + t.statuses.user_timeline(count=num, screen_name=user[1:])): draw(t=tweet) printNicely('') else: @@ -350,7 +367,8 @@ def quote(): if not formater: return # Get comment - prefix = light_magenta('Compose your ') + light_green('#comment: ') + prefix = light_magenta('Compose your ', rl=True) + \ + light_green('#comment: ', rl=True) comment = raw_input(prefix) if comment: quote = comment.join(formater.split('#comment')) @@ -464,6 +482,28 @@ def unfavorite(): printNicely('') +def share(): + """ + Copy url of a tweet to clipboard + """ + t = Twitter(auth=authen()) + try: + id = int(g['stuff'].split()[0]) + tid = c['tweet_dict'][id] + except: + printNicely(red('Tweet id is not valid.')) + return + tweet = t.statuses.show(id=tid) + url = 'https://twitter.com/' + \ + tweet['user']['screen_name'] + '/status/' + str(tid) + import platform + if platform.system().lower() == 'darwin': + os.system("echo '%s' | pbcopy" % url) + printNicely(green('Copied tweet\'s url to clipboard.')) + else: + printNicely('Direct link: ' + yellow(url)) + + def delete(): """ Delete @@ -825,10 +865,11 @@ def report(): def get_slug(): """ - Get Slug Decorator + Get slug """ # Get list name - list_name = raw_input(light_magenta('Give me the list\'s name: ')) + list_name = raw_input( + light_magenta('Give me the list\'s name ("@owner/list_name"): ', rl=True)) # Get list name and owner try: owner, slug = list_name.split('/') @@ -921,7 +962,10 @@ def list_add(t): """ owner, slug = get_slug() # Add - user_name = raw_input(light_magenta('Give me name of the newbie: ')) + user_name = raw_input( + light_magenta( + 'Give me name of the newbie: ', + rl=True)) if user_name.startswith('@'): user_name = user_name[1:] try: @@ -941,7 +985,10 @@ def list_remove(t): """ owner, slug = get_slug() # Remove - user_name = raw_input(light_magenta('Give me name of the unlucky one: ')) + user_name = raw_input( + light_magenta( + 'Give me name of the unlucky one: ', + rl=True)) if user_name.startswith('@'): user_name = user_name[1:] try: @@ -1011,9 +1058,15 @@ def list_new(t): """ Create a new list """ - name = raw_input(light_magenta('New list\'s name: ')) - mode = raw_input(light_magenta('New list\'s mode (public/private): ')) - description = raw_input(light_magenta('New list\'s description: ')) + name = raw_input(light_magenta('New list\'s name: ', rl=True)) + mode = raw_input( + light_magenta( + 'New list\'s mode (public/private): ', + rl=True)) + description = raw_input( + light_magenta( + 'New list\'s description: ', + rl=True)) try: t.lists.create( name=name, @@ -1029,10 +1082,16 @@ def list_update(t): """ Update a list """ - slug = raw_input(light_magenta('Your list that you want to update: ')) - name = raw_input(light_magenta('Update name (leave blank to unchange): ')) - mode = raw_input(light_magenta('Update mode (public/private): ')) - description = raw_input(light_magenta('Update description: ')) + slug = raw_input( + light_magenta( + 'Your list that you want to update: ', + rl=True)) + name = raw_input( + light_magenta( + 'Update name (leave blank to unchange): ', + rl=True)) + mode = raw_input(light_magenta('Update mode (public/private): ', rl=True)) + description = raw_input(light_magenta('Update description: ', rl=True)) try: if name: t.lists.update( @@ -1057,7 +1116,10 @@ def list_delete(t): """ Delete a list """ - slug = raw_input(light_magenta('Your list that you want to delete: ')) + slug = raw_input( + light_magenta( + 'Your list that you want to delete: ', + rl=True)) try: t.lists.destroy( slug='-'.join(slug.split()), @@ -1150,13 +1212,47 @@ def switch(): 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['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('Only: ' + str(args.filter))) + printNicely(cyan('Include: ' + str(len(args.filter)) + ' people.')) if args.ignore: - printNicely(red('Ignore: ' + str(args.ignore))) + printNicely(red('Ignore: ' + str(len(args.ignore)) + ' people.')) printNicely('') - except: + except Exception: + debug_option() printNicely(red('Sorry I can\'t understand.')) @@ -1320,6 +1416,9 @@ def help_tweets(): usage += s * 2 + \ light_green('ufav 12 ') + ' will unfavorite tweet with ' + \ light_yellow('[id=12]') + '.\n' + usage += s * 2 + \ + 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' @@ -1439,6 +1538,8 @@ def help_stream(): ' 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) @@ -1598,6 +1699,7 @@ cmdset = [ 'rep', 'del', 'ufav', + 'share', 's', 'mes', 'show', @@ -1643,6 +1745,7 @@ funcset = [ reply, delete, unfavorite, + share, search, message, show, @@ -1686,7 +1789,7 @@ def listen(): d = dict(zip( cmdset, [ - ['public', 'mine'], # switch + ['public', 'mine', 'list'], # switch [], # trend [], # home [], # notification @@ -1701,6 +1804,7 @@ def listen(): [], # reply [], # delete [], # unfavorite + [], # url ['#'], # search ['@'], # message ['image'], # show image @@ -1786,6 +1890,21 @@ def listen(): printNicely(red('OMG something is wrong with Twitter right now.')) +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.") + printNicely(guide) + sys.stdout.write(g['decorated_name'](c['PREFIX'])) + sys.stdout.flush() + + def stream(domain, args, name='Rainbow Stream'): """ Track the stream @@ -1829,24 +1948,21 @@ def stream(domain, args, name='Rainbow Stream'): if tweet is None: printNicely("-- None --") elif tweet is Timeout: + # Because the stream check for each 0.3s + # so we shouldn't output anything here if(g['stream_stop']): StreamLock.release() break elif tweet is HeartbeatTimeout: printNicely("-- Heartbeat 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.") - printNicely(guide) - sys.stdout.write(g['decorated_name'](c['PREFIX'])) - sys.stdout.flush() + reconn_notice() StreamLock.release() break elif tweet is Hangup: printNicely("-- Hangup --") + reconn_notice() + StreamLock.release() + break elif tweet.get('text'): # Check the semaphore pause and lock (stream process only) if g['pause']: @@ -1882,7 +1998,7 @@ def stream(domain, args, name='Rainbow Stream'): time.sleep(0.5) print_message(tweet['direct_message']) elif tweet.get('event'): - g['events'].append(tweet) + c['events'].append(tweet) print_event(tweet) except TwitterHTTPError: printNicely('')