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