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