update help
[rainbowstream.git] / rainbowstream / rainbow.py
CommitLineData
91476ec3
O
1"""
2Colorful user's timeline stream
3"""
78b81730
O
4from multiprocessing import Process
5from dateutil import parser
6
b2b933a9 7import os
8import os.path
9import sys
10import signal
11import argparse
12import time
13import datetime
991c30af 14import requests
91476ec3 15
91476ec3 16from twitter.stream import TwitterStream, Timeout, HeartbeatTimeout, Hangup
54277114 17from twitter.api import *
91476ec3 18from twitter.oauth import OAuth, read_token_file
8c840a83 19from twitter.oauth_dance import oauth_dance
91476ec3 20from twitter.util import printNicely
991c30af 21from StringIO import StringIO
91476ec3 22
2a6238f5
O
23from .colors import *
24from .config import *
777c52d4 25from .consumer import *
94a5f62e 26from .interactive import *
18cab06a 27from .db import *
991c30af 28from .c_image import *
2a6238f5 29
f405a7d0 30g = {}
18cab06a 31db = RainbowDB()
94a5f62e 32cmdset = [
42fde775 33 'switch',
94a5f62e 34 'home',
35 'view',
36 't',
37 'rt',
7e4ccbf3 38 'fav',
94a5f62e 39 'rep',
40 'del',
7e4ccbf3 41 'ufav',
94a5f62e 42 's',
f5677fb1 43 'show',
94a5f62e 44 'fl',
f5677fb1 45 'ufl',
94a5f62e 46 'h',
47 'c',
48 'q'
49]
22be990e 50
b2b933a9 51
c1fa7c94 52def draw(t, iot=False, keyword=None, fil=[], ig=[]):
91476ec3
O
53 """
54 Draw the rainbow
55 """
d51b4107 56
91476ec3 57 # Retrieve tweet
829cc2d8 58 tid = t['id']
91476ec3
O
59 text = t['text']
60 screen_name = t['user']['screen_name']
61 name = t['user']['name']
62 created_at = t['created_at']
7e4ccbf3 63 favorited = t['favorited']
91476ec3 64 date = parser.parse(created_at)
e20af1c3 65 date = date - datetime.timedelta(seconds=time.timezone)
66 clock = date.strftime('%Y/%m/%d %H:%M:%S')
91476ec3 67
991c30af
O
68 # Get expanded url
69 try:
70 expanded_url = []
71 url = []
72 urls = t['entities']['urls']
73 for u in urls:
74 expanded_url.append(u['expanded_url'])
75 url.append(u['url'])
76 except:
77 expanded_url = None
78 url = None
79
80 # Get media
81 try:
82 media_url = []
83 media = t['entities']['media']
84 for m in media:
f5677fb1 85 media_url.append(m['media_url'])
991c30af
O
86 except:
87 media_url = None
88
d51b4107
O
89 # Filter and ignore
90 screen_name = '@' + screen_name
91 if fil and screen_name not in fil:
92 return
93 if ig and screen_name in ig:
94 return
95
18cab06a
O
96 res = db.tweet_query(tid)
97 if not res:
98 db.store(tid)
99 res = db.tweet_query(tid)
100 rid = res[0].rainbow_id
101
91476ec3 102 # Format info
d51b4107 103 user = cycle_color(name) + grey(' ' + screen_name + ' ')
7e4ccbf3 104 meta = grey('[' + clock + '] [id=' + str(rid) + '] ')
105 if favorited:
106 meta = meta + green(u'\u2605')
8c840a83 107 tweet = text.split()
991c30af
O
108 # Replace url
109 if expanded_url:
110 for index in range(len(expanded_url)):
111 tweet = map(
112 lambda x: expanded_url[index] if x == url[index] else x,
113 tweet)
b8dda704 114 # Highlight RT
2a6238f5 115 tweet = map(lambda x: grey(x) if x == 'RT' else x, tweet)
b8dda704 116 # Highlight screen_name
2a6238f5 117 tweet = map(lambda x: cycle_color(x) if x[0] == '@' else x, tweet)
b8dda704 118 # Highlight link
2a6238f5 119 tweet = map(lambda x: cyan(x) if x[0:7] == 'http://' else x, tweet)
b8dda704 120 # Highlight search keyword
7a431249 121 if keyword:
22be990e 122 tweet = map(
123 lambda x: on_yellow(x) if
124 ''.join(c for c in x if c.isalnum()).lower() == keyword.lower()
125 else x,
126 tweet
127 )
991c30af 128 # Recreate tweet
8c840a83 129 tweet = ' '.join(tweet)
91476ec3
O
130
131 # Draw rainbow
06773ffe 132 line1 = u"{u:>{uw}}:".format(
2a6238f5
O
133 u=user,
134 uw=len(user) + 2,
91476ec3 135 )
06773ffe 136 line2 = u"{c:>{cw}}".format(
829cc2d8
O
137 c=meta,
138 cw=len(meta) + 2,
06773ffe
O
139 )
140 line3 = ' ' + tweet
91476ec3 141
94a5f62e 142 printNicely('')
f405a7d0
O
143 printNicely(line1)
144 printNicely(line2)
145 printNicely(line3)
91476ec3 146
991c30af 147 # Display Image
c1fa7c94 148 if iot and media_url:
f5677fb1
O
149 for mu in media_url:
150 response = requests.get(mu)
151 image_to_display(StringIO(response.content))
991c30af 152
91476ec3
O
153
154def parse_arguments():
155 """
156 Parse the arguments
157 """
91476ec3 158 parser = argparse.ArgumentParser(description=__doc__ or "")
2a6238f5
O
159 parser.add_argument(
160 '-to',
161 '--timeout',
162 help='Timeout for the stream (seconds).')
163 parser.add_argument(
164 '-ht',
165 '--heartbeat-timeout',
166 help='Set heartbeat timeout.',
167 default=90)
168 parser.add_argument(
169 '-nb',
170 '--no-block',
171 action='store_true',
172 help='Set stream to non-blocking.')
173 parser.add_argument(
174 '-tt',
175 '--track-keywords',
176 help='Search the stream for specific text.')
d51b4107
O
177 parser.add_argument(
178 '-fil',
179 '--filter',
180 help='Filter specific screen_name.')
181 parser.add_argument(
182 '-ig',
183 '--ignore',
184 help='Ignore specific screen_name.')
88af38d8 185 parser.add_argument(
c1fa7c94
O
186 '-iot',
187 '--image-on-term',
188 action='store_true',
189 help='Display all image on terminal.')
91476ec3
O
190 return parser.parse_args()
191
192
54277114
O
193def authen():
194 """
7b674cef 195 Authenticate with Twitter OAuth
54277114 196 """
8c840a83 197 # When using rainbow stream you must authorize.
2a6238f5
O
198 twitter_credential = os.environ.get(
199 'HOME',
200 os.environ.get(
201 'USERPROFILE',
202 '')) + os.sep + '.rainbow_oauth'
8c840a83
O
203 if not os.path.exists(twitter_credential):
204 oauth_dance("Rainbow Stream",
205 CONSUMER_KEY,
206 CONSUMER_SECRET,
207 twitter_credential)
208 oauth_token, oauth_token_secret = read_token_file(twitter_credential)
54277114 209 return OAuth(
2a6238f5
O
210 oauth_token,
211 oauth_token_secret,
212 CONSUMER_KEY,
213 CONSUMER_SECRET)
91476ec3 214
54277114
O
215
216def get_decorated_name():
217 """
218 Beginning of every line
219 """
220 t = Twitter(auth=authen())
c5ff542b 221 name = '@' + t.account.verify_credentials()['screen_name']
42fde775 222 g['original_name'] = name[1:]
f405a7d0 223 g['decorated_name'] = grey('[') + grey(name) + grey(']: ')
54277114 224
f405a7d0 225
42fde775 226def switch():
227 """
228 Switch stream
229 """
230 try:
231 target = g['stuff'].split()[0]
232
d51b4107
O
233 # Filter and ignore
234 args = parse_arguments()
7e4ccbf3 235 try:
d51b4107
O
236 if g['stuff'].split()[-1] == '-f':
237 only = raw_input('Only nicks: ')
238 ignore = raw_input('Ignore nicks: ')
7e4ccbf3 239 args.filter = filter(None, only.split(','))
240 args.ignore = filter(None, ignore.split(','))
d51b4107
O
241 elif g['stuff'].split()[-1] == '-d':
242 args.filter = ONLY_LIST
243 args.ignore = IGNORE_LIST
244 except:
245 printNicely(red('Sorry, wrong format.'))
246 return
247
42fde775 248 # Public stream
249 if target == 'public':
250 keyword = g['stuff'].split()[1]
251 if keyword[0] == '#':
252 keyword = keyword[1:]
42fde775 253 # Kill old process
254 os.kill(g['stream_pid'], signal.SIGKILL)
42fde775 255 args.track_keywords = keyword
42fde775 256 # Start new process
257 p = Process(
d51b4107 258 target=stream,
42fde775 259 args=(
d51b4107 260 PUBLIC_DOMAIN,
42fde775 261 args))
262 p.start()
263 g['stream_pid'] = p.pid
264
265 # Personal stream
266 elif target == 'mine':
42fde775 267 # Kill old process
268 os.kill(g['stream_pid'], signal.SIGKILL)
42fde775 269 # Start new process
270 p = Process(
271 target=stream,
272 args=(
273 USER_DOMAIN,
274 args,
275 g['original_name']))
276 p.start()
277 g['stream_pid'] = p.pid
d51b4107 278 printNicely('')
1551a7d3 279 printNicely(green('Stream switched.'))
d51b4107
O
280 if args.filter:
281 printNicely(cyan('Only: ' + str(args.filter)))
282 if args.ignore:
283 printNicely(red('Ignore: ' + str(args.ignore)))
284 printNicely('')
42fde775 285 except:
286 printNicely(red('Sorry I can\'t understand.'))
42fde775 287
288
7b674cef 289def home():
290 """
291 Home
292 """
293 t = Twitter(auth=authen())
94a5f62e 294 num = HOME_TWEET_NUM
7b674cef 295 if g['stuff'].isdigit():
94a5f62e 296 num = g['stuff']
297 for tweet in reversed(t.statuses.home_timeline(count=num)):
c1fa7c94 298 draw(t=tweet, iot=g['iot'])
94a5f62e 299 printNicely('')
7b674cef 300
301
302def view():
303 """
304 Friend view
305 """
306 t = Twitter(auth=authen())
307 user = g['stuff'].split()[0]
b8fbcb70 308 if user[0] == '@':
309 try:
94a5f62e 310 num = int(g['stuff'].split()[1])
b8fbcb70 311 except:
94a5f62e 312 num = HOME_TWEET_NUM
313 for tweet in reversed(t.statuses.user_timeline(count=num, screen_name=user[1:])):
c1fa7c94 314 draw(t=tweet, iot=g['iot'])
94a5f62e 315 printNicely('')
b8fbcb70 316 else:
c91f75f2 317 printNicely(red('A name should begin with a \'@\''))
7b674cef 318
319
f405a7d0 320def tweet():
54277114 321 """
7b674cef 322 Tweet
54277114
O
323 """
324 t = Twitter(auth=authen())
f405a7d0 325 t.statuses.update(status=g['stuff'])
f405a7d0 326
b2b933a9 327
1ba4abfd
O
328def retweet():
329 """
330 ReTweet
331 """
332 t = Twitter(auth=authen())
333 try:
334 id = int(g['stuff'].split()[0])
335 tid = db.rainbow_query(id)[0].tweet_id
b2b933a9 336 t.statuses.retweet(id=tid, include_entities=False, trim_user=True)
1ba4abfd 337 except:
c91f75f2 338 printNicely(red('Sorry I can\'t retweet for you.'))
1ba4abfd
O
339
340
7e4ccbf3 341def favorite():
342 """
343 Favorite
344 """
345 t = Twitter(auth=authen())
346 try:
347 id = int(g['stuff'].split()[0])
348 tid = db.rainbow_query(id)[0].tweet_id
349 t.favorites.create(_id=tid, include_entities=False)
350 printNicely(green('Favorited.'))
c1fa7c94 351 draw(t.statuses.show(id=tid), iot=g['iot'])
7e4ccbf3 352 except:
353 printNicely(red('Omg some syntax is wrong.'))
354
355
7b674cef 356def reply():
829cc2d8 357 """
7b674cef 358 Reply
829cc2d8
O
359 """
360 t = Twitter(auth=authen())
7b674cef 361 try:
362 id = int(g['stuff'].split()[0])
18cab06a
O
363 tid = db.rainbow_query(id)[0].tweet_id
364 user = t.statuses.show(id=tid)['user']['screen_name']
7b674cef 365 status = ' '.join(g['stuff'].split()[1:])
366 status = '@' + user + ' ' + status.decode('utf-8')
18cab06a 367 t.statuses.update(status=status, in_reply_to_status_id=tid)
7b674cef 368 except:
c91f75f2 369 printNicely(red('Sorry I can\'t understand.'))
7b674cef 370
371
372def delete():
373 """
374 Delete
375 """
376 t = Twitter(auth=authen())
377 try:
378 id = int(g['stuff'].split()[0])
18cab06a
O
379 tid = db.rainbow_query(id)[0].tweet_id
380 t.statuses.destroy(id=tid)
c91f75f2 381 printNicely(green('Okay it\'s gone.'))
7b674cef 382 except:
c91f75f2 383 printNicely(red('Sorry I can\'t delete this tweet for you.'))
829cc2d8
O
384
385
7e4ccbf3 386def unfavorite():
387 """
388 Unfavorite
389 """
390 t = Twitter(auth=authen())
391 try:
392 id = int(g['stuff'].split()[0])
393 tid = db.rainbow_query(id)[0].tweet_id
394 t.favorites.destroy(_id=tid)
395 printNicely(green('Okay it\'s unfavorited.'))
c1fa7c94 396 draw(t.statuses.show(id=tid), iot=g['iot'])
7e4ccbf3 397 except:
398 printNicely(red('Sorry I can\'t unfavorite this tweet for you.'))
399
400
f405a7d0
O
401def search():
402 """
7b674cef 403 Search
f405a7d0
O
404 """
405 t = Twitter(auth=authen())
94a5f62e 406 try:
407 if g['stuff'][0] == '#':
408 rel = t.search.tweets(q=g['stuff'])['statuses']
c91f75f2 409 if len(rel):
410 printNicely('Newest tweets:')
411 for i in reversed(xrange(SEARCH_MAX_RECORD)):
88af38d8 412 draw(t=rel[i],
c1fa7c94 413 iot=g['iot'],
88af38d8 414 keyword=g['stuff'].strip()[1:])
c91f75f2 415 printNicely('')
416 else:
417 printNicely(magenta('I\'m afraid there is no result'))
94a5f62e 418 else:
c91f75f2 419 printNicely(red('A keyword should be a hashtag (like \'#AKB48\')'))
94a5f62e 420 except:
c91f75f2 421 printNicely(red('Sorry I can\'t understand.'))
b2b933a9 422
f405a7d0 423
f5677fb1 424def show():
843647ad 425 """
f5677fb1 426 Show image
843647ad
O
427 """
428 t = Twitter(auth=authen())
f5677fb1
O
429 try:
430 target = g['stuff'].split()[0]
431 if target != 'image':
432 return
433 id = int(g['stuff'].split()[1])
434 tid = db.rainbow_query(id)[0].tweet_id
435 tweet = t.statuses.show(id=tid)
436 media = tweet['entities']['media']
437 for m in media:
438 res = requests.get(m['media_url'])
439 img = Image.open(StringIO(res.content))
440 img.show()
441 except:
442 printNicely(red('Sorry I can\'t show this image.'))
843647ad
O
443
444
f5677fb1 445def follow():
843647ad 446 """
f5677fb1 447 Follow a user
843647ad
O
448 """
449 t = Twitter(auth=authen())
f5677fb1
O
450 screen_name = g['stuff'].split()[0]
451 if screen_name[0] == '@':
452 try :
453 t.friendships.create(screen_name=screen_name[1:],follow=True)
454 printNicely(green('You are following ' + screen_name + ' now!'))
455 except:
456 printNicely(red('Sorry can not follow at this time.'))
457 else:
458 printNicely(red('Sorry I can\'t understand.'))
459
460
461def unfollow():
462 """
463 Unfollow a user
464 """
465 t = Twitter(auth=authen())
466 screen_name = g['stuff'].split()[0]
467 if screen_name[0] == '@':
468 try :
469 t.friendships.destroy(screen_name=screen_name[1:],include_entities=False)
470 printNicely(green('Unfollow ' + screen_name + ' success!'))
471 except:
472 printNicely(red('Sorry can not unfollow at this time.'))
473 else:
474 printNicely(red('Sorry I can\'t understand.'))
843647ad
O
475
476
f405a7d0
O
477def help():
478 """
7b674cef 479 Help
f405a7d0 480 """
7e4ccbf3 481 s = ' ' * 2
482 h, w = os.popen('stty size', 'r').read().split()
e3885f55
O
483
484 usage = '\n'
485 usage += s + 'Hi boss! I\'m ready to serve you right now!\n'
7e4ccbf3 486 usage += s + '-' * (int(w) - 4) + '\n'
487
488 usage += s + 'You are ' + yellow('already') + ' on your personal stream.\n'
489 usage += s * 2 + green('switch public #AKB') + \
490 ' will switch to public stream and follow "' + \
491 yellow('AKB') + '" keyword.\n'
492 usage += s * 2 + green('switch mine') + \
493 ' will switch to your personal stream.\n'
494 usage += s * 2 + green('switch mine -f ') + \
495 ' will prompt to enter the filter.\n'
496 usage += s * 3 + yellow('Only nicks') + \
497 ' filter will decide nicks will be INCLUDE ONLY.\n'
498 usage += s * 3 + yellow('Ignore nicks') + \
499 ' filter will decide nicks will be EXCLUDE.\n'
500 usage += s * 2 + green('switch mine -d') + \
501 ' will use the config\'s ONLY_LIST and IGNORE_LIST.\n'
502 usage += s * 3 + '(see ' + grey('rainbowstream/config.py') + ').\n'
e3885f55
O
503
504 usage += s + 'For more action: \n'
7e4ccbf3 505 usage += s * 2 + green('home') + ' will show your timeline. ' + \
506 green('home 7') + ' will show 7 tweet.\n'
507 usage += s * 2 + green('view @mdo') + \
508 ' will show ' + yellow('@mdo') + '\'s home.\n'
509 usage += s * 2 + green('t oops ') + \
510 'will tweet "' + yellow('oops') + '" immediately.\n'
511 usage += s * 2 + \
512 green('rt 12 ') + ' will retweet to tweet with ' + \
513 yellow('[id=12]') + '.\n'
514 usage += s * 2 + \
515 green('fav 12 ') + ' will favorite the tweet with ' + \
516 yellow('[id=12]') + '.\n'
517 usage += s * 2 + green('rep 12 oops') + ' will reply "' + \
518 yellow('oops') + '" to tweet with ' + yellow('[id=12]') + '.\n'
519 usage += s * 2 + \
520 green('del 12 ') + ' will delete tweet with ' + \
521 yellow('[id=12]') + '.\n'
522 usage += s * 2 + \
523 green('ufav 12 ') + ' will unfavorite tweet with ' + \
524 yellow('[id=12]') + '.\n'
525 usage += s * 2 + green('s #AKB48') + ' will search for "' + \
526 yellow('AKB48') + '" and return 5 newest tweet.\n'
a99b7b04
O
527 usage += s * 2 + green('show image 12') + ' will show image in tweet with ' + \
528 yellow('[id=12]') + ' in your OS\'s image viewer.\n'
f5677fb1
O
529 usage += s * 2 + green('fl @dtvd88') + ' will follow ' + \
530 yellow('@dtvd88') + '.\n'
531 usage += s * 2 + green('ufl @dtvd88') + ' will unfollow ' + \
532 yellow('@dtvd88') + '.\n'
7e4ccbf3 533 usage += s * 2 + green('h') + ' will show this help again.\n'
534 usage += s * 2 + green('c') + ' will clear the screen.\n'
535 usage += s * 2 + green('q') + ' will quit.\n'
536
537 usage += s + '-' * (int(w) - 4) + '\n'
e3885f55 538 usage += s + 'Have fun and hang tight!\n'
f405a7d0 539 printNicely(usage)
f405a7d0
O
540
541
843647ad 542def clear():
f405a7d0 543 """
7b674cef 544 Clear screen
f405a7d0 545 """
843647ad 546 os.system('clear')
f405a7d0
O
547
548
843647ad 549def quit():
b8dda704
O
550 """
551 Exit all
552 """
f5677fb1 553 save_history()
8e633322 554 os.system('rm -rf rainbow.db')
843647ad
O
555 os.kill(g['stream_pid'], signal.SIGKILL)
556 sys.exit()
b8dda704
O
557
558
94a5f62e 559def reset():
f405a7d0 560 """
94a5f62e 561 Reset prefix of line
f405a7d0 562 """
c91f75f2 563 if g['reset']:
e3885f55 564 printNicely(magenta('Need tips ? Type "h" and hit Enter key!'))
c91f75f2 565 g['reset'] = False
54277114
O
566
567
94a5f62e 568def process(cmd):
54277114 569 """
94a5f62e 570 Process switch
54277114 571 """
94a5f62e 572 return dict(zip(
573 cmdset,
b2b933a9 574 [
42fde775 575 switch,
b2b933a9 576 home,
577 view,
578 tweet,
579 retweet,
7e4ccbf3 580 favorite,
b2b933a9 581 reply,
582 delete,
7e4ccbf3 583 unfavorite,
b2b933a9 584 search,
f5677fb1
O
585 show,
586 follow,
587 unfollow,
b2b933a9 588 help,
589 clear,
590 quit
591 ]
94a5f62e 592 )).get(cmd, reset)
593
594
595def listen():
42fde775 596 """
597 Listen to user's input
598 """
d51b4107
O
599 d = dict(zip(
600 cmdset,
601 [
7e4ccbf3 602 ['public #', 'mine'], # switch
603 [], # home
604 ['@'], # view
605 [], # tweet
606 [], # retweet
f5677fb1 607 [], # favorite
7e4ccbf3 608 [], # reply
609 [], # delete
f5677fb1 610 [], # unfavorite
7e4ccbf3 611 ['#'], # search
f5677fb1
O
612 ['image'], # show image
613 [], # follow
614 [], # unfollow
7e4ccbf3 615 [], # help
616 [], # clear
617 [], # quit
d51b4107 618 ]
7e4ccbf3 619 ))
d51b4107 620 init_interactive_shell(d)
f5677fb1 621 read_history()
819569e8 622 reset()
b2b933a9 623 while True:
1dd312f5
O
624 if g['prefix']:
625 line = raw_input(g['decorated_name'])
626 else:
627 line = raw_input()
843647ad
O
628 try:
629 cmd = line.split()[0]
630 except:
631 cmd = ''
f405a7d0 632 # Save cmd to global variable and call process
843647ad
O
633 g['stuff'] = ' '.join(line.split()[1:])
634 process(cmd)()
7e4ccbf3 635 if cmd in ['switch', 't', 'rt', 'rep']:
1dd312f5
O
636 g['prefix'] = False
637 else:
638 g['prefix'] = True
54277114
O
639
640
42fde775 641def stream(domain, args, name='Rainbow Stream'):
54277114 642 """
f405a7d0 643 Track the stream
54277114 644 """
d51b4107 645
54277114 646 # The Logo
42fde775 647 art_dict = {
648 USER_DOMAIN: name,
649 PUBLIC_DOMAIN: args.track_keywords,
650 SITE_DOMAIN: 'Site Stream',
651 }
652 ascii_art(art_dict[domain])
d51b4107 653
91476ec3
O
654 # These arguments are optional:
655 stream_args = dict(
656 timeout=args.timeout,
657 block=not args.no_block,
658 heartbeat_timeout=args.heartbeat_timeout)
659
660 # Track keyword
661 query_args = dict()
662 if args.track_keywords:
663 query_args['track'] = args.track_keywords
664
665 # Get stream
2a6238f5 666 stream = TwitterStream(
22be990e 667 auth=authen(),
42fde775 668 domain=domain,
2a6238f5 669 **stream_args)
91476ec3 670
42fde775 671 if domain == USER_DOMAIN:
672 tweet_iter = stream.user(**query_args)
673 elif domain == SITE_DOMAIN:
674 tweet_iter = stream.site(**query_args)
675 else:
676 if args.track_keywords:
677 tweet_iter = stream.statuses.filter(**query_args)
678 else:
679 tweet_iter = stream.statuses.sample()
680
681 # Iterate over the stream.
91476ec3
O
682 for tweet in tweet_iter:
683 if tweet is None:
684 printNicely("-- None --")
685 elif tweet is Timeout:
686 printNicely("-- Timeout --")
687 elif tweet is HeartbeatTimeout:
688 printNicely("-- Heartbeat Timeout --")
689 elif tweet is Hangup:
690 printNicely("-- Hangup --")
691 elif tweet.get('text'):
7e4ccbf3 692 draw(
693 t=tweet,
c1fa7c94 694 iot=args.image_on_term,
7e4ccbf3 695 keyword=args.track_keywords,
696 fil=args.filter,
88af38d8
O
697 ig=args.ignore,
698 )
54277114
O
699
700
701def fly():
702 """
703 Main function
704 """
42fde775 705 # Spawn stream process
706 args = parse_arguments()
54277114 707 get_decorated_name()
42fde775 708 p = Process(target=stream, args=(USER_DOMAIN, args, g['original_name']))
709 p.start()
710
711 # Start listen process
819569e8 712 time.sleep(0.5)
c91f75f2 713 g['reset'] = True
1dd312f5 714 g['prefix'] = True
f405a7d0 715 g['stream_pid'] = p.pid
c1fa7c94 716 g['iot'] = args.image_on_term
88af38d8 717 listen()