X-Git-Url: https://vcs.fsf.org/?p=rainbowstream.git;a=blobdiff_plain;f=rainbowstream%2Frainbow.py;h=55e062cb5b0a5c38243dabbe54048cb6513c1c42;hp=20c110f6b1fdf637deb6744f680bffdec81052dd;hb=531f568231af56035b61bb196b0e43fa79ff223e;hpb=3c85d8fc9b0e42c3f960a837badceeb62549ec3f diff --git a/rainbowstream/rainbow.py b/rainbowstream/rainbow.py index 20c110f..55e062c 100644 --- a/rainbowstream/rainbow.py +++ b/rainbowstream/rainbow.py @@ -27,9 +27,13 @@ from .db import * from .c_image import * from .py3patch import * - +# Global values g = {} + +# Database db = RainbowDB() + +# Commands cmdset = [ 'switch', 'trend', @@ -63,6 +67,7 @@ cmdset = [ 'report', 'list', 'cal', + 'config', 'theme', 'h', 'c', @@ -132,21 +137,22 @@ def authen(): CONSUMER_SECRET) -def get_decorated_name(): +def init(): """ - Beginning of every line + Init function """ + # Get name t = Twitter(auth=authen()) name = '@' + t.account.verify_credentials()['screen_name'] g['original_name'] = name[1:] g['decorated_name'] = color_func(c['DECORATED_NAME'])('[' + name + ']: ') - g['ascii_art'] = True - + # Theme init 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']) + db.theme_store(c['THEME']) + # Semaphore init + db.semaphore_store(False) def switch(): @@ -155,7 +161,6 @@ def switch(): """ try: target = g['stuff'].split()[0] - # Filter and ignore args = parse_arguments() try: @@ -170,7 +175,6 @@ def switch(): except: printNicely(red('Sorry, wrong format.')) return - # Public stream if target == 'public': keyword = g['stuff'].split()[1] @@ -187,7 +191,6 @@ def switch(): args)) p.start() g['stream_pid'] = p.pid - # Personal stream elif target == 'mine': # Kill old process @@ -207,7 +210,6 @@ def switch(): if args.ignore: printNicely(red('Ignore: ' + str(args.ignore))) printNicely('') - g['ascii_art'] = True except: printNicely(red('Sorry I can\'t understand.')) @@ -226,7 +228,6 @@ def trend(): town = g['stuff'].split()[1] except: town = '' - avail = t.trends.available() # World wide if not country: @@ -440,19 +441,17 @@ def search(): Search """ t = Twitter(auth=authen()) - if g['stuff'].startswith('#'): - rel = t.search.tweets(q=g['stuff'])['statuses'] - if rel: - printNicely('Newest tweets:') - for i in reversed(xrange(c['SEARCH_MAX_RECORD'])): - draw(t=rel[i], - iot=g['iot'], - keyword=g['stuff'].strip()[1:]) - printNicely('') - else: - printNicely(magenta('I\'m afraid there is no result')) + g['stuff'] = g['stuff'].strip() + rel = t.search.tweets(q=g['stuff'])['statuses'] + if rel: + printNicely('Newest tweets:') + for i in reversed(xrange(c['SEARCH_MAX_RECORD'])): + draw(t=rel[i], + iot=g['iot'], + keyword=g['stuff']) + printNicely('') else: - printNicely(red('A keyword should be a hashtag (like \'#AKB48\')')) + printNicely(magenta('I\'m afraid there is no result')) def message(): @@ -490,7 +489,7 @@ def show(): media = tweet['entities']['media'] for m in media: res = requests.get(m['media_url']) - img = Image.open(StringIO(res.content)) + img = Image.open(BytesIO(res.content)) img.show() except: printNicely(red('Sorry I can\'t show this image.')) @@ -799,6 +798,24 @@ def report(): printNicely(red('Sorry I can\'t understand.')) +def get_slug(): + """ + Get Slug Decorator + """ + # Get list name + list_name = raw_input(light_magenta('Give me the list\'s name: ')) + # 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 @@ -814,16 +831,7 @@ def list_home(t): """ List home """ - # Get list name - list_name = raw_input(light_magenta('Give me the list\'s name: ')) - # Get list name and owner - try: - owner, slug = list_name.split('/') - if slug.startswith('@'): - slug = slug[1:] - except: - printNicely(light_magenta('Please follow "@owner/list_name" format.')) - return + owner, slug = get_slug() res = t.lists.statuses( slug=slug, owner_screen_name=owner, @@ -838,16 +846,7 @@ def list_members(t): """ List members """ - # Get list name - list_name = raw_input(light_magenta('Give me the list\'s name: ')) - # Get list name and owner - try: - owner, slug = list_name.split('/') - if slug.startswith('@'): - slug = slug[1:] - except: - printNicely(light_magenta('Please follow "@owner/list_name" format.')) - return + owner, slug = get_slug() # Get members rel = {} next_cursor = -1 @@ -871,16 +870,7 @@ def list_subscribers(t): """ List subscribers """ - # Get list name - list_name = raw_input(light_magenta('Give me the list\'s name: ')) - # Get list name and owner - try: - owner, slug = list_name.split('/') - if slug.startswith('@'): - slug = slug[1:] - except: - printNicely(light_magenta('Please follow "@owner/list_name" format.')) - return + owner, slug = get_slug() # Get subscribers rel = {} next_cursor = -1 @@ -904,16 +894,7 @@ def list_add(t): """ Add specific user to a list """ - # Get list name - list_name = raw_input(light_magenta('Give me the list\'s name: ')) - # Get list name and owner - try: - owner, slug = list_name.split('/') - if slug.startswith('@'): - slug = slug[1:] - except: - printNicely(light_magenta('Please follow "@owner/list_name" format.')) - return + owner, slug = get_slug() # Add user_name = raw_input(light_magenta('Give me name of the newbie: ')) if user_name.startswith('@'): @@ -932,16 +913,7 @@ def list_remove(t): """ Remove specific user from a list """ - # Get list name - list_name = raw_input(light_magenta('Give me the list\'s name: ')) - # Get list name and owner - try: - owner, slug = list_name.split('/') - if slug.startswith('@'): - slug = slug[1:] - except: - printNicely(light_magenta('Please follow "@owner/list_name" format.')) - return + owner, slug = get_slug() # Remove user_name = raw_input(light_magenta('Give me name of the unlucky one: ')) if user_name.startswith('@'): @@ -960,16 +932,7 @@ def list_subscribe(t): """ Subscribe to a list """ - # Get list name - list_name = raw_input(light_magenta('Give me the list\'s name: ')) - # Get list name and owner - try: - owner, slug = list_name.split('/') - if slug.startswith('@'): - slug = slug[1:] - except: - printNicely(light_magenta('Please follow "@owner/list_name" format.')) - return + owner, slug = get_slug() # Subscribe try: t.lists.subscribers.create( @@ -985,16 +948,7 @@ def list_unsubscribe(t): """ Unsubscribe a list """ - # Get list name - list_name = raw_input(light_magenta('Give me the list\'s name: ')) - # Get list name and owner - try: - owner, slug = list_name.split('/') - if slug.startswith('@'): - slug = slug[1:] - except: - printNicely(light_magenta('Please follow "@owner/list_name" format.')) - return + owner, slug = get_slug() # Subscribe try: t.lists.subscribers.destroy( @@ -1110,7 +1064,7 @@ def list(): try: return action_ary[g['list_action']](t) except: - printNicely(red('Sorry I can\'t understand.')) + printNicely(red('Please try again.')) def cal(): @@ -1124,6 +1078,52 @@ def cal(): show_calendar(month, date, rel) +def config(): + """ + Browse and change config + """ + all_config = get_all_config() + g['stuff'] = g['stuff'].strip() + # List all config + if not g['stuff']: + for k in all_config: + line = ' ' * 2 + \ + light_green(k) + ': ' + light_yellow(str(all_config[k])) + printNicely(line) + guide = 'Detailed explanation can be found at ' + \ + color_func(c['TWEET']['link'])( + 'http://rainbowstream.readthedocs.org/en/latest/#config-explanation') + printNicely(guide) + # Print specific config + elif len(g['stuff'].split()) == 1: + if g['stuff'] in all_config: + k = g['stuff'] + line = ' ' * 2 + \ + light_green(k) + ': ' + light_yellow(str(all_config[k])) + printNicely(line) + else: + printNicely(red('No config key like this.')) + # Print specific config's default value + elif len(g['stuff'].split()) == 2 and g['stuff'].split()[-1] == 'default': + key = g['stuff'].split()[0] + value = get_default_config(key) + line = ' ' * 2 + light_green(key) + ': ' + light_magenta(value) + printNicely(line) + # Set specific config + elif len(g['stuff'].split()) == 3 and g['stuff'].split()[1] == '=': + key = g['stuff'].split()[0] + value = g['stuff'].split()[-1] + try: + set_config(key, value) + printNicely(light_green('Updated successfully.')) + except: + printNicely(light_magenta('Not valid value.')) + return + reload_config() + else: + printNicely(light_magenta('Sorry I can\'s understand.')) + + def theme(): """ List and change theme @@ -1131,33 +1131,15 @@ def theme(): if not g['stuff']: # List themes for theme in g['themes']: - 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 = 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) + # Set as default + set_config('THEME', c['THEME']) printNicely(light_green('Okay it will be applied from next time :)')) else: # Change theme @@ -1177,17 +1159,14 @@ def theme(): c[nc] = new_config[nc] # Update db and reset colors db.theme_update(g['stuff']) - c['theme'] = g['stuff'] - reset_cycle() + c['THEME'] = g['stuff'] + start_cycle() g['decorated_name'] = color_func( c['DECORATED_NAME'])( '[@' + g['original_name'] + ']: ') printNicely(green('Theme changed.')) except: - if g['stuff'] == 'custom': - printNicely(red('~/.rainbow_config.json is not exists!')) - else: - printNicely(red('No such theme exists.')) + printNicely(red('No such theme exists.')) def help_discover(): @@ -1209,8 +1188,9 @@ def help_discover(): magenta('@mdo') + '.\n' usage += s * 2 + light_green('view @mdo') + \ ' will show ' + magenta('@mdo') + '\'s home.\n' - usage += s * 2 + light_green('s #AKB48') + ' will search for "' + \ - light_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. ' + \ + 'Search can be performed with or without hashtag.\n' printNicely(usage) @@ -1371,7 +1351,6 @@ def help(): """ s = ' ' * 2 h, w = os.popen('stty size', 'r').read().split() - # Start usage = '\n' usage += s + 'Hi boss! I\'m ready to serve you right now!\n' @@ -1381,7 +1360,6 @@ def help(): usage += s + 'Any update from Twitter will show up ' + \ light_yellow('immediately') + '.\n' usage += s + 'In addtion, following commands are available right now:\n' - # Twitter help section usage += '\n' usage += s + grey(u'\u266A' + ' Twitter help\n') @@ -1397,7 +1375,6 @@ def help(): ' will show help for list commands.\n' usage += s * 2 + light_green('h stream') + \ ' will show help for stream commands.\n' - # Smart shell usage += '\n' usage += s + grey(u'\u266A' + ' Smart shell\n') @@ -1405,22 +1382,33 @@ def help(): 'will be evaluate by Python interpreter.\n' usage += s * 2 + 'Even ' + light_green('cal') + ' will show the calendar' + \ ' for current month.\n' - - # Screening + # Config usage += '\n' - usage += s + grey(u'\u266A' + ' Screening \n') - usage += s * 2 + light_green('theme') + ' will list available theme.' + \ + usage += s + grey(u'\u266A' + ' Config \n') + 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 + light_green('config') + ' will list all config.\n' + usage += s * 3 + \ + light_green('config ASCII_ART') + ' will output current value of ' +\ + light_yellow('ASCII_ART') + ' config key.\n' + usage += s * 3 + \ + light_green('config ASCII_ART default') + ' will output default value of ' + \ + light_yellow('ASCII_ART') + ' config key.\n' + usage += s * 3 + \ + light_green('config ASCII_ART = False') + ' will set value of ' + \ + light_yellow('ASCII_ART') + ' config key to ' + \ + light_yellow('False') + '.\n' + # Screening + usage += '\n' + usage += s + grey(u'\u266A' + ' Screening \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' usage += s + '-' * (int(w) - 4) + '\n' usage += s + 'Have fun and hang tight! \n' - # Show help d = { 'discover': help_discover, @@ -1505,6 +1493,7 @@ def process(cmd): report, list, cal, + config, theme, help, clear, @@ -1564,6 +1553,7 @@ def listen(): 'del' ], # list [], # cal + [key for key in dict(get_all_config())], # config g['themes'] + ['current_as_default'], # theme [ 'discover', @@ -1590,50 +1580,50 @@ def listen(): except: cmd = '' g['cmd'] = cmd - # Save cmd to global variable and call process try: + # Lock the semaphore + db.semaphore_update(True) + # Save cmd to global variable and call process g['stuff'] = ' '.join(line.split()[1:]) + # Process the command process(cmd)() + # Not re-display + if cmd in ['switch', 't', 'rt', 'rep']: + g['prefix'] = False + else: + g['prefix'] = True + # Release the semaphore lock + db.semaphore_update(False) except Exception: printNicely(red('OMG something is wrong with Twitter right now.')) - # Not redisplay prefix - if cmd in ['switch', 't', 'rt', 'rep']: - g['prefix'] = False - else: - g['prefix'] = True def stream(domain, args, name='Rainbow Stream'): """ Track the stream """ - # The Logo art_dict = { c['USER_DOMAIN']: name, c['PUBLIC_DOMAIN']: args.track_keywords, - c['SITE_DOMAIN']: 'Site Stream', + c['SITE_DOMAIN']: name, } - if g['ascii_art']: + if c['ASCII_ART']: ascii_art(art_dict[domain]) - # These arguments are optional: stream_args = dict( timeout=args.timeout, block=not args.no_block, heartbeat_timeout=args.heartbeat_timeout) - # Track keyword query_args = dict() if args.track_keywords: query_args['track'] = args.track_keywords - # Get stream stream = TwitterStream( auth=authen(), domain=domain, **stream_args) - try: if domain == c['USER_DOMAIN']: tweet_iter = stream.user(**query_args) @@ -1644,8 +1634,6 @@ def stream(domain, args, name='Rainbow Stream'): tweet_iter = stream.statuses.filter(**query_args) else: tweet_iter = stream.statuses.sample() - - # Iterate over the stream. for tweet in tweet_iter: if tweet is None: printNicely("-- None --") @@ -1660,6 +1648,7 @@ def stream(domain, args, name='Rainbow Stream'): t=tweet, iot=args.image_on_term, keyword=args.track_keywords, + check_semaphore=True, fil=args.filter, ig=args.ignore, ) @@ -1673,20 +1662,20 @@ def fly(): """ Main function """ - # Spawn stream process + # Initial args = parse_arguments() try: - get_decorated_name() - + init() except TwitterHTTPError: printNicely('') printNicely( - magenta("I'm afraid we have maximum connection problem with twitter right now :(")) - printNicely(magenta("Let's try again later.")) + magenta("Something wrong with Twitter Oauth right now :(")) + printNicely( + magenta("Please delete ~/.rainbow_oauth and try again.")) save_history() os.system('rm -rf rainbow.db') sys.exit() - + # Spawn stream process p = Process( target=stream, args=( @@ -1694,7 +1683,6 @@ def fly(): args, g['original_name'])) p.start() - # Start listen process time.sleep(0.5) g['reset'] = True