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