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