X-Git-Url: https://vcs.fsf.org/?p=rainbowstream.git;a=blobdiff_plain;f=rainbowstream%2Frainbow.py;h=af674eb3d6b91a4c2d8ec35fe8306c0d081c92b6;hp=f31fa23308f284988d5a918b9880c5eefbe4c694;hb=c3bab4ef2c05950ac280571d9b3575beb5203b31;hpb=632c6fa515fe36cf88ef2bf39378464bd24701d8 diff --git a/rainbowstream/rainbow.py b/rainbowstream/rainbow.py index f31fa23..af674eb 100644 --- a/rainbowstream/rainbow.py +++ b/rainbowstream/rainbow.py @@ -10,13 +10,13 @@ import signal import argparse import time import requests +import webbrowser from twitter.stream import TwitterStream, Timeout, HeartbeatTimeout, Hangup from twitter.api import * from twitter.oauth import OAuth, read_token_file from twitter.oauth_dance import oauth_dance from twitter.util import printNicely -from StringIO import StringIO from .draw import * from .colors import * @@ -25,6 +25,8 @@ from .consumer import * from .interactive import * from .db import * from .c_image import * +from .py3patch import * + g = {} db = RainbowDB() @@ -36,6 +38,7 @@ cmdset = [ 'mentions', 't', 'rt', + 'quote', 'allrt', 'fav', 'rep', @@ -44,6 +47,7 @@ cmdset = [ 's', 'mes', 'show', + 'open', 'ls', 'inbox', 'sent', @@ -64,6 +68,7 @@ cmdset = [ 'q' ] + def parse_arguments(): """ Parse the arguments @@ -133,11 +138,14 @@ def get_decorated_name(): t = Twitter(auth=authen()) name = '@' + t.account.verify_credentials()['screen_name'] g['original_name'] = name[1:] - g['decorated_name'] = grey('[') + grey(name) + grey(']: ') + g['decorated_name'] = color_func(c['DECORATED_NAME'])('[' + name + ']: ') + g['ascii_art'] = True - files = os.listdir('rainbowstream/colorset') - themes = [f.split('.')[0] for f in files if f.split('.')[-1]=='json'] + files = os.listdir(os.path.dirname(__file__)+'/colorset') + themes = [f.split('.')[0] for f in files if f.split('.')[-1] == 'json'] + themes += ['custom'] g['themes'] = themes + db.theme_store(c['theme']) def switch(): @@ -193,12 +201,12 @@ def switch(): p.start() g['stream_pid'] = p.pid printNicely('') - printNicely(green('Stream switched.')) if args.filter: printNicely(cyan('Only: ' + str(args.filter))) if args.ignore: printNicely(red('Ignore: ' + str(args.ignore))) printNicely('') + g['ascii_art'] = True except: printNicely(red('Sorry I can\'t understand.')) @@ -306,6 +314,33 @@ def retweet(): t.statuses.retweet(id=tid, include_entities=False, trim_user=True) +def quote(): + """ + Quote a tweet + """ + t = Twitter(auth=authen()) + try: + id = int(g['stuff'].split()[0]) + except: + printNicely(red('Sorry I can\'t understand.')) + return + tid = db.rainbow_to_tweet_query(id)[0].tweet_id + tweet = t.statuses.show(id=tid) + screen_name = tweet['user']['screen_name'] + text = tweet['text'] + quote = '\"@' + screen_name + ': ' + text + '\"' + quote = quote.encode('utf8') + notice = light_magenta('Compose mode ') + notice += light_yellow('(Enter nothing will cancel the quote)') + notice += light_magenta(':') + printNicely(notice) + extra = raw_input(quote) + if extra: + t.statuses.update(status=quote+extra) + else: + printNicely(light_magenta('No text added.')) + + def allretweet(): """ List all retweet @@ -460,6 +495,26 @@ def show(): printNicely(red('Sorry I can\'t show this image.')) +def urlopen(): + """ + Open url + """ + t = Twitter(auth=authen()) + try: + if not g['stuff'].isdigit(): + return + tid = db.rainbow_to_tweet_query(g['stuff'])[0].tweet_id + tweet = t.statuses.show(id=tid) + link_ary = [u for u in tweet['text'].split() if u.startswith('http://')] + if not link_ary: + printNicely(light_magenta('No url here @.@!')) + return + for link in link_ary: + webbrowser.open(link) + except: + printNicely(red('Sorry I can\'t open url in this tweet.')) + + def list(): """ List friends for followers @@ -747,17 +802,8 @@ def cal(): # Format rel = os.popen('cal').read().split('\n') month = rel.pop(0) - month = random_rainbow(month) date = rel.pop(0) - date = ' '.join([cycle_color(i) for i in date.split(' ')]) - today = str(int(os.popen('date +\'%d\'').read().strip())) - # Display - printNicely(month) - printNicely(date) - for line in rel: - ary = line.split(' ') - ary = map(lambda x: on_grey(x) if x == today else grey(x), ary) - printNicely(' '.join(ary)) + show_calendar(month, date, rel) def theme(): @@ -767,18 +813,61 @@ def theme(): if not g['stuff']: # List themes for theme in g['themes']: - line = ' '*2 + magenta('* ' + theme) + line = '' + # Detect custom config + if theme == 'custom': + line += light_magenta('custom') + custom_path = os.environ.get( + 'HOME', + os.environ.get('USERPROFILE', + '')) + os.sep + '.rainbow_config.json' + if not os.path.exists(custom_path): + line += light_magenta(' (create your own config file at ~/.rainbow_config.json)') + else: + line += light_magenta(' (loaded)') + else: + line += light_magenta(theme) + if c['theme'] == theme : + line = ' '*2 + light_yellow('* ') + line + else: + line = ' '*4 + line printNicely(line) + elif g['stuff'] == 'current_as_default': + # Set default + path = os.path.dirname(__file__) + '/colorset/init' + f = open(path,'w') + f.write(c['theme']) + f.close() + os.system('chmod 777 ' + path) + printNicely(light_green('Okay it will be applied from next time :)')) else: # Change theme - try : - new_config = 'rainbowstream/colorset/' + g['stuff'] + '.json' + try: + # Load new config + if g['stuff'] != 'custom': + new_config = os.path.dirname(__file__) + '/colorset/' + g['stuff'] + '.json' + else: + new_config = os.environ.get( + 'HOME',os.environ.get( + 'USERPROFILE', + '')) + os.sep + '.rainbow_config.json' new_config = load_config(new_config) - for nc in new_config: - c[nc] = new_config[nc] + if new_config: + for nc in new_config: + c[nc] = new_config[nc] + # Update db and reset colors + db.theme_update(g['stuff']) + c['theme'] = g['stuff'] + reset_cycle() + g['decorated_name'] = color_func( + c['DECORATED_NAME'])( + '[@' + g['original_name'] + ']: ') printNicely(green('Theme changed.')) - except : - printNicely(red('Sorry, config file is broken!')) + except: + if g['stuff'] == 'custom': + printNicely(red('~/.rainbow_config.json is not exists!')) + else: + printNicely(red('No such theme exists.')) def help(): @@ -792,124 +881,132 @@ def help(): usage = '\n' usage += s + 'Hi boss! I\'m ready to serve you right now!\n' usage += s + '-' * (int(w) - 4) + '\n' - usage += s + 'You are ' + yellow('already') + ' on your personal stream.\n' + usage += s + 'You are ' + \ + light_yellow('already') + ' on your personal stream.\n' usage += s + 'Any update from Twitter will show up ' + \ - yellow('immediately') + '.\n' + light_yellow('immediately') + '.\n' usage += s + 'In addtion, following commands are available right now:\n' # Discover the world usage += '\n' usage += s + grey(u'\u266A' + ' Discover the world \n') - usage += s * 2 + green('trend') + ' will show global trending topics. ' + \ - 'You can try ' + green('trend US') + ' or ' + \ - green('trend JP Tokyo') + '.\n' - usage += s * 2 + green('home') + ' will show your timeline. ' + \ - green('home 7') + ' will show 7 tweets.\n' - usage += s * 2 + green('mentions') + ' will show mentions timeline. ' + \ - green('mentions 7') + ' will show 7 mention tweets.\n' - usage += s * 2 + green('whois @mdo') + ' will show profile of ' + \ + usage += s * 2 + light_green('trend') + ' will show global trending topics. ' + \ + 'You can try ' + light_green('trend US') + ' or ' + \ + light_green('trend JP Tokyo') + '.\n' + usage += s * 2 + light_green('home') + ' will show your timeline. ' + \ + light_green('home 7') + ' will show 7 tweets.\n' + usage += s * 2 + light_green('mentions') + ' will show mentions timeline. ' + \ + light_green('mentions 7') + ' will show 7 mention tweets.\n' + usage += s * 2 + light_green('whois @mdo') + ' will show profile of ' + \ magenta('@mdo') + '.\n' - usage += s * 2 + green('view @mdo') + \ + usage += s * 2 + light_green('view @mdo') + \ ' will show ' + magenta('@mdo') + '\'s home.\n' - usage += s * 2 + green('s #AKB48') + ' will search for "' + \ - yellow('AKB48') + '" and return 5 newest tweet.\n' + usage += s * 2 + light_green('s #AKB48') + ' will search for "' + \ + light_yellow('AKB48') + '" and return 5 newest tweet.\n' # Tweet usage += '\n' usage += s + grey(u'\u266A' + ' Tweets \n') - usage += s * 2 + green('t oops ') + \ - 'will tweet "' + yellow('oops') + '" immediately.\n' + usage += s * 2 + light_green('t oops ') + \ + 'will tweet "' + light_yellow('oops') + '" immediately.\n' usage += s * 2 + \ - green('rt 12 ') + ' will retweet to tweet with ' + \ - yellow('[id=12]') + '.\n' + light_green('rt 12 ') + ' will retweet to tweet with ' + \ + light_yellow('[id=12]') + '.\n' usage += s * 2 + \ - green('allrt 12 20 ') + ' will list 20 newest retweet of the tweet with ' + \ - yellow('[id=12]') + '.\n' - usage += s * 2 + green('rep 12 oops') + ' will reply "' + \ - yellow('oops') + '" to tweet with ' + yellow('[id=12]') + '.\n' + light_green('quote 12 ') + ' will quote the tweet with ' + \ + light_yellow('[id=12]') + '. If no extra text is added, ' + \ + 'the quote will be canceled.\n' usage += s * 2 + \ - green('fav 12 ') + ' will favorite the tweet with ' + \ - yellow('[id=12]') + '.\n' + light_green('allrt 12 20 ') + ' will list 20 newest retweet of 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('[id=12]') + '.\n' usage += s * 2 + \ - green('ufav 12 ') + ' will unfavorite tweet with ' + \ - yellow('[id=12]') + '.\n' + light_green('fav 12 ') + ' will favorite the tweet with ' + \ + light_yellow('[id=12]') + '.\n' usage += s * 2 + \ - green('del 12 ') + ' will delete tweet with ' + \ - yellow('[id=12]') + '.\n' - usage += s * 2 + green('show image 12') + ' will show image in tweet with ' + \ - yellow('[id=12]') + ' in your OS\'s image viewer.\n' + light_green('ufav 12 ') + ' will unfavorite tweet with ' + \ + light_yellow('[id=12]') + '.\n' + usage += s * 2 + \ + light_green('del 12 ') + ' will delete tweet with ' + \ + light_yellow('[id=12]') + '.\n' + usage += s * 2 + light_green('show image 12') + ' will show image in tweet with ' + \ + light_yellow('[id=12]') + ' in your OS\'s image viewer.\n' + usage += s * 2 + light_green('open 12') + ' will open url in tweet with ' + \ + light_yellow('[id=12]') + ' in your OS\'s default browser.\n' # Direct message usage += '\n' usage += s + grey(u'\u266A' + ' Direct messages \n') - usage += s * 2 + green('inbox') + ' will show inbox messages. ' + \ - green('inbox 7') + ' will show newest 7 messages.\n' - usage += s * 2 + green('sent') + ' will show sent messages. ' + \ - green('sent 7') + ' will show newest 7 messages.\n' - usage += s * 2 + green('mes @dtvd88 hi') + ' will send a "hi" messege to ' + \ + usage += s * 2 + light_green('inbox') + ' will show inbox messages. ' + \ + light_green('inbox 7') + ' will show newest 7 messages.\n' + usage += s * 2 + light_green('sent') + ' will show sent messages. ' + \ + light_green('sent 7') + ' will show newest 7 messages.\n' + usage += s * 2 + light_green('mes @dtvd88 hi') + ' will send a "hi" messege to ' + \ magenta('@dtvd88') + '.\n' - usage += s * 2 + green('trash 5') + ' will remove message with ' + \ - yellow('[message_id=5]') + '.\n' + usage += s * 2 + light_green('trash 5') + ' will remove message with ' + \ + light_yellow('[message_id=5]') + '.\n' # Follower and following usage += '\n' - usage += s + grey(u'\u266A' + ' Fiends and followers \n') + usage += s + grey(u'\u266A' + ' Friends and followers \n') usage += s * 2 + \ - green('ls fl') + \ + light_green('ls fl') + \ ' will list all followers (people who are following you).\n' usage += s * 2 + \ - green('ls fr') + \ + light_green('ls fr') + \ ' will list all friends (people who you are following).\n' - usage += s * 2 + green('fl @dtvd88') + ' will follow ' + \ + usage += s * 2 + light_green('fl @dtvd88') + ' will follow ' + \ magenta('@dtvd88') + '.\n' - usage += s * 2 + green('ufl @dtvd88') + ' will unfollow ' + \ + usage += s * 2 + light_green('ufl @dtvd88') + ' will unfollow ' + \ magenta('@dtvd88') + '.\n' - usage += s * 2 + green('mute @dtvd88') + ' will mute ' + \ + usage += s * 2 + light_green('mute @dtvd88') + ' will mute ' + \ magenta('@dtvd88') + '.\n' - usage += s * 2 + green('unmute @dtvd88') + ' will unmute ' + \ + usage += s * 2 + light_green('unmute @dtvd88') + ' will unmute ' + \ magenta('@dtvd88') + '.\n' - usage += s * 2 + green('muting') + ' will list muting users.\n' - usage += s * 2 + green('block @dtvd88') + ' will block ' + \ + usage += s * 2 + light_green('muting') + ' will list muting users.\n' + usage += s * 2 + light_green('block @dtvd88') + ' will block ' + \ magenta('@dtvd88') + '.\n' - usage += s * 2 + green('unblock @dtvd88') + ' will unblock ' + \ + usage += s * 2 + light_green('unblock @dtvd88') + ' will unblock ' + \ magenta('@dtvd88') + '.\n' - usage += s * 2 + green('report @dtvd88') + ' will report ' + \ + usage += s * 2 + light_green('report @dtvd88') + ' will report ' + \ magenta('@dtvd88') + ' as a spam account.\n' # Switch usage += '\n' usage += s + grey(u'\u266A' + ' Switching streams \n') - usage += s * 2 + green('switch public #AKB') + \ + usage += s * 2 + light_green('switch public #AKB') + \ ' will switch to public stream and follow "' + \ - yellow('AKB') + '" keyword.\n' - usage += s * 2 + green('switch mine') + \ + light_yellow('AKB') + '" keyword.\n' + usage += s * 2 + light_green('switch mine') + \ ' will switch to your personal stream.\n' - usage += s * 2 + green('switch mine -f ') + \ + usage += s * 2 + light_green('switch mine -f ') + \ ' will prompt to enter the filter.\n' - usage += s * 3 + yellow('Only nicks') + \ + usage += s * 3 + light_yellow('Only nicks') + \ ' filter will decide nicks will be INCLUDE ONLY.\n' - usage += s * 3 + yellow('Ignore nicks') + \ + usage += s * 3 + light_yellow('Ignore nicks') + \ ' filter will decide nicks will be EXCLUDE.\n' - usage += s * 2 + green('switch mine -d') + \ + usage += s * 2 + light_green('switch mine -d') + \ ' will use the config\'s ONLY_LIST and IGNORE_LIST.\n' # Smart shell usage += '\n' usage += s + grey(u'\u266A' + ' Smart shell\n') - usage += s * 2 + green('111111 * 9 / 7') + ' or any math expression ' + \ + usage += s * 2 + light_green('111111 * 9 / 7') + ' or any math expression ' + \ 'will be evaluate by Python interpreter.\n' - usage += s * 2 + 'Even ' + green('cal') + ' will show the calendar' + \ + usage += s * 2 + 'Even ' + light_green('cal') + ' will show the calendar' + \ ' for current month.\n' # Screening usage += '\n' usage += s + grey(u'\u266A' + ' Screening \n') - usage += s * 2 + green('theme') + ' will list available theme.' + \ - green('theme monokai') + ' will apply '+ yellow('monokai') + \ + usage += s * 2 + light_green('theme') + ' will list available theme.' + \ + light_green('theme monokai') + ' will apply ' + light_yellow('monokai') + \ ' theme immediately.\n' - usage += s * 2 + green('h') + ' will show this help again.\n' - usage += s * 2 + green('c') + ' will clear the screen.\n' - usage += s * 2 + green('q') + ' will quit.\n' + usage += s * 2 + light_green('h') + ' will show this help again.\n' + usage += s * 2 + light_green('c') + ' will clear the screen.\n' + usage += s * 2 + light_green('q') + ' will quit.\n' # End usage += '\n' @@ -943,8 +1040,8 @@ def reset(): printNicely(magenta('Need tips ? Type "h" and hit Enter key!')) g['reset'] = False try: - printNicely(eval(g['cmd'])) - except: + printNicely(str(eval(g['cmd']))) + except Exception: pass @@ -962,6 +1059,7 @@ def process(cmd): mentions, tweet, retweet, + quote, allretweet, favorite, reply, @@ -970,6 +1068,7 @@ def process(cmd): search, message, show, + urlopen, list, inbox, sent, @@ -1006,6 +1105,7 @@ def listen(): [], # mentions [], # tweet [], # retweet + [], # quote [], # allretweet [], # favorite [], # reply @@ -1014,6 +1114,7 @@ def listen(): ['#'], # search ['@'], # message ['image'], # show image + [''], # open url ['fl', 'fr'], # list [], # inbox [], # sent @@ -1028,7 +1129,7 @@ def listen(): ['@'], # unblock ['@'], # report [], # cal - g['themes'], # theme + g['themes'] + ['current_as_default'], # theme [], # help [], # clear [], # quit @@ -1071,7 +1172,8 @@ def stream(domain, args, name='Rainbow Stream'): c['PUBLIC_DOMAIN']: args.track_keywords, c['SITE_DOMAIN']: 'Site Stream', } - ascii_art(art_dict[domain]) + if g['ascii_art']: + ascii_art(art_dict[domain]) # These arguments are optional: stream_args = dict( @@ -1090,18 +1192,18 @@ def stream(domain, args, name='Rainbow Stream'): domain=domain, **stream_args) - if domain == c['USER_DOMAIN']: - tweet_iter = stream.user(**query_args) - elif domain == c['SITE_DOMAIN']: - tweet_iter = stream.site(**query_args) - else: - if args.track_keywords: - tweet_iter = stream.statuses.filter(**query_args) + try: + if domain == c['USER_DOMAIN']: + tweet_iter = stream.user(**query_args) + elif domain == c['SITE_DOMAIN']: + tweet_iter = stream.site(**query_args) else: - tweet_iter = stream.statuses.sample() + if args.track_keywords: + tweet_iter = stream.statuses.filter(**query_args) + else: + tweet_iter = stream.statuses.sample() - # Iterate over the stream. - try: + # Iterate over the stream. for tweet in tweet_iter: if tweet is None: printNicely("-- None --") @@ -1119,9 +1221,10 @@ def stream(domain, args, name='Rainbow Stream'): fil=args.filter, ig=args.ignore, ) - except: - printNicely(magenta("I'm afraid we have problem with twitter'S maximum connection.")) - printNicely(magenta("Let's try again later.")) + except TwitterHTTPError: + printNicely('') + printNicely( + magenta("We have maximum connection problem with twitter'stream API right now :(")) def fly(): @@ -1130,8 +1233,24 @@ def fly(): """ # Spawn stream process args = parse_arguments() - get_decorated_name() - p = Process(target=stream, args=(c['USER_DOMAIN'], args, g['original_name'])) + try: + get_decorated_name() + + except TwitterHTTPError: + printNicely('') + printNicely( + magenta("I'm afraid we have maximum connection problem with twitter right now :(")) + printNicely(magenta("Let's try again later.")) + save_history() + os.system('rm -rf rainbow.db') + sys.exit() + + p = Process( + target=stream, + args=( + c['USER_DOMAIN'], + args, + g['original_name'])) p.start() # Start listen process