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