--- /dev/null
+Rainbow Stream\r
+--------------\r
+\r
+Terminal-based Twitter Client. Realtime tweetstream, compose, search ,\r
+favorite … and much more fun directly from terminal.\r
+\r
+This package build on the top of `Python Twitter Tool`_ and `Twitter\r
+Streaming API`_ and inspired by `EarthQuake`_\r
+\r
+Screenshot\r
+----------\r
+\r
+.. figure:: https://raw.githubusercontent.com/DTVD/rainbowstream/master/screenshot/RainbowStreamvSS.png\r
+ :alt: v0.0.1\r
+\r
+\r
+Install\r
+-------\r
+\r
+You will need Python 2.7+ and pip.\r
+\r
+.. code:: bash\r
+\r
+ pip install rainbowstream\r
+\r
+Usage\r
+-----\r
+\r
+The stream\r
+^^^^^^^^^^\r
+\r
+Just type\r
+\r
+.. code:: bash\r
+\r
+ rainbow\r
+\r
+and see your stream.\r
+\r
+In the first time you will be asked for authorization of Rainbow Stream\r
+app at Twitter. Just click the “Authorize access” button and paste PIN\r
+number to the terminal, the rainbow will start.\r
+\r
+The interactive mode\r
+^^^^^^^^^^^^^^^^^^^^\r
+\r
+While your personal stream is continued, you are also ready to tweet,\r
+search, reply, retweet… directly from console. Simply type “h” and hit\r
+the Enter key to see the help\r
+\r
+Input is in interactive mode. It means that you can use arrow key to\r
+move up and down history, tab-autocomplete or 2 tab to view available\r
+suggestion\r
+\r
+Here is full list of supported command\r
+\r
+**Stream Command** ** \r
+\r
+- ``switch public #AKB48`` will switch current stream to public stream and track keyword ``AKB48``\r
+\r
+- ``switch public #AKB48 -f`` will do exactly as above but will ask you\r
+ to provide 2 list:\r
+\r
+ ``Only nicks`` decide what nicks will be include only.\r
+\r
+ ``Ignore nicks`` decide what nicks will be exclude.\r
+\r
+- ``switch public #AKB48 -d`` will apply filter to *ONLY\_LIST* and\r
+ *IGNORE\_LIST*. You can setup 2 list above at ``config.py``\r
+\r
+- ``switch mine`` will switch current stream to personal stream. ``-f``\r
+ and ``-d`` will work as well.\r
+\r
+**Action Command**\r
+\r
+- ``home`` will show your timeline. ``home 10`` will print exactly 10\r
+ tweet.\r
+\r
+- ``view @mdo`` will show @mdo ’s timeline. ``view @dmo 9`` will print\r
+ exactly 9 tweet.\r
+\r
+- ``t the rainbow is god's promise to noah`` will tweet exactly *‘the\r
+ rainbow is god’s promise to noah’*\r
+\r
+- ``rt 12`` will retweet the tweet with *[id=12]*. You can see id of\r
+ each tweet beside the time.\r
+\r
+- ``fav 12`` will favorite the tweet with *[id=12]*.\r
+\r
+- ``rep 12 Really`` will reply *‘Really’* to the tweet with *[id=12]*.\r
+\r
+- ``del 12`` will delete tweet with *[id=12]*.\r
+\r
+- ``ufav 12`` will unfavorite tweet with *[id=12]*.\r
+\r
+- ``s #noah`` will search the word *‘noah’*. Result will come back\r
+ with highlight.\r
+\r
+- ``fr`` will list all friend (You are following people).\r
+\r
+- ``fl`` will list all follower.\r
+\r
+- ``h`` will show the help.\r
+\r
+- ``c`` will clear the screen.\r
+\r
+- ``q`` will quit.\r
+\r
+For example see the screenshot above.\r
+\r
+Bug Report\r
+----------\r
+\r
+Please `create an issue`_ or contact me at\r
+[@dtvd88](https://twitter.com/dtvd88)\r
+\r
+License\r
+-------\r
+\r
+Rainbow Stream are released under an MIT License. See LICENSE.txt for\r
+details\r
+\r
+\r
+.. _Python Twitter Tool: http://mike.verdone.ca/twitter/\r
+.. _Twitter Streaming API: https://dev.twitter.com/docs/api/streaming\r
+.. _EarthQuake: https://github.com/jugyo/earthquake\r
+.. _create an issue: https://github.com/DTVD/rainbowstream/issues/new\r
--- /dev/null
+import random
+import itertools
+from functools import wraps
+from termcolor import *
+from pyfiglet import figlet_format
+
+grey = lambda x: colored(x, 'grey', attrs=['bold'])
+red = lambda x: colored(x, 'red', attrs=['bold'])
+green = lambda x: colored(x, 'green', attrs=['bold'])
+yellow = lambda x: colored(x, 'yellow', attrs=['bold'])
+blue = lambda x: colored(x, 'blue', attrs=['bold'])
+magenta = lambda x: colored(x, 'magenta', attrs=['bold'])
+cyan = lambda x: colored(x, 'cyan', attrs=['bold'])
+white = lambda x: colored(x, 'white', attrs=['bold'])
+
+on_grey = lambda x: colored(x, 'white', 'on_grey', attrs=['bold'])
+on_red = lambda x: colored(x, 'white', 'on_red', attrs=['bold'])
+on_green = lambda x: colored(x, 'white', 'on_green', attrs=['bold'])
+on_yellow = lambda x: colored(x, 'white', 'on_yellow', attrs=['bold'])
+on_blue = lambda x: colored(x, 'white', 'on_blue', attrs=['bold'])
+on_magenta = lambda x: colored(x, 'white', 'on_magenta', attrs=['bold'])
+on_cyan = lambda x: colored(x, 'white', 'on_cyan', attrs=['bold'])
+on_white = lambda x: colored(x, 'white', 'on_white', attrs=['bold'])
+
+colors_shuffle = [grey, red, green, yellow, blue, magenta, cyan]
+background_shuffle = [
+ on_grey,
+ on_red,
+ on_green,
+ on_yellow,
+ on_blue,
+ on_magenta,
+ on_cyan]
+cyc = itertools.cycle(colors_shuffle[1:])
+
+
+def order_rainbow(s):
+ """
+ Print a string with ordered color with each character
+ """
+ c = [colors_shuffle[i % 7](s[i]) for i in xrange(len(s))]
+ return reduce(lambda x, y: x + y, c)
+
+
+def random_rainbow(s):
+ """
+ Print a string with random color with each character
+ """
+ c = [random.choice(colors_shuffle)(i) for i in s]
+ return reduce(lambda x, y: x + y, c)
+
+
+def Memoize(func):
+ """
+ Memoize decorator
+ """
+ cache = {}
+
+ @wraps(func)
+ def wrapper(*args):
+ if args not in cache:
+ cache[args] = func(*args)
+ return cache[args]
+ return wrapper
+
+
+@Memoize
+def cycle_color(s):
+ """
+ Cycle the colors_shuffle
+ """
+ return next(cyc)(s)
+
+
+def ascii_art(text):
+ """
+ Draw the Ascii Art
+ """
+ fi = figlet_format(text, font='doom')
+ print('\n'.join(
+ [next(cyc)(i) for i in fi.split('\n')]
+ )
+ )
--- /dev/null
+"""
+Colorful user's timeline stream
+"""
+from multiprocessing import Process
+from dateutil import parser
+
+import os
+import os.path
+import sys
+import signal
+import argparse
+import time
+import datetime
+
+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 .colors import *
+from .config import *
+from .consumer import *
+from .interactive import *
+from .db import *
+
+g = {}
+db = RainbowDB()
+cmdset = [
+ 'switch',
+ 'home',
+ 'view',
+ 't',
+ 'rt',
+ 'fav',
+ 'rep',
+ 'del',
+ 'ufav',
+ 's',
+ 'fr',
+ 'fl',
+ 'h',
+ 'c',
+ 'q'
+]
+
+
+def draw(t, keyword=None, fil=[], ig=[]):
+ """
+ Draw the rainbow
+ """
+
+ # Retrieve tweet
+ tid = t['id']
+ text = t['text']
+ screen_name = t['user']['screen_name']
+ name = t['user']['name']
+ created_at = t['created_at']
+ favorited = t['favorited']
+ date = parser.parse(created_at)
+ date = date - datetime.timedelta(seconds=time.timezone)
+ clock = date.strftime('%Y/%m/%d %H:%M:%S')
+
+ # Filter and ignore
+ screen_name = '@' + screen_name
+ if fil and screen_name not in fil:
+ return
+ if ig and screen_name in ig:
+ return
+
+ res = db.tweet_query(tid)
+ if not res:
+ db.store(tid)
+ res = db.tweet_query(tid)
+ rid = res[0].rainbow_id
+
+ # Format info
+ user = cycle_color(name) + grey(' ' + screen_name + ' ')
+ meta = grey('[' + clock + '] [id=' + str(rid) + '] ')
+ if favorited:
+ meta = meta + green(u'\u2605')
+ tweet = text.split()
+ # Highlight RT
+ tweet = map(lambda x: grey(x) if x == 'RT' else x, tweet)
+ # Highlight screen_name
+ tweet = map(lambda x: cycle_color(x) if x[0] == '@' else x, tweet)
+ # Highlight link
+ tweet = map(lambda x: cyan(x) if x[0:7] == 'http://' else x, tweet)
+ # Highlight search keyword
+ if keyword:
+ tweet = map(
+ lambda x: on_yellow(x) if
+ ''.join(c for c in x if c.isalnum()).lower() == keyword.lower()
+ else x,
+ tweet
+ )
+ tweet = ' '.join(tweet)
+
+ # Draw rainbow
+ line1 = u"{u:>{uw}}:".format(
+ u=user,
+ uw=len(user) + 2,
+ )
+ line2 = u"{c:>{cw}}".format(
+ c=meta,
+ cw=len(meta) + 2,
+ )
+ line3 = ' ' + tweet
+
+ printNicely('')
+ printNicely(line1)
+ printNicely(line2)
+ printNicely(line3)
+
+
+def parse_arguments():
+ """
+ Parse the arguments
+ """
+ parser = argparse.ArgumentParser(description=__doc__ or "")
+ parser.add_argument(
+ '-to',
+ '--timeout',
+ help='Timeout for the stream (seconds).')
+ parser.add_argument(
+ '-ht',
+ '--heartbeat-timeout',
+ help='Set heartbeat timeout.',
+ default=90)
+ parser.add_argument(
+ '-nb',
+ '--no-block',
+ action='store_true',
+ help='Set stream to non-blocking.')
+ parser.add_argument(
+ '-tt',
+ '--track-keywords',
+ help='Search the stream for specific text.')
+ parser.add_argument(
+ '-fil',
+ '--filter',
+ help='Filter specific screen_name.')
+ parser.add_argument(
+ '-ig',
+ '--ignore',
+ help='Ignore specific screen_name.')
+ return parser.parse_args()
+
+
+def authen():
+ """
+ Authenticate with Twitter OAuth
+ """
+ # When using rainbow stream you must authorize.
+ twitter_credential = os.environ.get(
+ 'HOME',
+ os.environ.get(
+ 'USERPROFILE',
+ '')) + os.sep + '.rainbow_oauth'
+ if not os.path.exists(twitter_credential):
+ oauth_dance("Rainbow Stream",
+ CONSUMER_KEY,
+ CONSUMER_SECRET,
+ twitter_credential)
+ oauth_token, oauth_token_secret = read_token_file(twitter_credential)
+ return OAuth(
+ oauth_token,
+ oauth_token_secret,
+ CONSUMER_KEY,
+ CONSUMER_SECRET)
+
+
+def get_decorated_name():
+ """
+ Beginning of every line
+ """
+ t = Twitter(auth=authen())
+ name = '@' + t.account.verify_credentials()['screen_name']
+ g['original_name'] = name[1:]
+ g['decorated_name'] = grey('[') + grey(name) + grey(']: ')
+
+
+def switch():
+ """
+ Switch stream
+ """
+ try:
+ target = g['stuff'].split()[0]
+
+ # Filter and ignore
+ args = parse_arguments()
+ try:
+ if g['stuff'].split()[-1] == '-f':
+ only = raw_input('Only nicks: ')
+ ignore = raw_input('Ignore nicks: ')
+ args.filter = filter(None, only.split(','))
+ args.ignore = filter(None, ignore.split(','))
+ elif g['stuff'].split()[-1] == '-d':
+ args.filter = ONLY_LIST
+ args.ignore = IGNORE_LIST
+ 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 process
+ os.kill(g['stream_pid'], signal.SIGKILL)
+ args.track_keywords = keyword
+ # Start new process
+ p = Process(
+ target=stream,
+ args=(
+ PUBLIC_DOMAIN,
+ args))
+ p.start()
+ g['stream_pid'] = p.pid
+
+ # Personal stream
+ elif target == 'mine':
+ # Kill old process
+ os.kill(g['stream_pid'], signal.SIGKILL)
+ # Start new process
+ p = Process(
+ target=stream,
+ args=(
+ USER_DOMAIN,
+ args,
+ g['original_name']))
+ 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('')
+ except:
+ printNicely(red('Sorry I can\'t understand.'))
+
+
+def home():
+ """
+ Home
+ """
+ t = Twitter(auth=authen())
+ num = HOME_TWEET_NUM
+ if g['stuff'].isdigit():
+ num = g['stuff']
+ for tweet in reversed(t.statuses.home_timeline(count=num)):
+ draw(t=tweet)
+ printNicely('')
+
+
+def view():
+ """
+ Friend view
+ """
+ t = Twitter(auth=authen())
+ user = g['stuff'].split()[0]
+ if user[0] == '@':
+ try:
+ num = int(g['stuff'].split()[1])
+ except:
+ num = HOME_TWEET_NUM
+ for tweet in reversed(t.statuses.user_timeline(count=num, screen_name=user[1:])):
+ draw(t=tweet)
+ printNicely('')
+ else:
+ printNicely(red('A name should begin with a \'@\''))
+
+
+def tweet():
+ """
+ Tweet
+ """
+ t = Twitter(auth=authen())
+ t.statuses.update(status=g['stuff'])
+
+
+def retweet():
+ """
+ ReTweet
+ """
+ t = Twitter(auth=authen())
+ try:
+ id = int(g['stuff'].split()[0])
+ tid = db.rainbow_query(id)[0].tweet_id
+ t.statuses.retweet(id=tid, include_entities=False, trim_user=True)
+ except:
+ printNicely(red('Sorry I can\'t retweet for you.'))
+
+
+def favorite():
+ """
+ Favorite
+ """
+ t = Twitter(auth=authen())
+ try:
+ id = int(g['stuff'].split()[0])
+ tid = db.rainbow_query(id)[0].tweet_id
+ t.favorites.create(_id=tid, include_entities=False)
+ printNicely(green('Favorited.'))
+ draw(t.statuses.show(id=tid))
+ except:
+ printNicely(red('Omg some syntax is wrong.'))
+
+
+def reply():
+ """
+ Reply
+ """
+ t = Twitter(auth=authen())
+ try:
+ id = int(g['stuff'].split()[0])
+ tid = db.rainbow_query(id)[0].tweet_id
+ user = t.statuses.show(id=tid)['user']['screen_name']
+ status = ' '.join(g['stuff'].split()[1:])
+ status = '@' + user + ' ' + status.decode('utf-8')
+ t.statuses.update(status=status, in_reply_to_status_id=tid)
+ except:
+ printNicely(red('Sorry I can\'t understand.'))
+
+
+def delete():
+ """
+ Delete
+ """
+ t = Twitter(auth=authen())
+ try:
+ id = int(g['stuff'].split()[0])
+ tid = db.rainbow_query(id)[0].tweet_id
+ t.statuses.destroy(id=tid)
+ printNicely(green('Okay it\'s gone.'))
+ except:
+ printNicely(red('Sorry I can\'t delete this tweet for you.'))
+
+
+def unfavorite():
+ """
+ Unfavorite
+ """
+ t = Twitter(auth=authen())
+ try:
+ id = int(g['stuff'].split()[0])
+ tid = db.rainbow_query(id)[0].tweet_id
+ t.favorites.destroy(_id=tid)
+ printNicely(green('Okay it\'s unfavorited.'))
+ draw(t.statuses.show(id=tid))
+ except:
+ printNicely(red('Sorry I can\'t unfavorite this tweet for you.'))
+
+
+def search():
+ """
+ Search
+ """
+ t = Twitter(auth=authen())
+ try:
+ if g['stuff'][0] == '#':
+ rel = t.search.tweets(q=g['stuff'])['statuses']
+ if len(rel):
+ printNicely('Newest tweets:')
+ for i in reversed(xrange(SEARCH_MAX_RECORD)):
+ draw(t=rel[i], keyword=g['stuff'].strip()[1:])
+ printNicely('')
+ else:
+ printNicely(magenta('I\'m afraid there is no result'))
+ else:
+ printNicely(red('A keyword should be a hashtag (like \'#AKB48\')'))
+ except:
+ printNicely(red('Sorry I can\'t understand.'))
+
+
+def friend():
+ """
+ List of friend (following)
+ """
+ t = Twitter(auth=authen())
+ g['friends'] = t.friends.ids()['ids']
+ for i in g['friends']:
+ name = t.users.lookup(user_id=i)[0]['name']
+ screen_name = '@' + t.users.lookup(user_id=i)[0]['screen_name']
+ user = cycle_color(name) + grey(' ' + screen_name + ' ')
+ print user
+
+
+def follower():
+ """
+ List of follower
+ """
+ t = Twitter(auth=authen())
+ g['followers'] = t.followers.ids()['ids']
+ for i in g['followers']:
+ name = t.users.lookup(user_id=i)[0]['name']
+ screen_name = '@' + t.users.lookup(user_id=i)[0]['screen_name']
+ user = cycle_color(name) + grey(' ' + screen_name + ' ')
+ print user
+
+
+def help():
+ """
+ Help
+ """
+ s = ' ' * 2
+ h, w = os.popen('stty size', 'r').read().split()
+
+ 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 * 2 + green('switch public #AKB') + \
+ ' will switch to public stream and follow "' + \
+ yellow('AKB') + '" keyword.\n'
+ usage += s * 2 + green('switch mine') + \
+ ' will switch to your personal stream.\n'
+ usage += s * 2 + green('switch mine -f ') + \
+ ' will prompt to enter the filter.\n'
+ usage += s * 3 + yellow('Only nicks') + \
+ ' filter will decide nicks will be INCLUDE ONLY.\n'
+ usage += s * 3 + yellow('Ignore nicks') + \
+ ' filter will decide nicks will be EXCLUDE.\n'
+ usage += s * 2 + green('switch mine -d') + \
+ ' will use the config\'s ONLY_LIST and IGNORE_LIST.\n'
+ usage += s * 3 + '(see ' + grey('rainbowstream/config.py') + ').\n'
+
+ usage += s + 'For more action: \n'
+ usage += s * 2 + green('home') + ' will show your timeline. ' + \
+ green('home 7') + ' will show 7 tweet.\n'
+ usage += s * 2 + green('view @mdo') + \
+ ' will show ' + yellow('@mdo') + '\'s home.\n'
+ usage += s * 2 + green('t oops ') + \
+ 'will tweet "' + yellow('oops') + '" immediately.\n'
+ usage += s * 2 + \
+ green('rt 12 ') + ' will retweet to tweet with ' + \
+ yellow('[id=12]') + '.\n'
+ usage += s * 2 + \
+ green('fav 12 ') + ' will favorite 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'
+ usage += s * 2 + \
+ green('del 12 ') + ' will delete tweet with ' + \
+ yellow('[id=12]') + '.\n'
+ usage += s * 2 + \
+ green('ufav 12 ') + ' will unfavorite tweet with ' + \
+ yellow('[id=12]') + '.\n'
+ usage += s * 2 + green('s #AKB48') + ' will search for "' + \
+ yellow('AKB48') + '" and return 5 newest tweet.\n'
+ usage += s * 2 + green('fr') + ' will list out your following people.\n'
+ usage += s * 2 + green('fl') + ' will list out your follower.\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 + '-' * (int(w) - 4) + '\n'
+ usage += s + 'Have fun and hang tight!\n'
+ printNicely(usage)
+
+
+def clear():
+ """
+ Clear screen
+ """
+ os.system('clear')
+
+
+def quit():
+ """
+ Exit all
+ """
+ os.system('rm -rf rainbow.db')
+ os.kill(g['stream_pid'], signal.SIGKILL)
+ sys.exit()
+
+
+def reset():
+ """
+ Reset prefix of line
+ """
+ if g['reset']:
+ printNicely(magenta('Need tips ? Type "h" and hit Enter key!'))
+ g['reset'] = False
+
+
+def process(cmd):
+ """
+ Process switch
+ """
+ return dict(zip(
+ cmdset,
+ [
+ switch,
+ home,
+ view,
+ tweet,
+ retweet,
+ favorite,
+ reply,
+ delete,
+ unfavorite,
+ search,
+ friend,
+ follower,
+ help,
+ clear,
+ quit
+ ]
+ )).get(cmd, reset)
+
+
+def listen():
+ """
+ Listen to user's input
+ """
+ d = dict(zip(
+ cmdset,
+ [
+ ['public #', 'mine'], # switch
+ [], # home
+ ['@'], # view
+ [], # tweet
+ [], # retweet
+ [], # reply
+ [], # delete
+ ['#'], # search
+ [], # friend
+ [], # follower
+ [], # help
+ [], # clear
+ [], # quit
+ ]
+ ))
+ init_interactive_shell(d)
+ reset()
+ while True:
+ if g['prefix']:
+ line = raw_input(g['decorated_name'])
+ else:
+ line = raw_input()
+ try:
+ cmd = line.split()[0]
+ except:
+ cmd = ''
+ # Save cmd to global variable and call process
+ g['stuff'] = ' '.join(line.split()[1:])
+ process(cmd)()
+ 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 = {
+ USER_DOMAIN: name,
+ PUBLIC_DOMAIN: args.track_keywords,
+ SITE_DOMAIN: 'Site Stream',
+ }
+ 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)
+
+ if domain == USER_DOMAIN:
+ tweet_iter = stream.user(**query_args)
+ elif domain == SITE_DOMAIN:
+ tweet_iter = stream.site(**query_args)
+ else:
+ if args.track_keywords:
+ 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 --")
+ elif tweet is Timeout:
+ printNicely("-- Timeout --")
+ elif tweet is HeartbeatTimeout:
+ printNicely("-- Heartbeat Timeout --")
+ elif tweet is Hangup:
+ printNicely("-- Hangup --")
+ elif tweet.get('text'):
+ draw(
+ t=tweet,
+ keyword=args.track_keywords,
+ fil=args.filter,
+ ig=args.ignore)
+
+
+def fly():
+ """
+ Main function
+ """
+ # Spawn stream process
+ args = parse_arguments()
+ get_decorated_name()
+ p = Process(target=stream, args=(USER_DOMAIN, args, g['original_name']))
+ p.start()
+
+ # Start listen process
+ time.sleep(0.5)
+ g['reset'] = True
+ g['prefix'] = True
+ g['stream_pid'] = p.pid
+ listen()