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