a9ee2bab32b421d1d5dcee1dcbcdff27ade09dfe
[rainbowstream.git] / rainbowstream / rainbow.py
1 """
2 Colorful user's timeline stream
3 """
4 from multiprocessing import Process
5
6 import os
7 import os.path
8 import sys
9 import signal
10 import argparse
11 import time
12 import requests
13 import webbrowser
14
15 from twitter.stream import TwitterStream, Timeout, HeartbeatTimeout, Hangup
16 from twitter.api import *
17 from twitter.oauth import OAuth, read_token_file
18 from twitter.oauth_dance import oauth_dance
19 from twitter.util import printNicely
20
21 from .draw import *
22 from .colors import *
23 from .config import *
24 from .consumer import *
25 from .interactive import *
26 from .db import *
27 from .c_image import *
28 from .py3patch import *
29
30 # Global values
31 g = {}
32
33 # Database
34 db = RainbowDB()
35
36 # Commands
37 cmdset = [
38 'switch',
39 'trend',
40 'home',
41 'view',
42 'mentions',
43 't',
44 'rt',
45 'quote',
46 'allrt',
47 'fav',
48 'rep',
49 'del',
50 'ufav',
51 's',
52 'mes',
53 'show',
54 'open',
55 'ls',
56 'inbox',
57 'sent',
58 'trash',
59 'whois',
60 'fl',
61 'ufl',
62 'mute',
63 'unmute',
64 'muting',
65 'block',
66 'unblock',
67 'report',
68 'list',
69 'cal',
70 'config',
71 'theme',
72 'h',
73 'p',
74 'r',
75 'c',
76 'q'
77 ]
78
79
80 def parse_arguments():
81 """
82 Parse the arguments
83 """
84 parser = argparse.ArgumentParser(description=__doc__ or "")
85 parser.add_argument(
86 '-to',
87 '--timeout',
88 help='Timeout for the stream (seconds).')
89 parser.add_argument(
90 '-ht',
91 '--heartbeat-timeout',
92 help='Set heartbeat timeout.',
93 default=90)
94 parser.add_argument(
95 '-nb',
96 '--no-block',
97 action='store_true',
98 help='Set stream to non-blocking.')
99 parser.add_argument(
100 '-tt',
101 '--track-keywords',
102 help='Search the stream for specific text.')
103 parser.add_argument(
104 '-fil',
105 '--filter',
106 help='Filter specific screen_name.')
107 parser.add_argument(
108 '-ig',
109 '--ignore',
110 help='Ignore specific screen_name.')
111 parser.add_argument(
112 '-iot',
113 '--image-on-term',
114 action='store_true',
115 help='Display all image on terminal.')
116 return parser.parse_args()
117
118
119 def authen():
120 """
121 Authenticate with Twitter OAuth
122 """
123 # When using rainbow stream you must authorize.
124 twitter_credential = os.environ.get(
125 'HOME',
126 os.environ.get(
127 'USERPROFILE',
128 '')) + os.sep + '.rainbow_oauth'
129 if not os.path.exists(twitter_credential):
130 oauth_dance("Rainbow Stream",
131 CONSUMER_KEY,
132 CONSUMER_SECRET,
133 twitter_credential)
134 oauth_token, oauth_token_secret = read_token_file(twitter_credential)
135 return OAuth(
136 oauth_token,
137 oauth_token_secret,
138 CONSUMER_KEY,
139 CONSUMER_SECRET)
140
141
142 def init(args):
143 """
144 Init function
145 """
146 # Handle Ctrl C
147 ctrl_c_handler = lambda signum, frame: quit()
148 signal.signal(signal.SIGINT, ctrl_c_handler)
149 # Get name
150 t = Twitter(auth=authen())
151 name = '@' + t.account.verify_credentials()['screen_name']
152 if not get_config('PREFIX'):
153 set_config('PREFIX', name)
154 g['original_name'] = name[1:]
155 g['decorated_name'] = lambda x: color_func(
156 c['DECORATED_NAME'])(
157 '[' + x + ']: ')
158 # Theme init
159 files = os.listdir(os.path.dirname(__file__) + '/colorset')
160 themes = [f.split('.')[0] for f in files if f.split('.')[-1] == 'json']
161 g['themes'] = themes
162 db.theme_store(c['THEME'])
163 # Semaphore init
164 db.semaphore_store(False, False)
165 # Image on term
166 c['IMAGE_ON_TERM'] = args.image_on_term
167
168
169 def switch():
170 """
171 Switch stream
172 """
173 try:
174 target = g['stuff'].split()[0]
175 # Filter and ignore
176 args = parse_arguments()
177 try:
178 if g['stuff'].split()[-1] == '-f':
179 guide = 'To ignore an option, just hit Enter key.'
180 printNicely(light_magenta(guide))
181 only = raw_input('Only nicks [Ex: @xxx,@yy]: ')
182 ignore = raw_input('Ignore nicks [Ex: @xxx,@yy]: ')
183 args.filter = filter(None, only.split(','))
184 args.ignore = filter(None, ignore.split(','))
185 elif g['stuff'].split()[-1] == '-d':
186 args.filter = c['ONLY_LIST']
187 args.ignore = c['IGNORE_LIST']
188 except:
189 printNicely(red('Sorry, wrong format.'))
190 return
191 # Public stream
192 if target == 'public':
193 keyword = g['stuff'].split()[1]
194 if keyword[0] == '#':
195 keyword = keyword[1:]
196 # Kill old process
197 os.kill(g['stream_pid'], signal.SIGKILL)
198 args.track_keywords = keyword
199 # Start new process
200 p = Process(
201 target=stream,
202 args=(
203 c['PUBLIC_DOMAIN'],
204 args))
205 p.start()
206 g['stream_pid'] = p.pid
207 # Personal stream
208 elif target == 'mine':
209 # Kill old process
210 os.kill(g['stream_pid'], signal.SIGKILL)
211 # Start new process
212 p = Process(
213 target=stream,
214 args=(
215 c['USER_DOMAIN'],
216 args,
217 g['original_name']))
218 p.start()
219 g['stream_pid'] = p.pid
220 printNicely('')
221 if args.filter:
222 printNicely(cyan('Only: ' + str(args.filter)))
223 if args.ignore:
224 printNicely(red('Ignore: ' + str(args.ignore)))
225 printNicely('')
226 except:
227 printNicely(red('Sorry I can\'t understand.'))
228
229
230 def trend():
231 """
232 Trend
233 """
234 t = Twitter(auth=authen())
235 # Get country and town
236 try:
237 country = g['stuff'].split()[0]
238 except:
239 country = ''
240 try:
241 town = g['stuff'].split()[1]
242 except:
243 town = ''
244 avail = t.trends.available()
245 # World wide
246 if not country:
247 trends = t.trends.place(_id=1)[0]['trends']
248 print_trends(trends)
249 else:
250 for location in avail:
251 # Search for country and Town
252 if town:
253 if location['countryCode'] == country \
254 and location['placeType']['name'] == 'Town' \
255 and location['name'] == town:
256 trends = t.trends.place(_id=location['woeid'])[0]['trends']
257 print_trends(trends)
258 # Search for country only
259 else:
260 if location['countryCode'] == country \
261 and location['placeType']['name'] == 'Country':
262 trends = t.trends.place(_id=location['woeid'])[0]['trends']
263 print_trends(trends)
264
265
266 def home():
267 """
268 Home
269 """
270 t = Twitter(auth=authen())
271 num = c['HOME_TWEET_NUM']
272 if g['stuff'].isdigit():
273 num = int(g['stuff'])
274 for tweet in reversed(t.statuses.home_timeline(count=num)):
275 draw(t=tweet)
276 printNicely('')
277
278
279 def view():
280 """
281 Friend view
282 """
283 t = Twitter(auth=authen())
284 user = g['stuff'].split()[0]
285 if user[0] == '@':
286 try:
287 num = int(g['stuff'].split()[1])
288 except:
289 num = c['HOME_TWEET_NUM']
290 for tweet in reversed(t.statuses.user_timeline(count=num, screen_name=user[1:])):
291 draw(t=tweet)
292 printNicely('')
293 else:
294 printNicely(red('A name should begin with a \'@\''))
295
296
297 def mentions():
298 """
299 Mentions timeline
300 """
301 t = Twitter(auth=authen())
302 num = c['HOME_TWEET_NUM']
303 if g['stuff'].isdigit():
304 num = int(g['stuff'])
305 for tweet in reversed(t.statuses.mentions_timeline(count=num)):
306 draw(t=tweet)
307 printNicely('')
308
309
310 def tweet():
311 """
312 Tweet
313 """
314 t = Twitter(auth=authen())
315 t.statuses.update(status=g['stuff'])
316
317
318 def retweet():
319 """
320 ReTweet
321 """
322 t = Twitter(auth=authen())
323 try:
324 id = int(g['stuff'].split()[0])
325 except:
326 printNicely(red('Sorry I can\'t understand.'))
327 return
328 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
329 t.statuses.retweet(id=tid, include_entities=False, trim_user=True)
330
331
332 def quote():
333 """
334 Quote a tweet
335 """
336 t = Twitter(auth=authen())
337 try:
338 id = int(g['stuff'].split()[0])
339 except:
340 printNicely(red('Sorry I can\'t understand.'))
341 return
342 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
343 tweet = t.statuses.show(id=tid)
344 screen_name = tweet['user']['screen_name']
345 text = tweet['text']
346 quote = '\"@' + screen_name + ': ' + text + '\"'
347 quote = quote.encode('utf8')
348 notice = light_magenta('Compose mode ')
349 notice += light_yellow('(Enter nothing will cancel the quote)')
350 notice += light_magenta(':')
351 printNicely(notice)
352 extra = raw_input(quote)
353 if extra:
354 t.statuses.update(status=quote + extra)
355 else:
356 printNicely(light_magenta('No text added.'))
357
358
359 def allretweet():
360 """
361 List all retweet
362 """
363 t = Twitter(auth=authen())
364 # Get rainbow id
365 try:
366 id = int(g['stuff'].split()[0])
367 except:
368 printNicely(red('Sorry I can\'t understand.'))
369 return
370 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
371 # Get display num if exist
372 try:
373 num = int(g['stuff'].split()[1])
374 except:
375 num = c['RETWEETS_SHOW_NUM']
376 # Get result and display
377 rt_ary = t.statuses.retweets(id=tid, count=num)
378 if not rt_ary:
379 printNicely(magenta('This tweet has no retweet.'))
380 return
381 for tweet in reversed(rt_ary):
382 draw(t=tweet)
383 printNicely('')
384
385
386 def favorite():
387 """
388 Favorite
389 """
390 t = Twitter(auth=authen())
391 try:
392 id = int(g['stuff'].split()[0])
393 except:
394 printNicely(red('Sorry I can\'t understand.'))
395 return
396 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
397 t.favorites.create(_id=tid, include_entities=False)
398 printNicely(green('Favorited.'))
399 draw(t.statuses.show(id=tid))
400 printNicely('')
401
402
403 def reply():
404 """
405 Reply
406 """
407 t = Twitter(auth=authen())
408 try:
409 id = int(g['stuff'].split()[0])
410 except:
411 printNicely(red('Sorry I can\'t understand.'))
412 return
413 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
414 user = t.statuses.show(id=tid)['user']['screen_name']
415 status = ' '.join(g['stuff'].split()[1:])
416 status = '@' + user + ' ' + status.decode('utf-8')
417 t.statuses.update(status=status, in_reply_to_status_id=tid)
418
419
420 def delete():
421 """
422 Delete
423 """
424 t = Twitter(auth=authen())
425 try:
426 rid = int(g['stuff'].split()[0])
427 except:
428 printNicely(red('Sorry I can\'t understand.'))
429 return
430 tid = db.rainbow_to_tweet_query(rid)[0].tweet_id
431 t.statuses.destroy(id=tid)
432 printNicely(green('Okay it\'s gone.'))
433
434
435 def unfavorite():
436 """
437 Unfavorite
438 """
439 t = Twitter(auth=authen())
440 try:
441 id = int(g['stuff'].split()[0])
442 except:
443 printNicely(red('Sorry I can\'t understand.'))
444 return
445 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
446 t.favorites.destroy(_id=tid)
447 printNicely(green('Okay it\'s unfavorited.'))
448 draw(t.statuses.show(id=tid))
449 printNicely('')
450
451
452 def search():
453 """
454 Search
455 """
456 t = Twitter(auth=authen())
457 g['stuff'] = g['stuff'].strip()
458 rel = t.search.tweets(q=g['stuff'])['statuses']
459 if rel:
460 printNicely('Newest tweets:')
461 for i in reversed(xrange(c['SEARCH_MAX_RECORD'])):
462 draw(t=rel[i],
463 keyword=g['stuff'])
464 printNicely('')
465 else:
466 printNicely(magenta('I\'m afraid there is no result'))
467
468
469 def message():
470 """
471 Send a direct message
472 """
473 t = Twitter(auth=authen())
474 user = g['stuff'].split()[0]
475 if user[0].startswith('@'):
476 try:
477 content = g['stuff'].split()[1]
478 except:
479 printNicely(red('Sorry I can\'t understand.'))
480 t.direct_messages.new(
481 screen_name=user[1:],
482 text=content
483 )
484 printNicely(green('Message sent.'))
485 else:
486 printNicely(red('A name should begin with a \'@\''))
487
488
489 def show():
490 """
491 Show image
492 """
493 t = Twitter(auth=authen())
494 try:
495 target = g['stuff'].split()[0]
496 if target != 'image':
497 return
498 id = int(g['stuff'].split()[1])
499 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
500 tweet = t.statuses.show(id=tid)
501 media = tweet['entities']['media']
502 for m in media:
503 res = requests.get(m['media_url'])
504 img = Image.open(BytesIO(res.content))
505 img.show()
506 except:
507 printNicely(red('Sorry I can\'t show this image.'))
508
509
510 def urlopen():
511 """
512 Open url
513 """
514 t = Twitter(auth=authen())
515 try:
516 if not g['stuff'].isdigit():
517 return
518 tid = db.rainbow_to_tweet_query(g['stuff'])[0].tweet_id
519 tweet = t.statuses.show(id=tid)
520 link_ary = [
521 u for u in tweet['text'].split() if u.startswith('http://')]
522 if not link_ary:
523 printNicely(light_magenta('No url here @.@!'))
524 return
525 for link in link_ary:
526 webbrowser.open(link)
527 except:
528 printNicely(red('Sorry I can\'t open url in this tweet.'))
529
530
531 def ls():
532 """
533 List friends for followers
534 """
535 t = Twitter(auth=authen())
536 # Get name
537 try:
538 name = g['stuff'].split()[1]
539 if name.startswith('@'):
540 name = name[1:]
541 else:
542 printNicely(red('A name should begin with a \'@\''))
543 raise Exception('Invalid name')
544 except:
545 name = g['original_name']
546 # Get list followers or friends
547 try:
548 target = g['stuff'].split()[0]
549 except:
550 printNicely(red('Omg some syntax is wrong.'))
551 # Init cursor
552 d = {'fl': 'followers', 'fr': 'friends'}
553 next_cursor = -1
554 rel = {}
555 # Cursor loop
556 while next_cursor != 0:
557 list = getattr(t, d[target]).list(
558 screen_name=name,
559 cursor=next_cursor,
560 skip_status=True,
561 include_entities=False,
562 )
563 for u in list['users']:
564 rel[u['name']] = '@' + u['screen_name']
565 next_cursor = list['next_cursor']
566 # Print out result
567 printNicely('All: ' + str(len(rel)) + ' ' + d[target] + '.')
568 for name in rel:
569 user = ' ' + cycle_color(name)
570 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
571 printNicely(user)
572
573
574 def inbox():
575 """
576 Inbox direct messages
577 """
578 t = Twitter(auth=authen())
579 num = c['MESSAGES_DISPLAY']
580 rel = []
581 if g['stuff'].isdigit():
582 num = g['stuff']
583 cur_page = 1
584 # Max message per page is 20 so we have to loop
585 while num > 20:
586 rel = rel + t.direct_messages(
587 count=20,
588 page=cur_page,
589 include_entities=False,
590 skip_status=False
591 )
592 num -= 20
593 cur_page += 1
594 rel = rel + t.direct_messages(
595 count=num,
596 page=cur_page,
597 include_entities=False,
598 skip_status=False
599 )
600 # Display
601 printNicely('Inbox: newest ' + str(len(rel)) + ' messages.')
602 for m in reversed(rel):
603 print_message(m)
604 printNicely('')
605
606
607 def sent():
608 """
609 Sent direct messages
610 """
611 t = Twitter(auth=authen())
612 num = c['MESSAGES_DISPLAY']
613 rel = []
614 if g['stuff'].isdigit():
615 num = int(g['stuff'])
616 cur_page = 1
617 # Max message per page is 20 so we have to loop
618 while num > 20:
619 rel = rel + t.direct_messages.sent(
620 count=20,
621 page=cur_page,
622 include_entities=False,
623 skip_status=False
624 )
625 num -= 20
626 cur_page += 1
627 rel = rel + t.direct_messages.sent(
628 count=num,
629 page=cur_page,
630 include_entities=False,
631 skip_status=False
632 )
633 # Display
634 printNicely('Sent: newest ' + str(len(rel)) + ' messages.')
635 for m in reversed(rel):
636 print_message(m)
637 printNicely('')
638
639
640 def trash():
641 """
642 Remove message
643 """
644 t = Twitter(auth=authen())
645 try:
646 rid = int(g['stuff'].split()[0])
647 except:
648 printNicely(red('Sorry I can\'t understand.'))
649 mid = db.rainbow_to_message_query(rid)[0].message_id
650 t.direct_messages.destroy(id=mid)
651 printNicely(green('Message deleted.'))
652
653
654 def whois():
655 """
656 Show profile of a specific user
657 """
658 t = Twitter(auth=authen())
659 screen_name = g['stuff'].split()[0]
660 if screen_name.startswith('@'):
661 try:
662 user = t.users.show(
663 screen_name=screen_name[1:],
664 include_entities=False)
665 show_profile(user)
666 except:
667 printNicely(red('Omg no user.'))
668 else:
669 printNicely(red('A name should begin with a \'@\''))
670
671
672 def follow():
673 """
674 Follow a user
675 """
676 t = Twitter(auth=authen())
677 screen_name = g['stuff'].split()[0]
678 if screen_name.startswith('@'):
679 t.friendships.create(screen_name=screen_name[1:], follow=True)
680 printNicely(green('You are following ' + screen_name + ' now!'))
681 else:
682 printNicely(red('A name should begin with a \'@\''))
683
684
685 def unfollow():
686 """
687 Unfollow a user
688 """
689 t = Twitter(auth=authen())
690 screen_name = g['stuff'].split()[0]
691 if screen_name.startswith('@'):
692 t.friendships.destroy(
693 screen_name=screen_name[1:],
694 include_entities=False)
695 printNicely(green('Unfollow ' + screen_name + ' success!'))
696 else:
697 printNicely(red('A name should begin with a \'@\''))
698
699
700 def mute():
701 """
702 Mute a user
703 """
704 t = Twitter(auth=authen())
705 try:
706 screen_name = g['stuff'].split()[0]
707 except:
708 printNicely(red('A name should be specified. '))
709 return
710 if screen_name.startswith('@'):
711 rel = t.mutes.users.create(screen_name=screen_name[1:])
712 if isinstance(rel, dict):
713 printNicely(green(screen_name + ' is muted.'))
714 else:
715 printNicely(red(rel))
716 else:
717 printNicely(red('A name should begin with a \'@\''))
718
719
720 def unmute():
721 """
722 Unmute a user
723 """
724 t = Twitter(auth=authen())
725 try:
726 screen_name = g['stuff'].split()[0]
727 except:
728 printNicely(red('A name should be specified. '))
729 return
730 if screen_name.startswith('@'):
731 rel = t.mutes.users.destroy(screen_name=screen_name[1:])
732 if isinstance(rel, dict):
733 printNicely(green(screen_name + ' is unmuted.'))
734 else:
735 printNicely(red(rel))
736 else:
737 printNicely(red('A name should begin with a \'@\''))
738
739
740 def muting():
741 """
742 List muting user
743 """
744 t = Twitter(auth=authen())
745 # Init cursor
746 next_cursor = -1
747 rel = {}
748 # Cursor loop
749 while next_cursor != 0:
750 list = t.mutes.users.list(
751 screen_name=g['original_name'],
752 cursor=next_cursor,
753 skip_status=True,
754 include_entities=False,
755 )
756 for u in list['users']:
757 rel[u['name']] = '@' + u['screen_name']
758 next_cursor = list['next_cursor']
759 # Print out result
760 printNicely('All: ' + str(len(rel)) + ' people.')
761 for name in rel:
762 user = ' ' + cycle_color(name)
763 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
764 printNicely(user)
765
766
767 def block():
768 """
769 Block a user
770 """
771 t = Twitter(auth=authen())
772 screen_name = g['stuff'].split()[0]
773 if screen_name.startswith('@'):
774 t.blocks.create(
775 screen_name=screen_name[1:],
776 include_entities=False,
777 skip_status=True)
778 printNicely(green('You blocked ' + screen_name + '.'))
779 else:
780 printNicely(red('A name should begin with a \'@\''))
781
782
783 def unblock():
784 """
785 Unblock a user
786 """
787 t = Twitter(auth=authen())
788 screen_name = g['stuff'].split()[0]
789 if screen_name.startswith('@'):
790 t.blocks.destroy(
791 screen_name=screen_name[1:],
792 include_entities=False,
793 skip_status=True)
794 printNicely(green('Unblock ' + screen_name + ' success!'))
795 else:
796 printNicely(red('A name should begin with a \'@\''))
797
798
799 def report():
800 """
801 Report a user as a spam account
802 """
803 t = Twitter(auth=authen())
804 screen_name = g['stuff'].split()[0]
805 if screen_name.startswith('@'):
806 t.users.report_spam(
807 screen_name=screen_name[1:])
808 printNicely(green('You reported ' + screen_name + '.'))
809 else:
810 printNicely(red('Sorry I can\'t understand.'))
811
812
813 def get_slug():
814 """
815 Get Slug Decorator
816 """
817 # Get list name
818 list_name = raw_input(light_magenta('Give me the list\'s name: '))
819 # Get list name and owner
820 try:
821 owner, slug = list_name.split('/')
822 if slug.startswith('@'):
823 slug = slug[1:]
824 return owner, slug
825 except:
826 printNicely(
827 light_magenta('List name should follow "@owner/list_name" format.'))
828 raise Exception('Wrong list name')
829
830
831 def show_lists(t):
832 """
833 List list
834 """
835 rel = t.lists.list(screen_name=g['original_name'])
836 if rel:
837 print_list(rel)
838 else:
839 printNicely(light_magenta('You belong to no lists :)'))
840
841
842 def list_home(t):
843 """
844 List home
845 """
846 owner, slug = get_slug()
847 res = t.lists.statuses(
848 slug=slug,
849 owner_screen_name=owner,
850 count=c['LIST_MAX'],
851 include_entities=False)
852 for tweet in res:
853 draw(t=tweet)
854 printNicely('')
855
856
857 def list_members(t):
858 """
859 List members
860 """
861 owner, slug = get_slug()
862 # Get members
863 rel = {}
864 next_cursor = -1
865 while next_cursor != 0:
866 m = t.lists.members(
867 slug=slug,
868 owner_screen_name=owner,
869 cursor=next_cursor,
870 include_entities=False)
871 for u in m['users']:
872 rel[u['name']] = '@' + u['screen_name']
873 next_cursor = m['next_cursor']
874 printNicely('All: ' + str(len(rel)) + ' members.')
875 for name in rel:
876 user = ' ' + cycle_color(name)
877 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
878 printNicely(user)
879
880
881 def list_subscribers(t):
882 """
883 List subscribers
884 """
885 owner, slug = get_slug()
886 # Get subscribers
887 rel = {}
888 next_cursor = -1
889 while next_cursor != 0:
890 m = t.lists.subscribers(
891 slug=slug,
892 owner_screen_name=owner,
893 cursor=next_cursor,
894 include_entities=False)
895 for u in m['users']:
896 rel[u['name']] = '@' + u['screen_name']
897 next_cursor = m['next_cursor']
898 printNicely('All: ' + str(len(rel)) + ' subscribers.')
899 for name in rel:
900 user = ' ' + cycle_color(name)
901 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
902 printNicely(user)
903
904
905 def list_add(t):
906 """
907 Add specific user to a list
908 """
909 owner, slug = get_slug()
910 # Add
911 user_name = raw_input(light_magenta('Give me name of the newbie: '))
912 if user_name.startswith('@'):
913 user_name = user_name[1:]
914 try:
915 t.lists.members.create(
916 slug=slug,
917 owner_screen_name=owner,
918 screen_name=user_name)
919 printNicely(green('Added.'))
920 except:
921 printNicely(light_magenta('I\'m sorry we can not add him/her.'))
922
923
924 def list_remove(t):
925 """
926 Remove specific user from a list
927 """
928 owner, slug = get_slug()
929 # Remove
930 user_name = raw_input(light_magenta('Give me name of the unlucky one: '))
931 if user_name.startswith('@'):
932 user_name = user_name[1:]
933 try:
934 t.lists.members.destroy(
935 slug=slug,
936 owner_screen_name=owner,
937 screen_name=user_name)
938 printNicely(green('Gone.'))
939 except:
940 printNicely(light_magenta('I\'m sorry we can not remove him/her.'))
941
942
943 def list_subscribe(t):
944 """
945 Subscribe to a list
946 """
947 owner, slug = get_slug()
948 # Subscribe
949 try:
950 t.lists.subscribers.create(
951 slug=slug,
952 owner_screen_name=owner)
953 printNicely(green('Done.'))
954 except:
955 printNicely(
956 light_magenta('I\'m sorry you can not subscribe to this list.'))
957
958
959 def list_unsubscribe(t):
960 """
961 Unsubscribe a list
962 """
963 owner, slug = get_slug()
964 # Subscribe
965 try:
966 t.lists.subscribers.destroy(
967 slug=slug,
968 owner_screen_name=owner)
969 printNicely(green('Done.'))
970 except:
971 printNicely(
972 light_magenta('I\'m sorry you can not unsubscribe to this list.'))
973
974
975 def list_own(t):
976 """
977 List own
978 """
979 rel = []
980 next_cursor = -1
981 while next_cursor != 0:
982 res = t.lists.ownerships(
983 screen_name=g['original_name'],
984 cursor=next_cursor)
985 rel += res['lists']
986 next_cursor = res['next_cursor']
987 if rel:
988 print_list(rel)
989 else:
990 printNicely(light_magenta('You own no lists :)'))
991
992
993 def list_new(t):
994 """
995 Create a new list
996 """
997 name = raw_input(light_magenta('New list\'s name: '))
998 mode = raw_input(light_magenta('New list\'s mode (public/private): '))
999 description = raw_input(light_magenta('New list\'s description: '))
1000 try:
1001 t.lists.create(
1002 name=name,
1003 mode=mode,
1004 description=description)
1005 printNicely(green(name + ' list is created.'))
1006 except:
1007 printNicely(red('Oops something is wrong with Twitter :('))
1008
1009
1010 def list_update(t):
1011 """
1012 Update a list
1013 """
1014 slug = raw_input(light_magenta('Your list that you want to update: '))
1015 name = raw_input(light_magenta('Update name (leave blank to unchange): '))
1016 mode = raw_input(light_magenta('Update mode (public/private): '))
1017 description = raw_input(light_magenta('Update description: '))
1018 try:
1019 if name:
1020 t.lists.update(
1021 slug='-'.join(slug.split()),
1022 owner_screen_name=g['original_name'],
1023 name=name,
1024 mode=mode,
1025 description=description)
1026 else:
1027 t.lists.update(
1028 slug=slug,
1029 owner_screen_name=g['original_name'],
1030 mode=mode,
1031 description=description)
1032 printNicely(green(slug + ' list is updated.'))
1033 except:
1034 printNicely(red('Oops something is wrong with Twitter :('))
1035
1036
1037 def list_delete(t):
1038 """
1039 Delete a list
1040 """
1041 slug = raw_input(light_magenta('Your list that you want to update: '))
1042 try:
1043 t.lists.destroy(
1044 slug='-'.join(slug.split()),
1045 owner_screen_name=g['original_name'])
1046 printNicely(green(slug + ' list is deleted.'))
1047 except:
1048 printNicely(red('Oops something is wrong with Twitter :('))
1049
1050
1051 def list():
1052 """
1053 Twitter's list
1054 """
1055 t = Twitter(auth=authen())
1056 # List all lists or base on action
1057 try:
1058 g['list_action'] = g['stuff'].split()[0]
1059 except:
1060 show_lists(t)
1061 return
1062 # Sub-function
1063 action_ary = {
1064 'home': list_home,
1065 'all_mem': list_members,
1066 'all_sub': list_subscribers,
1067 'add': list_add,
1068 'rm': list_remove,
1069 'sub': list_subscribe,
1070 'unsub': list_unsubscribe,
1071 'own': list_own,
1072 'new': list_new,
1073 'update': list_update,
1074 'del': list_delete,
1075 }
1076 try:
1077 return action_ary[g['list_action']](t)
1078 except:
1079 printNicely(red('Please try again.'))
1080
1081
1082 def cal():
1083 """
1084 Unix's command `cal`
1085 """
1086 # Format
1087 rel = os.popen('cal').read().split('\n')
1088 month = rel.pop(0)
1089 date = rel.pop(0)
1090 show_calendar(month, date, rel)
1091
1092
1093 def config():
1094 """
1095 Browse and change config
1096 """
1097 all_config = get_all_config()
1098 g['stuff'] = g['stuff'].strip()
1099 # List all config
1100 if not g['stuff']:
1101 for k in all_config:
1102 line = ' ' * 2 + \
1103 green(k) + ': ' + light_yellow(str(all_config[k]))
1104 printNicely(line)
1105 guide = 'Detailed explanation can be found at ' + \
1106 color_func(c['TWEET']['link'])(
1107 'http://rainbowstream.readthedocs.org/en/latest/#config-explanation')
1108 printNicely(guide)
1109 # Print specific config
1110 elif len(g['stuff'].split()) == 1:
1111 if g['stuff'] in all_config:
1112 k = g['stuff']
1113 line = ' ' * 2 + \
1114 green(k) + ': ' + light_yellow(str(all_config[k]))
1115 printNicely(line)
1116 else:
1117 printNicely(red('No such config key.'))
1118 # Print specific config's default value
1119 elif len(g['stuff'].split()) == 2 and g['stuff'].split()[-1] == 'default':
1120 key = g['stuff'].split()[0]
1121 try:
1122 value = get_default_config(key)
1123 line = ' ' * 2 + green(key) + ': ' + light_magenta(value)
1124 printNicely(line)
1125 except:
1126 printNicely(
1127 light_magenta('This config key does not exist in default.'))
1128 # Delete specific config key in config file
1129 elif len(g['stuff'].split()) == 2 and g['stuff'].split()[-1] == 'drop':
1130 key = g['stuff'].split()[0]
1131 try:
1132 delete_config(key)
1133 printNicely(green('Config key is dropped.'))
1134 except:
1135 printNicely(red('No such config key.'))
1136 # Set specific config
1137 elif len(g['stuff'].split()) == 3 and g['stuff'].split()[1] == '=':
1138 key = g['stuff'].split()[0]
1139 value = g['stuff'].split()[-1]
1140 if key == 'THEME' and not validate_theme(value):
1141 printNicely(red('Invalid theme\'s value.'))
1142 return
1143 try:
1144 set_config(key, value)
1145 # Apply theme immediately
1146 if key == 'THEME':
1147 reload_theme(value)
1148 g['decorated_name'] = lambda x: color_func(
1149 c['DECORATED_NAME'])(
1150 '[' + x + ']: ')
1151 printNicely(green('Updated successfully.'))
1152 except:
1153 printNicely(light_magenta('Not valid value.'))
1154 return
1155 reload_config()
1156 else:
1157 printNicely(light_magenta('Sorry I can\'s understand.'))
1158
1159
1160 def theme():
1161 """
1162 List and change theme
1163 """
1164 if not g['stuff']:
1165 # List themes
1166 for theme in g['themes']:
1167 line = light_magenta(theme)
1168 if c['THEME'] == theme:
1169 line = ' ' * 2 + light_yellow('* ') + line
1170 else:
1171 line = ' ' * 4 + line
1172 printNicely(line)
1173 else:
1174 # Change theme
1175 try:
1176 # Load new theme
1177 reload_theme(g['stuff'])
1178 # Redefine decorated_name
1179 g['decorated_name'] = lambda x: color_func(
1180 c['DECORATED_NAME'])(
1181 '[' + x + ']: ')
1182 printNicely(green('Theme changed.'))
1183 except:
1184 printNicely(red('No such theme exists.'))
1185
1186
1187 def help_discover():
1188 """
1189 Discover the world
1190 """
1191 s = ' ' * 2
1192 # Discover the world
1193 usage = '\n'
1194 usage += s + grey(u'\u266A' + ' Discover the world \n')
1195 usage += s * 2 + light_green('trend') + ' will show global trending topics. ' + \
1196 'You can try ' + light_green('trend US') + ' or ' + \
1197 light_green('trend JP Tokyo') + '.\n'
1198 usage += s * 2 + light_green('home') + ' will show your timeline. ' + \
1199 light_green('home 7') + ' will show 7 tweets.\n'
1200 usage += s * 2 + light_green('mentions') + ' will show mentions timeline. ' + \
1201 light_green('mentions 7') + ' will show 7 mention tweets.\n'
1202 usage += s * 2 + light_green('whois @mdo') + ' will show profile of ' + \
1203 magenta('@mdo') + '.\n'
1204 usage += s * 2 + light_green('view @mdo') + \
1205 ' will show ' + magenta('@mdo') + '\'s home.\n'
1206 usage += s * 2 + light_green('s AKB48') + ' will search for "' + \
1207 light_yellow('AKB48') + '" and return 5 newest tweet. ' + \
1208 'Search can be performed with or without hashtag.\n'
1209 printNicely(usage)
1210
1211
1212 def help_tweets():
1213 """
1214 Tweets
1215 """
1216 s = ' ' * 2
1217 # Tweet
1218 usage = '\n'
1219 usage += s + grey(u'\u266A' + ' Tweets \n')
1220 usage += s * 2 + light_green('t oops ') + \
1221 'will tweet "' + light_yellow('oops') + '" immediately.\n'
1222 usage += s * 2 + \
1223 light_green('rt 12 ') + ' will retweet to tweet with ' + \
1224 light_yellow('[id=12]') + '.\n'
1225 usage += s * 2 + \
1226 light_green('quote 12 ') + ' will quote the tweet with ' + \
1227 light_yellow('[id=12]') + '. If no extra text is added, ' + \
1228 'the quote will be canceled.\n'
1229 usage += s * 2 + \
1230 light_green('allrt 12 20 ') + ' will list 20 newest retweet of the tweet with ' + \
1231 light_yellow('[id=12]') + '.\n'
1232 usage += s * 2 + light_green('rep 12 oops') + ' will reply "' + \
1233 light_yellow('oops') + '" to tweet with ' + \
1234 light_yellow('[id=12]') + '.\n'
1235 usage += s * 2 + \
1236 light_green('fav 12 ') + ' will favorite the tweet with ' + \
1237 light_yellow('[id=12]') + '.\n'
1238 usage += s * 2 + \
1239 light_green('ufav 12 ') + ' will unfavorite tweet with ' + \
1240 light_yellow('[id=12]') + '.\n'
1241 usage += s * 2 + \
1242 light_green('del 12 ') + ' will delete tweet with ' + \
1243 light_yellow('[id=12]') + '.\n'
1244 usage += s * 2 + light_green('show image 12') + ' will show image in tweet with ' + \
1245 light_yellow('[id=12]') + ' in your OS\'s image viewer.\n'
1246 usage += s * 2 + light_green('open 12') + ' will open url in tweet with ' + \
1247 light_yellow('[id=12]') + ' in your OS\'s default browser.\n'
1248 printNicely(usage)
1249
1250
1251 def help_messages():
1252 """
1253 Messages
1254 """
1255 s = ' ' * 2
1256 # Direct message
1257 usage = '\n'
1258 usage += s + grey(u'\u266A' + ' Direct messages \n')
1259 usage += s * 2 + light_green('inbox') + ' will show inbox messages. ' + \
1260 light_green('inbox 7') + ' will show newest 7 messages.\n'
1261 usage += s * 2 + light_green('sent') + ' will show sent messages. ' + \
1262 light_green('sent 7') + ' will show newest 7 messages.\n'
1263 usage += s * 2 + light_green('mes @dtvd88 hi') + ' will send a "hi" messege to ' + \
1264 magenta('@dtvd88') + '.\n'
1265 usage += s * 2 + light_green('trash 5') + ' will remove message with ' + \
1266 light_yellow('[message_id=5]') + '.\n'
1267 printNicely(usage)
1268
1269
1270 def help_friends_and_followers():
1271 """
1272 Friends and Followers
1273 """
1274 s = ' ' * 2
1275 # Follower and following
1276 usage = '\n'
1277 usage += s + grey(u'\u266A' + ' Friends and followers \n')
1278 usage += s * 2 + \
1279 light_green('ls fl') + \
1280 ' will list all followers (people who are following you).\n'
1281 usage += s * 2 + \
1282 light_green('ls fr') + \
1283 ' will list all friends (people who you are following).\n'
1284 usage += s * 2 + light_green('fl @dtvd88') + ' will follow ' + \
1285 magenta('@dtvd88') + '.\n'
1286 usage += s * 2 + light_green('ufl @dtvd88') + ' will unfollow ' + \
1287 magenta('@dtvd88') + '.\n'
1288 usage += s * 2 + light_green('mute @dtvd88') + ' will mute ' + \
1289 magenta('@dtvd88') + '.\n'
1290 usage += s * 2 + light_green('unmute @dtvd88') + ' will unmute ' + \
1291 magenta('@dtvd88') + '.\n'
1292 usage += s * 2 + light_green('muting') + ' will list muting users.\n'
1293 usage += s * 2 + light_green('block @dtvd88') + ' will block ' + \
1294 magenta('@dtvd88') + '.\n'
1295 usage += s * 2 + light_green('unblock @dtvd88') + ' will unblock ' + \
1296 magenta('@dtvd88') + '.\n'
1297 usage += s * 2 + light_green('report @dtvd88') + ' will report ' + \
1298 magenta('@dtvd88') + ' as a spam account.\n'
1299 printNicely(usage)
1300
1301
1302 def help_list():
1303 """
1304 Lists
1305 """
1306 s = ' ' * 2
1307 # Twitter list
1308 usage = '\n'
1309 usage += s + grey(u'\u266A' + ' Twitter list\n')
1310 usage += s * 2 + light_green('list') + \
1311 ' will show all lists you are belong to.\n'
1312 usage += s * 2 + light_green('list home') + \
1313 ' will show timeline of list. You will be asked for list\'s name.\n'
1314 usage += s * 2 + light_green('list all_mem') + \
1315 ' will show list\'s all members.\n'
1316 usage += s * 2 + light_green('list all_sub') + \
1317 ' will show list\'s all subscribers.\n'
1318 usage += s * 2 + light_green('list add') + \
1319 ' will add specific person to a list owned by you.' + \
1320 ' You will be asked for list\'s name and person\'s name.\n'
1321 usage += s * 2 + light_green('list rm') + \
1322 ' will remove specific person from a list owned by you.' + \
1323 ' You will be asked for list\'s name and person\'s name.\n'
1324 usage += s * 2 + light_green('list sub') + \
1325 ' will subscribe you to a specific list.\n'
1326 usage += s * 2 + light_green('list unsub') + \
1327 ' will unsubscribe you from a specific list.\n'
1328 usage += s * 2 + light_green('list own') + \
1329 ' will show all list owned by you.\n'
1330 usage += s * 2 + light_green('list new') + \
1331 ' will create a new list.\n'
1332 usage += s * 2 + light_green('list update') + \
1333 ' will update a list owned by you.\n'
1334 usage += s * 2 + light_green('list del') + \
1335 ' will delete a list owned by you.\n'
1336 printNicely(usage)
1337
1338
1339 def help_stream():
1340 """
1341 Stream switch
1342 """
1343 s = ' ' * 2
1344 # Switch
1345 usage = '\n'
1346 usage += s + grey(u'\u266A' + ' Switching streams \n')
1347 usage += s * 2 + light_green('switch public #AKB') + \
1348 ' will switch to public stream and follow "' + \
1349 light_yellow('AKB') + '" keyword.\n'
1350 usage += s * 2 + light_green('switch mine') + \
1351 ' will switch to your personal stream.\n'
1352 usage += s * 2 + light_green('switch mine -f ') + \
1353 ' will prompt to enter the filter.\n'
1354 usage += s * 3 + light_yellow('Only nicks') + \
1355 ' filter will decide nicks will be INCLUDE ONLY.\n'
1356 usage += s * 3 + light_yellow('Ignore nicks') + \
1357 ' filter will decide nicks will be EXCLUDE.\n'
1358 usage += s * 2 + light_green('switch mine -d') + \
1359 ' will use the config\'s ONLY_LIST and IGNORE_LIST.\n'
1360 printNicely(usage)
1361
1362
1363 def help():
1364 """
1365 Help
1366 """
1367 s = ' ' * 2
1368 h, w = os.popen('stty size', 'r').read().split()
1369 # Start
1370 usage = '\n'
1371 usage += s + 'Hi boss! I\'m ready to serve you right now!\n'
1372 usage += s + '-' * (int(w) - 4) + '\n'
1373 usage += s + 'You are ' + \
1374 light_yellow('already') + ' on your personal stream.\n'
1375 usage += s + 'Any update from Twitter will show up ' + \
1376 light_yellow('immediately') + '.\n'
1377 usage += s + 'In addtion, following commands are available right now:\n'
1378 # Twitter help section
1379 usage += '\n'
1380 usage += s + grey(u'\u266A' + ' Twitter help\n')
1381 usage += s * 2 + light_green('h discover') + \
1382 ' will show help for discover commands.\n'
1383 usage += s * 2 + light_green('h tweets') + \
1384 ' will show help for tweets commands.\n'
1385 usage += s * 2 + light_green('h messages') + \
1386 ' will show help for messages commands.\n'
1387 usage += s * 2 + light_green('h friends_and_followers') + \
1388 ' will show help for friends and followers commands.\n'
1389 usage += s * 2 + light_green('h list') + \
1390 ' will show help for list commands.\n'
1391 usage += s * 2 + light_green('h stream') + \
1392 ' will show help for stream commands.\n'
1393 # Smart shell
1394 usage += '\n'
1395 usage += s + grey(u'\u266A' + ' Smart shell\n')
1396 usage += s * 2 + light_green('111111 * 9 / 7') + ' or any math expression ' + \
1397 'will be evaluate by Python interpreter.\n'
1398 usage += s * 2 + 'Even ' + light_green('cal') + ' will show the calendar' + \
1399 ' for current month.\n'
1400 # Config
1401 usage += '\n'
1402 usage += s + grey(u'\u266A' + ' Config \n')
1403 usage += s * 2 + light_green('theme') + ' will list available theme. ' + \
1404 light_green('theme monokai') + ' will apply ' + light_yellow('monokai') + \
1405 ' theme immediately.\n'
1406 usage += s * 2 + light_green('config') + ' will list all config.\n'
1407 usage += s * 3 + \
1408 light_green('config ASCII_ART') + ' will output current value of ' +\
1409 light_yellow('ASCII_ART') + ' config key.\n'
1410 usage += s * 3 + \
1411 light_green('config TREND_MAX default') + ' will output default value of ' + \
1412 light_yellow('TREND_MAX') + ' config key.\n'
1413 usage += s * 3 + \
1414 light_green('config CUSTOM_CONFIG drop') + ' will drop ' + \
1415 light_yellow('CUSTOM_CONFIG') + ' config key.\n'
1416 usage += s * 3 + \
1417 light_green('config IMAGE_ON_TERM = true') + ' will set value of ' + \
1418 light_yellow('IMAGE_ON_TERM') + ' config key to ' + \
1419 light_yellow('True') + '.\n'
1420 # Screening
1421 usage += '\n'
1422 usage += s + grey(u'\u266A' + ' Screening \n')
1423 usage += s * 2 + light_green('h') + ' will show this help again.\n'
1424 usage += s * 2 + light_green('p') + ' will pause the stream.\n'
1425 usage += s * 2 + light_green('r') + ' will unpause the stream.\n'
1426 usage += s * 2 + light_green('c') + ' will clear the screen.\n'
1427 usage += s * 2 + light_green('q') + ' will quit.\n'
1428 # End
1429 usage += '\n'
1430 usage += s + '-' * (int(w) - 4) + '\n'
1431 usage += s + 'Have fun and hang tight! \n'
1432 # Show help
1433 d = {
1434 'discover': help_discover,
1435 'tweets': help_tweets,
1436 'messages': help_messages,
1437 'friends_and_followers': help_friends_and_followers,
1438 'list': help_list,
1439 'stream': help_stream,
1440 }
1441 if g['stuff']:
1442 d[g['stuff'].strip()]()
1443 else:
1444 printNicely(usage)
1445
1446
1447 def pause():
1448 """
1449 Pause stream display
1450 """
1451 db.semaphore_update_pause(True)
1452 printNicely(green('Stream is paused'))
1453
1454
1455 def replay():
1456 """
1457 Replay stream
1458 """
1459 db.semaphore_update_pause(False)
1460 printNicely(green('Stream is running back now'))
1461
1462
1463 def clear():
1464 """
1465 Clear screen
1466 """
1467 os.system('clear')
1468
1469
1470 def quit():
1471 """
1472 Exit all
1473 """
1474 try:
1475 save_history()
1476 os.system('rm -rf rainbow.db')
1477 os.kill(g['stream_pid'], signal.SIGKILL)
1478 printNicely(green('See you next time :)'))
1479 except:
1480 pass
1481 sys.exit()
1482
1483
1484 def reset():
1485 """
1486 Reset prefix of line
1487 """
1488 if g['reset']:
1489 printNicely(magenta('Need tips ? Type "h" and hit Enter key!'))
1490 g['reset'] = False
1491 try:
1492 printNicely(str(eval(g['cmd'])))
1493 except Exception:
1494 pass
1495
1496
1497 def process(cmd):
1498 """
1499 Process switch
1500 """
1501 return dict(zip(
1502 cmdset,
1503 [
1504 switch,
1505 trend,
1506 home,
1507 view,
1508 mentions,
1509 tweet,
1510 retweet,
1511 quote,
1512 allretweet,
1513 favorite,
1514 reply,
1515 delete,
1516 unfavorite,
1517 search,
1518 message,
1519 show,
1520 urlopen,
1521 ls,
1522 inbox,
1523 sent,
1524 trash,
1525 whois,
1526 follow,
1527 unfollow,
1528 mute,
1529 unmute,
1530 muting,
1531 block,
1532 unblock,
1533 report,
1534 list,
1535 cal,
1536 config,
1537 theme,
1538 help,
1539 pause,
1540 replay,
1541 clear,
1542 quit
1543 ]
1544 )).get(cmd, reset)
1545
1546
1547 def listen():
1548 """
1549 Listen to user's input
1550 """
1551 d = dict(zip(
1552 cmdset,
1553 [
1554 ['public', 'mine'], # switch
1555 [], # trend
1556 [], # home
1557 ['@'], # view
1558 [], # mentions
1559 [], # tweet
1560 [], # retweet
1561 [], # quote
1562 [], # allretweet
1563 [], # favorite
1564 [], # reply
1565 [], # delete
1566 [], # unfavorite
1567 ['#'], # search
1568 ['@'], # message
1569 ['image'], # show image
1570 [''], # open url
1571 ['fl', 'fr'], # list
1572 [], # inbox
1573 [], # sent
1574 [], # trash
1575 ['@'], # whois
1576 ['@'], # follow
1577 ['@'], # unfollow
1578 ['@'], # mute
1579 ['@'], # unmute
1580 ['@'], # muting
1581 ['@'], # block
1582 ['@'], # unblock
1583 ['@'], # report
1584 [
1585 'home',
1586 'all_mem',
1587 'all_sub',
1588 'add',
1589 'rm',
1590 'sub',
1591 'unsub',
1592 'own',
1593 'new',
1594 'update',
1595 'del'
1596 ], # list
1597 [], # cal
1598 [key for key in dict(get_all_config())], # config
1599 g['themes'], # theme
1600 [
1601 'discover',
1602 'tweets',
1603 'messages',
1604 'friends_and_followers',
1605 'list',
1606 'stream'
1607 ], # help
1608 [], # pause
1609 [], # reconnect
1610 [], # clear
1611 [], # quit
1612 ]
1613 ))
1614 init_interactive_shell(d)
1615 read_history()
1616 reset()
1617 while True:
1618 if g['prefix']:
1619 line = raw_input(g['decorated_name'](c['PREFIX']))
1620 else:
1621 line = raw_input()
1622 try:
1623 cmd = line.split()[0]
1624 except:
1625 cmd = ''
1626 g['cmd'] = cmd
1627 try:
1628 # Lock the semaphore
1629 db.semaphore_update_lock(True)
1630 # Save cmd to global variable and call process
1631 g['stuff'] = ' '.join(line.split()[1:])
1632 # Process the command
1633 process(cmd)()
1634 # Not re-display
1635 if cmd in ['switch', 't', 'rt', 'rep']:
1636 g['prefix'] = False
1637 else:
1638 g['prefix'] = True
1639 # Release the semaphore lock
1640 db.semaphore_update_lock(False)
1641 except Exception:
1642 printNicely(red('OMG something is wrong with Twitter right now.'))
1643
1644
1645 def stream(domain, args, name='Rainbow Stream'):
1646 """
1647 Track the stream
1648 """
1649 # The Logo
1650 art_dict = {
1651 c['USER_DOMAIN']: name,
1652 c['PUBLIC_DOMAIN']: args.track_keywords,
1653 c['SITE_DOMAIN']: name,
1654 }
1655 if c['ASCII_ART']:
1656 ascii_art(art_dict[domain])
1657 # These arguments are optional:
1658 stream_args = dict(
1659 timeout=args.timeout,
1660 block=not args.no_block,
1661 heartbeat_timeout=args.heartbeat_timeout)
1662 # Track keyword
1663 query_args = dict()
1664 if args.track_keywords:
1665 query_args['track'] = args.track_keywords
1666 # Get stream
1667 stream = TwitterStream(
1668 auth=authen(),
1669 domain=domain,
1670 **stream_args)
1671 try:
1672 if domain == c['USER_DOMAIN']:
1673 tweet_iter = stream.user(**query_args)
1674 elif domain == c['SITE_DOMAIN']:
1675 tweet_iter = stream.site(**query_args)
1676 else:
1677 if args.track_keywords:
1678 tweet_iter = stream.statuses.filter(**query_args)
1679 else:
1680 tweet_iter = stream.statuses.sample()
1681 for tweet in tweet_iter:
1682 if tweet is None:
1683 printNicely("-- None --")
1684 elif tweet is Timeout:
1685 printNicely("-- Timeout --")
1686 elif tweet is HeartbeatTimeout:
1687 printNicely("-- Heartbeat Timeout --")
1688 elif tweet is Hangup:
1689 printNicely("-- Hangup --")
1690 elif tweet.get('text'):
1691 draw(
1692 t=tweet,
1693 keyword=args.track_keywords,
1694 check_semaphore=True,
1695 fil=args.filter,
1696 ig=args.ignore,
1697 )
1698 elif tweet.get('direct_message'):
1699 print_message(tweet['direct_message'],check_semaphore=True)
1700 except TwitterHTTPError:
1701 printNicely('')
1702 printNicely(
1703 magenta("We have maximum connection problem with twitter'stream API right now :("))
1704
1705
1706 def fly():
1707 """
1708 Main function
1709 """
1710 # Initial
1711 args = parse_arguments()
1712 try:
1713 init(args)
1714 except TwitterHTTPError:
1715 printNicely('')
1716 printNicely(
1717 magenta("We have maximum connection problem with twitter'stream API right now :("))
1718 printNicely(magenta("Let's try again later."))
1719 save_history()
1720 os.system('rm -rf rainbow.db')
1721 sys.exit()
1722 # Spawn stream process
1723 p = Process(
1724 target=stream,
1725 args=(
1726 c['USER_DOMAIN'],
1727 args,
1728 g['original_name']))
1729 p.start()
1730 # Start listen process
1731 time.sleep(0.5)
1732 g['reset'] = True
1733 g['prefix'] = True
1734 g['stream_pid'] = p.pid
1735 listen()