8605aecec371c7407ea0603cef2fa342b5bef87e
[rainbowstream.git] / rainbowstream / rainbow.py
1 """
2 Colorful user's timeline stream
3 """
4 from multiprocessing import Process
5 from dateutil import parser
6
7 import os
8 import os.path
9 import sys
10 import signal
11 import argparse
12 import time
13 import datetime
14 import requests
15
16 from twitter.stream import TwitterStream, Timeout, HeartbeatTimeout, Hangup
17 from twitter.api import *
18 from twitter.oauth import OAuth, read_token_file
19 from twitter.oauth_dance import oauth_dance
20 from twitter.util import printNicely
21 from StringIO import StringIO
22
23 from .colors import *
24 from .config import *
25 from .consumer import *
26 from .interactive import *
27 from .db import *
28 from .c_image import *
29
30 g = {}
31 db = RainbowDB()
32 cmdset = [
33 'switch',
34 'home',
35 'view',
36 'mentions',
37 't',
38 'rt',
39 'fav',
40 'rep',
41 'del',
42 'ufav',
43 's',
44 'mes',
45 'show',
46 'ls',
47 'inbox',
48 'sent',
49 'trash',
50 'fl',
51 'ufl',
52 'block',
53 'unblock',
54 'report',
55 'h',
56 'c',
57 'q'
58 ]
59
60
61 def draw(t, iot=False, keyword=None, fil=[], ig=[]):
62 """
63 Draw the rainbow
64 """
65
66 # Retrieve tweet
67 tid = t['id']
68 text = t['text']
69 screen_name = t['user']['screen_name']
70 name = t['user']['name']
71 created_at = t['created_at']
72 favorited = t['favorited']
73 date = parser.parse(created_at)
74 date = date - datetime.timedelta(seconds=time.timezone)
75 clock = date.strftime('%Y/%m/%d %H:%M:%S')
76
77 # Get expanded url
78 try:
79 expanded_url = []
80 url = []
81 urls = t['entities']['urls']
82 for u in urls:
83 expanded_url.append(u['expanded_url'])
84 url.append(u['url'])
85 except:
86 expanded_url = None
87 url = None
88
89 # Get media
90 try:
91 media_url = []
92 media = t['entities']['media']
93 for m in media:
94 media_url.append(m['media_url'])
95 except:
96 media_url = None
97
98 # Filter and ignore
99 screen_name = '@' + screen_name
100 if fil and screen_name not in fil:
101 return
102 if ig and screen_name in ig:
103 return
104
105 # Get rainbow id
106 res = db.tweet_to_rainbow_query(tid)
107 if not res:
108 db.tweet_store(tid)
109 res = db.tweet_to_rainbow_query(tid)
110 rid = res[0].rainbow_id
111
112 # Format info
113 user = cycle_color(name) + grey(' ' + screen_name + ' ')
114 meta = grey('[' + clock + '] [id=' + str(rid) + '] ')
115 if favorited:
116 meta = meta + green(u'\u2605')
117 tweet = text.split()
118 # Replace url
119 if expanded_url:
120 for index in range(len(expanded_url)):
121 tweet = map(
122 lambda x: expanded_url[index] if x == url[index] else x,
123 tweet)
124 # Highlight RT
125 tweet = map(lambda x: grey(x) if x == 'RT' else x, tweet)
126 # Highlight screen_name
127 tweet = map(lambda x: cycle_color(x) if x[0] == '@' else x, tweet)
128 # Highlight link
129 tweet = map(lambda x: cyan(x) if x[0:7] == 'http://' else x, tweet)
130 # Highlight search keyword
131 if keyword:
132 tweet = map(
133 lambda x: on_yellow(x) if
134 ''.join(c for c in x if c.isalnum()).lower() == keyword.lower()
135 else x,
136 tweet
137 )
138 # Recreate tweet
139 tweet = ' '.join(tweet)
140
141 # Draw rainbow
142 line1 = u"{u:>{uw}}:".format(
143 u=user,
144 uw=len(user) + 2,
145 )
146 line2 = u"{c:>{cw}}".format(
147 c=meta,
148 cw=len(meta) + 2,
149 )
150 line3 = ' ' + tweet
151
152 printNicely('')
153 printNicely(line1)
154 printNicely(line2)
155 printNicely(line3)
156
157 # Display Image
158 if iot and media_url:
159 for mu in media_url:
160 response = requests.get(mu)
161 image_to_display(StringIO(response.content))
162
163
164 def print_message(m):
165 """
166 Print direct message
167 """
168 screen_name = '@' + m['sender_screen_name']
169 name = m['sender']['name']
170 text = m['text']
171 mid = m['id']
172 date = parser.parse(m['created_at'])
173 date = date - datetime.timedelta(seconds=time.timezone)
174 clock = date.strftime('%Y/%m/%d %H:%M:%S')
175
176 # Get rainbow id
177 res = db.message_to_rainbow_query(mid)
178 if not res:
179 db.message_store(mid)
180 res = db.message_to_rainbow_query(mid)
181 rid = res[0].rainbow_id
182
183 user = cycle_color(name) + grey(' ' + screen_name + ' ')
184 meta = grey('[' + clock + '] [message_id=' + str(rid) + '] ')
185 text = ''.join(map(lambda x: x+' ' if x=='\n' else x,text))
186
187 line1 = u"{u:>{uw}}:".format(
188 u=user,
189 uw=len(user) + 2,
190 )
191 line2 = u"{c:>{cw}}".format(
192 c=meta,
193 cw=len(meta) + 2,
194 )
195
196 line3 = ' ' + text
197
198 printNicely('')
199 printNicely(line1)
200 printNicely(line2)
201 printNicely(line3)
202
203
204 def parse_arguments():
205 """
206 Parse the arguments
207 """
208 parser = argparse.ArgumentParser(description=__doc__ or "")
209 parser.add_argument(
210 '-to',
211 '--timeout',
212 help='Timeout for the stream (seconds).')
213 parser.add_argument(
214 '-ht',
215 '--heartbeat-timeout',
216 help='Set heartbeat timeout.',
217 default=90)
218 parser.add_argument(
219 '-nb',
220 '--no-block',
221 action='store_true',
222 help='Set stream to non-blocking.')
223 parser.add_argument(
224 '-tt',
225 '--track-keywords',
226 help='Search the stream for specific text.')
227 parser.add_argument(
228 '-fil',
229 '--filter',
230 help='Filter specific screen_name.')
231 parser.add_argument(
232 '-ig',
233 '--ignore',
234 help='Ignore specific screen_name.')
235 parser.add_argument(
236 '-iot',
237 '--image-on-term',
238 action='store_true',
239 help='Display all image on terminal.')
240 return parser.parse_args()
241
242
243 def authen():
244 """
245 Authenticate with Twitter OAuth
246 """
247 # When using rainbow stream you must authorize.
248 twitter_credential = os.environ.get(
249 'HOME',
250 os.environ.get(
251 'USERPROFILE',
252 '')) + os.sep + '.rainbow_oauth'
253 if not os.path.exists(twitter_credential):
254 oauth_dance("Rainbow Stream",
255 CONSUMER_KEY,
256 CONSUMER_SECRET,
257 twitter_credential)
258 oauth_token, oauth_token_secret = read_token_file(twitter_credential)
259 return OAuth(
260 oauth_token,
261 oauth_token_secret,
262 CONSUMER_KEY,
263 CONSUMER_SECRET)
264
265
266 def get_decorated_name():
267 """
268 Beginning of every line
269 """
270 t = Twitter(auth=authen())
271 name = '@' + t.account.verify_credentials()['screen_name']
272 g['original_name'] = name[1:]
273 g['decorated_name'] = grey('[') + grey(name) + grey(']: ')
274
275
276 def switch():
277 """
278 Switch stream
279 """
280 try:
281 target = g['stuff'].split()[0]
282
283 # Filter and ignore
284 args = parse_arguments()
285 try:
286 if g['stuff'].split()[-1] == '-f':
287 only = raw_input('Only nicks: ')
288 ignore = raw_input('Ignore nicks: ')
289 args.filter = filter(None, only.split(','))
290 args.ignore = filter(None, ignore.split(','))
291 elif g['stuff'].split()[-1] == '-d':
292 args.filter = ONLY_LIST
293 args.ignore = IGNORE_LIST
294 except:
295 printNicely(red('Sorry, wrong format.'))
296 return
297
298 # Public stream
299 if target == 'public':
300 keyword = g['stuff'].split()[1]
301 if keyword[0] == '#':
302 keyword = keyword[1:]
303 # Kill old process
304 os.kill(g['stream_pid'], signal.SIGKILL)
305 args.track_keywords = keyword
306 # Start new process
307 p = Process(
308 target=stream,
309 args=(
310 PUBLIC_DOMAIN,
311 args))
312 p.start()
313 g['stream_pid'] = p.pid
314
315 # Personal stream
316 elif target == 'mine':
317 # Kill old process
318 os.kill(g['stream_pid'], signal.SIGKILL)
319 # Start new process
320 p = Process(
321 target=stream,
322 args=(
323 USER_DOMAIN,
324 args,
325 g['original_name']))
326 p.start()
327 g['stream_pid'] = p.pid
328 printNicely('')
329 printNicely(green('Stream switched.'))
330 if args.filter:
331 printNicely(cyan('Only: ' + str(args.filter)))
332 if args.ignore:
333 printNicely(red('Ignore: ' + str(args.ignore)))
334 printNicely('')
335 except:
336 printNicely(red('Sorry I can\'t understand.'))
337
338
339 def home():
340 """
341 Home
342 """
343 t = Twitter(auth=authen())
344 num = HOME_TWEET_NUM
345 if g['stuff'].isdigit():
346 num = int(g['stuff'])
347 for tweet in reversed(t.statuses.home_timeline(count=num)):
348 draw(t=tweet, iot=g['iot'])
349 printNicely('')
350
351
352 def view():
353 """
354 Friend view
355 """
356 t = Twitter(auth=authen())
357 user = g['stuff'].split()[0]
358 if user[0] == '@':
359 try:
360 num = int(g['stuff'].split()[1])
361 except:
362 num = HOME_TWEET_NUM
363 for tweet in reversed(t.statuses.user_timeline(count=num, screen_name=user[1:])):
364 draw(t=tweet, iot=g['iot'])
365 printNicely('')
366 else:
367 printNicely(red('A name should begin with a \'@\''))
368
369
370 def mentions():
371 """
372 Mentions timeline
373 """
374 t = Twitter(auth=authen())
375 num = HOME_TWEET_NUM
376 if g['stuff'].isdigit():
377 num = int(g['stuff'])
378 for tweet in reversed(t.statuses.mentions_timeline(count=num)):
379 draw(t=tweet, iot=g['iot'])
380 printNicely('')
381
382
383 def tweet():
384 """
385 Tweet
386 """
387 t = Twitter(auth=authen())
388 t.statuses.update(status=g['stuff'])
389
390
391 def retweet():
392 """
393 ReTweet
394 """
395 t = Twitter(auth=authen())
396 try:
397 id = int(g['stuff'].split()[0])
398 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
399 t.statuses.retweet(id=tid, include_entities=False, trim_user=True)
400 except:
401 printNicely(red('Sorry I can\'t retweet for you.'))
402
403
404 def favorite():
405 """
406 Favorite
407 """
408 t = Twitter(auth=authen())
409 try:
410 id = int(g['stuff'].split()[0])
411 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
412 t.favorites.create(_id=tid, include_entities=False)
413 printNicely(green('Favorited.'))
414 draw(t.statuses.show(id=tid), iot=g['iot'])
415 except:
416 printNicely(red('Omg some syntax is wrong.'))
417
418
419 def reply():
420 """
421 Reply
422 """
423 t = Twitter(auth=authen())
424 try:
425 id = int(g['stuff'].split()[0])
426 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
427 user = t.statuses.show(id=tid)['user']['screen_name']
428 status = ' '.join(g['stuff'].split()[1:])
429 status = '@' + user + ' ' + status.decode('utf-8')
430 t.statuses.update(status=status, in_reply_to_status_id=tid)
431 except:
432 printNicely(red('Sorry I can\'t understand.'))
433
434
435 def delete():
436 """
437 Delete
438 """
439 t = Twitter(auth=authen())
440 try:
441 rid = int(g['stuff'].split()[0])
442 tid = db.rainbow_to_tweet_query(rid)[0].tweet_id
443 t.statuses.destroy(id=tid)
444 printNicely(green('Okay it\'s gone.'))
445 except:
446 printNicely(red('Sorry I can\'t understand.'))
447
448
449 def unfavorite():
450 """
451 Unfavorite
452 """
453 t = Twitter(auth=authen())
454 try:
455 id = int(g['stuff'].split()[0])
456 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
457 t.favorites.destroy(_id=tid)
458 printNicely(green('Okay it\'s unfavorited.'))
459 draw(t.statuses.show(id=tid), iot=g['iot'])
460 except:
461 printNicely(red('Sorry I can\'t unfavorite this tweet for you.'))
462
463
464 def search():
465 """
466 Search
467 """
468 t = Twitter(auth=authen())
469 try:
470 if g['stuff'][0] == '#':
471 rel = t.search.tweets(q=g['stuff'])['statuses']
472 if len(rel):
473 printNicely('Newest tweets:')
474 for i in reversed(xrange(SEARCH_MAX_RECORD)):
475 draw(t=rel[i],
476 iot=g['iot'],
477 keyword=g['stuff'].strip()[1:])
478 printNicely('')
479 else:
480 printNicely(magenta('I\'m afraid there is no result'))
481 else:
482 printNicely(red('A keyword should be a hashtag (like \'#AKB48\')'))
483 except:
484 printNicely(red('Sorry I can\'t understand.'))
485
486
487 def message():
488 """
489 Send a direct message
490 """
491 t = Twitter(auth=authen())
492 user = g['stuff'].split()[0]
493 if user[0] == '@':
494 try:
495 content = g['stuff'].split()[1]
496 t.direct_messages.new(
497 screen_name=user[1:],
498 text=content
499 )
500 printNicely(green('Message sent.'))
501 except:
502 printNicely(red('Sorry I can\'t understand.'))
503 else:
504 printNicely(red('A name should begin with a \'@\''))
505
506
507 def show():
508 """
509 Show image
510 """
511 t = Twitter(auth=authen())
512 try:
513 target = g['stuff'].split()[0]
514 if target != 'image':
515 return
516 id = int(g['stuff'].split()[1])
517 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
518 tweet = t.statuses.show(id=tid)
519 media = tweet['entities']['media']
520 for m in media:
521 res = requests.get(m['media_url'])
522 img = Image.open(StringIO(res.content))
523 img.show()
524 except:
525 printNicely(red('Sorry I can\'t show this image.'))
526
527
528 def list():
529 """
530 List friends for followers
531 """
532 t = Twitter(auth=authen())
533 try:
534 target = g['stuff'].split()[0]
535 d = {'fl': 'followers', 'fr': 'friends'}
536 next_cursor = -1
537 rel = {}
538 # Cursor loop
539 while next_cursor != 0:
540 list = getattr(t, d[target]).list(
541 screen_name=g['original_name'],
542 cursor=next_cursor,
543 skip_status=True,
544 include_entities=False,
545 )
546 for u in list['users']:
547 rel[u['name']] = '@' + u['screen_name']
548 next_cursor = list['next_cursor']
549 # Print out result
550 printNicely('All: ' + str(len(rel)) + ' people.')
551 for name in rel:
552 user = ' ' + cycle_color(name) + grey(' ' + rel[name] + ' ')
553 printNicely(user)
554 except:
555 printNicely(red('Omg some syntax is wrong.'))
556
557
558 def inbox():
559 """
560 Inbox direct messages
561 """
562 t = Twitter(auth=authen())
563 num = MESSAGES_DISPLAY
564 rel = []
565 if g['stuff'].isdigit():
566 num = g['stuff']
567 cur_page = 1
568 # Max message per page is 20 so we have to loop
569 while num > 20:
570 rel = rel + t.direct_messages(
571 count=20,
572 page=cur_page,
573 include_entities=False,
574 skip_status=False
575 )
576 num -= 20
577 cur_page += 1
578 rel = rel + t.direct_messages(
579 count=num,
580 page=cur_page,
581 include_entities=False,
582 skip_status=False
583 )
584 # Display
585 printNicely('Inbox: newest ' + str(len(rel)) + ' messages.')
586 for m in reversed(rel):
587 print_message(m)
588 printNicely('')
589
590
591 def sent():
592 """
593 Sent direct messages
594 """
595 t = Twitter(auth=authen())
596 num = MESSAGES_DISPLAY
597 rel = []
598 if g['stuff'].isdigit():
599 num = int(g['stuff'])
600 cur_page = 1
601 # Max message per page is 20 so we have to loop
602 while num > 20:
603 rel = rel + t.direct_messages.sent(
604 count=20,
605 page=cur_page,
606 include_entities=False,
607 skip_status=False
608 )
609 num -= 20
610 cur_page += 1
611 rel = rel + t.direct_messages.sent(
612 count=num,
613 page=cur_page,
614 include_entities=False,
615 skip_status=False
616 )
617 # Display
618 printNicely('Sent: newest ' + str(len(rel)) + ' messages.')
619 for m in reversed(rel):
620 print_message(m)
621 printNicely('')
622
623
624 def trash():
625 """
626 Remove message
627 """
628 t = Twitter(auth=authen())
629 try:
630 rid = int(g['stuff'].split()[0])
631 mid = db.rainbow_to_message_query(rid)[0].message_id
632 t.direct_messages.destroy(id=mid)
633 printNicely(green('Message deleted.'))
634 except:
635 printNicely(red('Sorry I can\'t understand.'))
636
637
638 def follow():
639 """
640 Follow a user
641 """
642 t = Twitter(auth=authen())
643 screen_name = g['stuff'].split()[0]
644 if screen_name[0] == '@':
645 try:
646 t.friendships.create(screen_name=screen_name[1:], follow=True)
647 printNicely(green('You are following ' + screen_name + ' now!'))
648 except:
649 printNicely(red('Sorry can not follow at this time.'))
650 else:
651 printNicely(red('Sorry I can\'t understand.'))
652
653
654 def unfollow():
655 """
656 Unfollow a user
657 """
658 t = Twitter(auth=authen())
659 screen_name = g['stuff'].split()[0]
660 if screen_name[0] == '@':
661 try:
662 t.friendships.destroy(
663 screen_name=screen_name[1:],
664 include_entities=False)
665 printNicely(green('Unfollow ' + screen_name + ' success!'))
666 except:
667 printNicely(red('Sorry can not unfollow at this time.'))
668 else:
669 printNicely(red('Sorry I can\'t understand.'))
670
671
672 def block():
673 """
674 Block a user
675 """
676 t = Twitter(auth=authen())
677 screen_name = g['stuff'].split()[0]
678 if screen_name[0] == '@':
679 try:
680 t.blocks.create(
681 screen_name=screen_name[1:],
682 include_entities=False,
683 skip_status=True)
684 printNicely(green('You blocked ' + screen_name + '.'))
685 except:
686 printNicely(red('Sorry something went wrong.'))
687 else:
688 printNicely(red('Sorry I can\'t understand.'))
689
690
691 def unblock():
692 """
693 Unblock a user
694 """
695 t = Twitter(auth=authen())
696 screen_name = g['stuff'].split()[0]
697 if screen_name[0] == '@':
698 try:
699 t.blocks.destroy(
700 screen_name=screen_name[1:],
701 include_entities=False,
702 skip_status=True)
703 printNicely(green('Unblock ' + screen_name + ' success!'))
704 except:
705 printNicely(red('Sorry something went wrong.'))
706 else:
707 printNicely(red('Sorry I can\'t understand.'))
708
709
710 def report():
711 """
712 Report a user as a spam account
713 """
714 t = Twitter(auth=authen())
715 screen_name = g['stuff'].split()[0]
716 if screen_name[0] == '@':
717 try:
718 t.users.report_spam(
719 screen_name=screen_name[1:])
720 printNicely(green('You reported ' + screen_name + '.'))
721 except:
722 printNicely(red('Sorry something went wrong.'))
723 else:
724 printNicely(red('Sorry I can\'t understand.'))
725
726
727 def help():
728 """
729 Help
730 """
731 s = ' ' * 2
732 h, w = os.popen('stty size', 'r').read().split()
733
734 usage = '\n'
735 usage += s + 'Hi boss! I\'m ready to serve you right now!\n'
736 usage += s + '-' * (int(w) - 4) + '\n'
737
738 usage += s + 'You are ' + yellow('already') + ' on your personal stream.\n'
739 usage += s * 2 + green('switch public #AKB') + \
740 ' will switch to public stream and follow "' + \
741 yellow('AKB') + '" keyword.\n'
742 usage += s * 2 + green('switch mine') + \
743 ' will switch to your personal stream.\n'
744 usage += s * 2 + green('switch mine -f ') + \
745 ' will prompt to enter the filter.\n'
746 usage += s * 3 + yellow('Only nicks') + \
747 ' filter will decide nicks will be INCLUDE ONLY.\n'
748 usage += s * 3 + yellow('Ignore nicks') + \
749 ' filter will decide nicks will be EXCLUDE.\n'
750 usage += s * 2 + green('switch mine -d') + \
751 ' will use the config\'s ONLY_LIST and IGNORE_LIST.\n'
752 usage += s * 3 + '(see ' + grey('rainbowstream/config.py') + ').\n'
753
754 usage += s + 'For more action: \n'
755 usage += s * 2 + green('home') + ' will show your timeline. ' + \
756 green('home 7') + ' will show 7 tweets.\n'
757 usage += s * 2 + green('view @mdo') + \
758 ' will show ' + magenta('@mdo') + '\'s home.\n'
759 usage += s * 2 + green('mentions') + ' will show mentions timeline. ' + \
760 green('mentions 7') + ' will show 7 mentions tweets.\n'
761 usage += s * 2 + green('t oops ') + \
762 'will tweet "' + yellow('oops') + '" immediately.\n'
763 usage += s * 2 + \
764 green('rt 12 ') + ' will retweet to tweet with ' + \
765 yellow('[id=12]') + '.\n'
766 usage += s * 2 + \
767 green('fav 12 ') + ' will favorite the tweet with ' + \
768 yellow('[id=12]') + '.\n'
769 usage += s * 2 + green('rep 12 oops') + ' will reply "' + \
770 yellow('oops') + '" to tweet with ' + yellow('[id=12]') + '.\n'
771 usage += s * 2 + \
772 green('del 12 ') + ' will delete tweet with ' + \
773 yellow('[id=12]') + '.\n'
774 usage += s * 2 + \
775 green('ufav 12 ') + ' will unfavorite tweet with ' + \
776 yellow('[id=12]') + '.\n'
777 usage += s * 2 + green('s #AKB48') + ' will search for "' + \
778 yellow('AKB48') + '" and return 5 newest tweet.\n'
779 usage += s * 2 + green('mes @dtvd88 hi') + ' will send a "hi" messege to ' + \
780 magenta('@dtvd88') + '.\n'
781 usage += s * 2 + green('show image 12') + ' will show image in tweet with ' + \
782 yellow('[id=12]') + ' in your OS\'s image viewer.\n'
783 usage += s * 2 + \
784 green('ls fl') + \
785 ' will list all followers (people who are following you).\n'
786 usage += s * 2 + \
787 green('ls fr') + \
788 ' will list all friends (people who you are following).\n'
789 usage += s * 2 + green('inbox') + ' will show inbox messages. ' + \
790 green('inbox 7') + ' will show newest 7 messages.\n'
791 usage += s * 2 + green('sent') + ' will show sent messages. ' + \
792 green('sent 7') + ' will show newest 7 messages.\n'
793 usage += s * 2 + green('trash 5') + ' will remove message with ' + \
794 yellow('[message_id=5]') + '.\n'
795 usage += s * 2 + green('fl @dtvd88') + ' will follow ' + \
796 magenta('@dtvd88') + '.\n'
797 usage += s * 2 + green('ufl @dtvd88') + ' will unfollow ' + \
798 magenta('@dtvd88') + '.\n'
799 usage += s * 2 + green('block @dtvd88') + ' will block ' + \
800 magenta('@dtvd88') + '.\n'
801 usage += s * 2 + green('unblock @dtvd88') + ' will unblock ' + \
802 magenta('@dtvd88') + '.\n'
803 usage += s * 2 + green('report @dtvd88') + ' will report ' + \
804 magenta('@dtvd88') + ' as a spam account.\n'
805 usage += s * 2 + green('h') + ' will show this help again.\n'
806 usage += s * 2 + green('c') + ' will clear the screen.\n'
807 usage += s * 2 + green('q') + ' will quit.\n'
808
809 usage += s + '-' * (int(w) - 4) + '\n'
810 usage += s + 'Have fun and hang tight!\n'
811 printNicely(usage)
812
813
814 def clear():
815 """
816 Clear screen
817 """
818 os.system('clear')
819
820
821 def quit():
822 """
823 Exit all
824 """
825 save_history()
826 os.system('rm -rf rainbow.db')
827 os.kill(g['stream_pid'], signal.SIGKILL)
828 sys.exit()
829
830
831 def reset():
832 """
833 Reset prefix of line
834 """
835 if g['reset']:
836 printNicely(magenta('Need tips ? Type "h" and hit Enter key!'))
837 g['reset'] = False
838
839
840 def process(cmd):
841 """
842 Process switch
843 """
844 return dict(zip(
845 cmdset,
846 [
847 switch,
848 home,
849 view,
850 mentions,
851 tweet,
852 retweet,
853 favorite,
854 reply,
855 delete,
856 unfavorite,
857 search,
858 message,
859 show,
860 list,
861 inbox,
862 sent,
863 trash,
864 follow,
865 unfollow,
866 block,
867 unblock,
868 report,
869 help,
870 clear,
871 quit
872 ]
873 )).get(cmd, reset)
874
875
876 def listen():
877 """
878 Listen to user's input
879 """
880 d = dict(zip(
881 cmdset,
882 [
883 ['public', 'mine'], # switch
884 [], # home
885 ['@'], # view
886 [], # mentions
887 [], # tweet
888 [], # retweet
889 [], # favorite
890 [], # reply
891 [], # delete
892 [], # unfavorite
893 ['#'], # search
894 ['@'], # message
895 ['image'], # show image
896 ['fl', 'fr'], # list
897 [], # inbox
898 [], # sent
899 [], # trash
900 ['@'], # follow
901 ['@'], # unfollow
902 ['@'], # block
903 ['@'], # unblock
904 ['@'], # report
905 [], # help
906 [], # clear
907 [], # quit
908 ]
909 ))
910 init_interactive_shell(d)
911 read_history()
912 reset()
913 while True:
914 if g['prefix']:
915 line = raw_input(g['decorated_name'])
916 else:
917 line = raw_input()
918 try:
919 cmd = line.split()[0]
920 except:
921 cmd = ''
922 # Save cmd to global variable and call process
923 g['stuff'] = ' '.join(line.split()[1:])
924 process(cmd)()
925 if cmd in ['switch', 't', 'rt', 'rep']:
926 g['prefix'] = False
927 else:
928 g['prefix'] = True
929
930
931 def stream(domain, args, name='Rainbow Stream'):
932 """
933 Track the stream
934 """
935
936 # The Logo
937 art_dict = {
938 USER_DOMAIN: name,
939 PUBLIC_DOMAIN: args.track_keywords,
940 SITE_DOMAIN: 'Site Stream',
941 }
942 ascii_art(art_dict[domain])
943
944 # These arguments are optional:
945 stream_args = dict(
946 timeout=args.timeout,
947 block=not args.no_block,
948 heartbeat_timeout=args.heartbeat_timeout)
949
950 # Track keyword
951 query_args = dict()
952 if args.track_keywords:
953 query_args['track'] = args.track_keywords
954
955 # Get stream
956 stream = TwitterStream(
957 auth=authen(),
958 domain=domain,
959 **stream_args)
960
961 if domain == USER_DOMAIN:
962 tweet_iter = stream.user(**query_args)
963 elif domain == SITE_DOMAIN:
964 tweet_iter = stream.site(**query_args)
965 else:
966 if args.track_keywords:
967 tweet_iter = stream.statuses.filter(**query_args)
968 else:
969 tweet_iter = stream.statuses.sample()
970
971 # Iterate over the stream.
972 for tweet in tweet_iter:
973 if tweet is None:
974 printNicely("-- None --")
975 elif tweet is Timeout:
976 printNicely("-- Timeout --")
977 elif tweet is HeartbeatTimeout:
978 printNicely("-- Heartbeat Timeout --")
979 elif tweet is Hangup:
980 printNicely("-- Hangup --")
981 elif tweet.get('text'):
982 draw(
983 t=tweet,
984 iot=args.image_on_term,
985 keyword=args.track_keywords,
986 fil=args.filter,
987 ig=args.ignore,
988 )
989
990
991 def fly():
992 """
993 Main function
994 """
995 # Spawn stream process
996 args = parse_arguments()
997 get_decorated_name()
998 p = Process(target=stream, args=(USER_DOMAIN, args, g['original_name']))
999 p.start()
1000
1001 # Start listen process
1002 time.sleep(0.5)
1003 g['reset'] = True
1004 g['prefix'] = True
1005 g['stream_pid'] = p.pid
1006 g['iot'] = args.image_on_term
1007 listen()