image viewer + input history + follow + unfollow
[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
88af38d8 52def draw(t, imgflg = 0, 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
88af38d8 148 if imgflg 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
O
185 parser.add_argument(
186 '-img',
187 '--image',
188 help='Display all photo on terminal.')
91476ec3
O
189 return parser.parse_args()
190
191
54277114
O
192def authen():
193 """
7b674cef 194 Authenticate with Twitter OAuth
54277114 195 """
8c840a83 196 # When using rainbow stream you must authorize.
2a6238f5
O
197 twitter_credential = os.environ.get(
198 'HOME',
199 os.environ.get(
200 'USERPROFILE',
201 '')) + os.sep + '.rainbow_oauth'
8c840a83
O
202 if not os.path.exists(twitter_credential):
203 oauth_dance("Rainbow Stream",
204 CONSUMER_KEY,
205 CONSUMER_SECRET,
206 twitter_credential)
207 oauth_token, oauth_token_secret = read_token_file(twitter_credential)
54277114 208 return OAuth(
2a6238f5
O
209 oauth_token,
210 oauth_token_secret,
211 CONSUMER_KEY,
212 CONSUMER_SECRET)
91476ec3 213
54277114
O
214
215def get_decorated_name():
216 """
217 Beginning of every line
218 """
219 t = Twitter(auth=authen())
c5ff542b 220 name = '@' + t.account.verify_credentials()['screen_name']
42fde775 221 g['original_name'] = name[1:]
f405a7d0 222 g['decorated_name'] = grey('[') + grey(name) + grey(']: ')
54277114 223
f405a7d0 224
42fde775 225def switch():
226 """
227 Switch stream
228 """
229 try:
230 target = g['stuff'].split()[0]
231
d51b4107
O
232 # Filter and ignore
233 args = parse_arguments()
7e4ccbf3 234 try:
d51b4107
O
235 if g['stuff'].split()[-1] == '-f':
236 only = raw_input('Only nicks: ')
237 ignore = raw_input('Ignore nicks: ')
7e4ccbf3 238 args.filter = filter(None, only.split(','))
239 args.ignore = filter(None, ignore.split(','))
d51b4107
O
240 elif g['stuff'].split()[-1] == '-d':
241 args.filter = ONLY_LIST
242 args.ignore = IGNORE_LIST
243 except:
244 printNicely(red('Sorry, wrong format.'))
245 return
246
42fde775 247 # Public stream
248 if target == 'public':
249 keyword = g['stuff'].split()[1]
250 if keyword[0] == '#':
251 keyword = keyword[1:]
42fde775 252 # Kill old process
253 os.kill(g['stream_pid'], signal.SIGKILL)
42fde775 254 args.track_keywords = keyword
42fde775 255 # Start new process
256 p = Process(
d51b4107 257 target=stream,
42fde775 258 args=(
d51b4107 259 PUBLIC_DOMAIN,
42fde775 260 args))
261 p.start()
262 g['stream_pid'] = p.pid
263
264 # Personal stream
265 elif target == 'mine':
42fde775 266 # Kill old process
267 os.kill(g['stream_pid'], signal.SIGKILL)
42fde775 268 # Start new process
269 p = Process(
270 target=stream,
271 args=(
272 USER_DOMAIN,
273 args,
274 g['original_name']))
275 p.start()
276 g['stream_pid'] = p.pid
d51b4107 277 printNicely('')
1551a7d3 278 printNicely(green('Stream switched.'))
d51b4107
O
279 if args.filter:
280 printNicely(cyan('Only: ' + str(args.filter)))
281 if args.ignore:
282 printNicely(red('Ignore: ' + str(args.ignore)))
283 printNicely('')
42fde775 284 except:
285 printNicely(red('Sorry I can\'t understand.'))
42fde775 286
287
7b674cef 288def home():
289 """
290 Home
291 """
292 t = Twitter(auth=authen())
94a5f62e 293 num = HOME_TWEET_NUM
7b674cef 294 if g['stuff'].isdigit():
94a5f62e 295 num = g['stuff']
296 for tweet in reversed(t.statuses.home_timeline(count=num)):
88af38d8 297 draw(t=tweet, imgflg=g['image'])
94a5f62e 298 printNicely('')
7b674cef 299
300
301def view():
302 """
303 Friend view
304 """
305 t = Twitter(auth=authen())
306 user = g['stuff'].split()[0]
b8fbcb70 307 if user[0] == '@':
308 try:
94a5f62e 309 num = int(g['stuff'].split()[1])
b8fbcb70 310 except:
94a5f62e 311 num = HOME_TWEET_NUM
312 for tweet in reversed(t.statuses.user_timeline(count=num, screen_name=user[1:])):
88af38d8 313 draw(t=tweet, imgflg=g['image'])
94a5f62e 314 printNicely('')
b8fbcb70 315 else:
c91f75f2 316 printNicely(red('A name should begin with a \'@\''))
7b674cef 317
318
f405a7d0 319def tweet():
54277114 320 """
7b674cef 321 Tweet
54277114
O
322 """
323 t = Twitter(auth=authen())
f405a7d0 324 t.statuses.update(status=g['stuff'])
f405a7d0 325
b2b933a9 326
1ba4abfd
O
327def retweet():
328 """
329 ReTweet
330 """
331 t = Twitter(auth=authen())
332 try:
333 id = int(g['stuff'].split()[0])
334 tid = db.rainbow_query(id)[0].tweet_id
b2b933a9 335 t.statuses.retweet(id=tid, include_entities=False, trim_user=True)
1ba4abfd 336 except:
c91f75f2 337 printNicely(red('Sorry I can\'t retweet for you.'))
1ba4abfd
O
338
339
7e4ccbf3 340def favorite():
341 """
342 Favorite
343 """
344 t = Twitter(auth=authen())
345 try:
346 id = int(g['stuff'].split()[0])
347 tid = db.rainbow_query(id)[0].tweet_id
348 t.favorites.create(_id=tid, include_entities=False)
349 printNicely(green('Favorited.'))
88af38d8 350 draw(t.statuses.show(id=tid), imgflg=g['image'])
7e4ccbf3 351 except:
352 printNicely(red('Omg some syntax is wrong.'))
353
354
7b674cef 355def reply():
829cc2d8 356 """
7b674cef 357 Reply
829cc2d8
O
358 """
359 t = Twitter(auth=authen())
7b674cef 360 try:
361 id = int(g['stuff'].split()[0])
18cab06a
O
362 tid = db.rainbow_query(id)[0].tweet_id
363 user = t.statuses.show(id=tid)['user']['screen_name']
7b674cef 364 status = ' '.join(g['stuff'].split()[1:])
365 status = '@' + user + ' ' + status.decode('utf-8')
18cab06a 366 t.statuses.update(status=status, in_reply_to_status_id=tid)
7b674cef 367 except:
c91f75f2 368 printNicely(red('Sorry I can\'t understand.'))
7b674cef 369
370
371def delete():
372 """
373 Delete
374 """
375 t = Twitter(auth=authen())
376 try:
377 id = int(g['stuff'].split()[0])
18cab06a
O
378 tid = db.rainbow_query(id)[0].tweet_id
379 t.statuses.destroy(id=tid)
c91f75f2 380 printNicely(green('Okay it\'s gone.'))
7b674cef 381 except:
c91f75f2 382 printNicely(red('Sorry I can\'t delete this tweet for you.'))
829cc2d8
O
383
384
7e4ccbf3 385def unfavorite():
386 """
387 Unfavorite
388 """
389 t = Twitter(auth=authen())
390 try:
391 id = int(g['stuff'].split()[0])
392 tid = db.rainbow_query(id)[0].tweet_id
393 t.favorites.destroy(_id=tid)
394 printNicely(green('Okay it\'s unfavorited.'))
88af38d8 395 draw(t.statuses.show(id=tid), imgflg=g['image'])
7e4ccbf3 396 except:
397 printNicely(red('Sorry I can\'t unfavorite this tweet for you.'))
398
399
f405a7d0
O
400def search():
401 """
7b674cef 402 Search
f405a7d0
O
403 """
404 t = Twitter(auth=authen())
94a5f62e 405 try:
406 if g['stuff'][0] == '#':
407 rel = t.search.tweets(q=g['stuff'])['statuses']
c91f75f2 408 if len(rel):
409 printNicely('Newest tweets:')
410 for i in reversed(xrange(SEARCH_MAX_RECORD)):
88af38d8
O
411 draw(t=rel[i],
412 imgflg=g['image'],
413 keyword=g['stuff'].strip()[1:])
c91f75f2 414 printNicely('')
415 else:
416 printNicely(magenta('I\'m afraid there is no result'))
94a5f62e 417 else:
c91f75f2 418 printNicely(red('A keyword should be a hashtag (like \'#AKB48\')'))
94a5f62e 419 except:
c91f75f2 420 printNicely(red('Sorry I can\'t understand.'))
b2b933a9 421
f405a7d0 422
f5677fb1 423def show():
843647ad 424 """
f5677fb1 425 Show image
843647ad
O
426 """
427 t = Twitter(auth=authen())
f5677fb1
O
428 try:
429 target = g['stuff'].split()[0]
430 if target != 'image':
431 return
432 id = int(g['stuff'].split()[1])
433 tid = db.rainbow_query(id)[0].tweet_id
434 tweet = t.statuses.show(id=tid)
435 media = tweet['entities']['media']
436 for m in media:
437 res = requests.get(m['media_url'])
438 img = Image.open(StringIO(res.content))
439 img.show()
440 except:
441 printNicely(red('Sorry I can\'t show this image.'))
843647ad
O
442
443
f5677fb1 444def follow():
843647ad 445 """
f5677fb1 446 Follow a user
843647ad
O
447 """
448 t = Twitter(auth=authen())
f5677fb1
O
449 screen_name = g['stuff'].split()[0]
450 if screen_name[0] == '@':
451 try :
452 t.friendships.create(screen_name=screen_name[1:],follow=True)
453 printNicely(green('You are following ' + screen_name + ' now!'))
454 except:
455 printNicely(red('Sorry can not follow at this time.'))
456 else:
457 printNicely(red('Sorry I can\'t understand.'))
458
459
460def unfollow():
461 """
462 Unfollow a user
463 """
464 t = Twitter(auth=authen())
465 screen_name = g['stuff'].split()[0]
466 if screen_name[0] == '@':
467 try :
468 t.friendships.destroy(screen_name=screen_name[1:],include_entities=False)
469 printNicely(green('Unfollow ' + screen_name + ' success!'))
470 except:
471 printNicely(red('Sorry can not unfollow at this time.'))
472 else:
473 printNicely(red('Sorry I can\'t understand.'))
843647ad
O
474
475
f405a7d0
O
476def help():
477 """
7b674cef 478 Help
f405a7d0 479 """
7e4ccbf3 480 s = ' ' * 2
481 h, w = os.popen('stty size', 'r').read().split()
e3885f55
O
482
483 usage = '\n'
484 usage += s + 'Hi boss! I\'m ready to serve you right now!\n'
7e4ccbf3 485 usage += s + '-' * (int(w) - 4) + '\n'
486
487 usage += s + 'You are ' + yellow('already') + ' on your personal stream.\n'
488 usage += s * 2 + green('switch public #AKB') + \
489 ' will switch to public stream and follow "' + \
490 yellow('AKB') + '" keyword.\n'
491 usage += s * 2 + green('switch mine') + \
492 ' will switch to your personal stream.\n'
493 usage += s * 2 + green('switch mine -f ') + \
494 ' will prompt to enter the filter.\n'
495 usage += s * 3 + yellow('Only nicks') + \
496 ' filter will decide nicks will be INCLUDE ONLY.\n'
497 usage += s * 3 + yellow('Ignore nicks') + \
498 ' filter will decide nicks will be EXCLUDE.\n'
499 usage += s * 2 + green('switch mine -d') + \
500 ' will use the config\'s ONLY_LIST and IGNORE_LIST.\n'
501 usage += s * 3 + '(see ' + grey('rainbowstream/config.py') + ').\n'
e3885f55
O
502
503 usage += s + 'For more action: \n'
7e4ccbf3 504 usage += s * 2 + green('home') + ' will show your timeline. ' + \
505 green('home 7') + ' will show 7 tweet.\n'
506 usage += s * 2 + green('view @mdo') + \
507 ' will show ' + yellow('@mdo') + '\'s home.\n'
508 usage += s * 2 + green('t oops ') + \
509 'will tweet "' + yellow('oops') + '" immediately.\n'
510 usage += s * 2 + \
511 green('rt 12 ') + ' will retweet to tweet with ' + \
512 yellow('[id=12]') + '.\n'
513 usage += s * 2 + \
514 green('fav 12 ') + ' will favorite the tweet with ' + \
515 yellow('[id=12]') + '.\n'
516 usage += s * 2 + green('rep 12 oops') + ' will reply "' + \
517 yellow('oops') + '" to tweet with ' + yellow('[id=12]') + '.\n'
518 usage += s * 2 + \
519 green('del 12 ') + ' will delete tweet with ' + \
520 yellow('[id=12]') + '.\n'
521 usage += s * 2 + \
522 green('ufav 12 ') + ' will unfavorite tweet with ' + \
523 yellow('[id=12]') + '.\n'
524 usage += s * 2 + green('s #AKB48') + ' will search for "' + \
525 yellow('AKB48') + '" and return 5 newest tweet.\n'
f5677fb1
O
526 usage += s * 2 + green('show image 12') + ' will show image in ' + \
527 yellow('[id=12]') + 'in your OS\'s image viewer.\n'
528 usage += s * 2 + green('fl @dtvd88') + ' will follow ' + \
529 yellow('@dtvd88') + '.\n'
530 usage += s * 2 + green('ufl @dtvd88') + ' will unfollow ' + \
531 yellow('@dtvd88') + '.\n'
7e4ccbf3 532 usage += s * 2 + green('h') + ' will show this help again.\n'
533 usage += s * 2 + green('c') + ' will clear the screen.\n'
534 usage += s * 2 + green('q') + ' will quit.\n'
535
536 usage += s + '-' * (int(w) - 4) + '\n'
e3885f55 537 usage += s + 'Have fun and hang tight!\n'
f405a7d0 538 printNicely(usage)
f405a7d0
O
539
540
843647ad 541def clear():
f405a7d0 542 """
7b674cef 543 Clear screen
f405a7d0 544 """
843647ad 545 os.system('clear')
f405a7d0
O
546
547
843647ad 548def quit():
b8dda704
O
549 """
550 Exit all
551 """
f5677fb1 552 save_history()
8e633322 553 os.system('rm -rf rainbow.db')
843647ad
O
554 os.kill(g['stream_pid'], signal.SIGKILL)
555 sys.exit()
b8dda704
O
556
557
94a5f62e 558def reset():
f405a7d0 559 """
94a5f62e 560 Reset prefix of line
f405a7d0 561 """
c91f75f2 562 if g['reset']:
e3885f55 563 printNicely(magenta('Need tips ? Type "h" and hit Enter key!'))
c91f75f2 564 g['reset'] = False
54277114
O
565
566
94a5f62e 567def process(cmd):
54277114 568 """
94a5f62e 569 Process switch
54277114 570 """
94a5f62e 571 return dict(zip(
572 cmdset,
b2b933a9 573 [
42fde775 574 switch,
b2b933a9 575 home,
576 view,
577 tweet,
578 retweet,
7e4ccbf3 579 favorite,
b2b933a9 580 reply,
581 delete,
7e4ccbf3 582 unfavorite,
b2b933a9 583 search,
f5677fb1
O
584 show,
585 follow,
586 unfollow,
b2b933a9 587 help,
588 clear,
589 quit
590 ]
94a5f62e 591 )).get(cmd, reset)
592
593
594def listen():
42fde775 595 """
596 Listen to user's input
597 """
d51b4107
O
598 d = dict(zip(
599 cmdset,
600 [
7e4ccbf3 601 ['public #', 'mine'], # switch
602 [], # home
603 ['@'], # view
604 [], # tweet
605 [], # retweet
f5677fb1 606 [], # favorite
7e4ccbf3 607 [], # reply
608 [], # delete
f5677fb1 609 [], # unfavorite
7e4ccbf3 610 ['#'], # search
f5677fb1
O
611 ['image'], # show image
612 [], # follow
613 [], # unfollow
7e4ccbf3 614 [], # help
615 [], # clear
616 [], # quit
d51b4107 617 ]
7e4ccbf3 618 ))
d51b4107 619 init_interactive_shell(d)
f5677fb1 620 read_history()
819569e8 621 reset()
b2b933a9 622 while True:
1dd312f5
O
623 if g['prefix']:
624 line = raw_input(g['decorated_name'])
625 else:
626 line = raw_input()
843647ad
O
627 try:
628 cmd = line.split()[0]
629 except:
630 cmd = ''
f405a7d0 631 # Save cmd to global variable and call process
843647ad
O
632 g['stuff'] = ' '.join(line.split()[1:])
633 process(cmd)()
7e4ccbf3 634 if cmd in ['switch', 't', 'rt', 'rep']:
1dd312f5
O
635 g['prefix'] = False
636 else:
637 g['prefix'] = True
54277114
O
638
639
42fde775 640def stream(domain, args, name='Rainbow Stream'):
54277114 641 """
f405a7d0 642 Track the stream
54277114 643 """
d51b4107 644
54277114 645 # The Logo
42fde775 646 art_dict = {
647 USER_DOMAIN: name,
648 PUBLIC_DOMAIN: args.track_keywords,
649 SITE_DOMAIN: 'Site Stream',
650 }
651 ascii_art(art_dict[domain])
d51b4107 652
91476ec3
O
653 # These arguments are optional:
654 stream_args = dict(
655 timeout=args.timeout,
656 block=not args.no_block,
657 heartbeat_timeout=args.heartbeat_timeout)
658
659 # Track keyword
660 query_args = dict()
661 if args.track_keywords:
662 query_args['track'] = args.track_keywords
663
664 # Get stream
2a6238f5 665 stream = TwitterStream(
22be990e 666 auth=authen(),
42fde775 667 domain=domain,
2a6238f5 668 **stream_args)
91476ec3 669
42fde775 670 if domain == USER_DOMAIN:
671 tweet_iter = stream.user(**query_args)
672 elif domain == SITE_DOMAIN:
673 tweet_iter = stream.site(**query_args)
674 else:
675 if args.track_keywords:
676 tweet_iter = stream.statuses.filter(**query_args)
677 else:
678 tweet_iter = stream.statuses.sample()
679
680 # Iterate over the stream.
91476ec3
O
681 for tweet in tweet_iter:
682 if tweet is None:
683 printNicely("-- None --")
684 elif tweet is Timeout:
685 printNicely("-- Timeout --")
686 elif tweet is HeartbeatTimeout:
687 printNicely("-- Heartbeat Timeout --")
688 elif tweet is Hangup:
689 printNicely("-- Hangup --")
690 elif tweet.get('text'):
7e4ccbf3 691 draw(
692 t=tweet,
88af38d8 693 imgflg=args.image,
7e4ccbf3 694 keyword=args.track_keywords,
695 fil=args.filter,
88af38d8
O
696 ig=args.ignore,
697 )
54277114
O
698
699
700def fly():
701 """
702 Main function
703 """
42fde775 704 # Spawn stream process
705 args = parse_arguments()
54277114 706 get_decorated_name()
42fde775 707 p = Process(target=stream, args=(USER_DOMAIN, args, g['original_name']))
708 p.start()
709
710 # Start listen process
819569e8 711 time.sleep(0.5)
c91f75f2 712 g['reset'] = True
1dd312f5 713 g['prefix'] = True
f405a7d0 714 g['stream_pid'] = p.pid
88af38d8
O
715 g['image'] = args.image
716 listen()