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