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