refactoring and add various comments
[rainbowstream.git] / rainbowstream / rainbow.py
CommitLineData
91476ec3
O
1"""
2Colorful user's timeline stream
3"""
78b81730 4from multiprocessing import Process
78b81730 5
b2b933a9 6import os
7import os.path
8import sys
9import signal
10import argparse
11import time
991c30af 12import requests
80b70d60 13import webbrowser
91476ec3 14
91476ec3 15from twitter.stream import TwitterStream, Timeout, HeartbeatTimeout, Hangup
54277114 16from twitter.api import *
91476ec3 17from twitter.oauth import OAuth, read_token_file
8c840a83 18from twitter.oauth_dance import oauth_dance
91476ec3 19from twitter.util import printNicely
91476ec3 20
7500d90b 21from .draw import *
2a6238f5
O
22from .colors import *
23from .config import *
777c52d4 24from .consumer import *
94a5f62e 25from .interactive import *
18cab06a 26from .db import *
991c30af 27from .c_image import *
c3bab4ef 28from .py3patch import *
29
531f5682 30# Global values
f405a7d0 31g = {}
531f5682
O
32
33# Database
18cab06a 34db = RainbowDB()
531f5682
O
35
36# Commands
94a5f62e 37cmdset = [
42fde775 38 'switch',
4592d231 39 'trend',
94a5f62e 40 'home',
41 'view',
305ce127 42 'mentions',
94a5f62e 43 't',
44 'rt',
80b70d60 45 'quote',
1f24a05a 46 'allrt',
7e4ccbf3 47 'fav',
94a5f62e 48 'rep',
49 'del',
7e4ccbf3 50 'ufav',
94a5f62e 51 's',
305ce127 52 'mes',
f5677fb1 53 'show',
80b70d60 54 'open',
0f6e4daf 55 'ls',
305ce127 56 'inbox',
57 'sent',
58 'trash',
e2b81717 59 'whois',
94a5f62e 60 'fl',
f5677fb1 61 'ufl',
5b2c4faf 62 'mute',
63 'unmute',
64 'muting',
305ce127 65 'block',
66 'unblock',
67 'report',
2d341029 68 'list',
813a5d80 69 'cal',
29fd0be6 70 'config',
632c6fa5 71 'theme',
94a5f62e 72 'h',
73 'c',
74 'q'
75]
22be990e 76
c075e6dc 77
91476ec3
O
78def parse_arguments():
79 """
80 Parse the arguments
81 """
91476ec3 82 parser = argparse.ArgumentParser(description=__doc__ or "")
2a6238f5
O
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.')
d51b4107
O
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.')
88af38d8 109 parser.add_argument(
c1fa7c94
O
110 '-iot',
111 '--image-on-term',
112 action='store_true',
113 help='Display all image on terminal.')
91476ec3
O
114 return parser.parse_args()
115
116
54277114
O
117def authen():
118 """
7b674cef 119 Authenticate with Twitter OAuth
54277114 120 """
8c840a83 121 # When using rainbow stream you must authorize.
2a6238f5
O
122 twitter_credential = os.environ.get(
123 'HOME',
124 os.environ.get(
125 'USERPROFILE',
126 '')) + os.sep + '.rainbow_oauth'
8c840a83
O
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)
54277114 133 return OAuth(
2a6238f5
O
134 oauth_token,
135 oauth_token_secret,
136 CONSUMER_KEY,
137 CONSUMER_SECRET)
91476ec3 138
54277114 139
531f5682 140def init():
54277114 141 """
9683e61d 142 Init function
54277114 143 """
9683e61d 144 # Get name
54277114 145 t = Twitter(auth=authen())
c5ff542b 146 name = '@' + t.account.verify_credentials()['screen_name']
42fde775 147 g['original_name'] = name[1:]
c075e6dc 148 g['decorated_name'] = color_func(c['DECORATED_NAME'])('[' + name + ']: ')
9683e61d 149 # Theme init
422dd385 150 files = os.listdir(os.path.dirname(__file__) + '/colorset')
c075e6dc 151 themes = [f.split('.')[0] for f in files if f.split('.')[-1] == 'json']
632c6fa5 152 g['themes'] = themes
1f2f6159 153 db.theme_store(c['THEME'])
9683e61d
O
154 # Semaphore init
155 db.semaphore_store(False)
156
f405a7d0 157
42fde775 158def switch():
159 """
160 Switch stream
161 """
162 try:
163 target = g['stuff'].split()[0]
d51b4107
O
164 # Filter and ignore
165 args = parse_arguments()
7e4ccbf3 166 try:
d51b4107
O
167 if g['stuff'].split()[-1] == '-f':
168 only = raw_input('Only nicks: ')
169 ignore = raw_input('Ignore nicks: ')
7e4ccbf3 170 args.filter = filter(None, only.split(','))
171 args.ignore = filter(None, ignore.split(','))
d51b4107 172 elif g['stuff'].split()[-1] == '-d':
632c6fa5
O
173 args.filter = c['ONLY_LIST']
174 args.ignore = c['IGNORE_LIST']
d51b4107
O
175 except:
176 printNicely(red('Sorry, wrong format.'))
177 return
42fde775 178 # Public stream
179 if target == 'public':
180 keyword = g['stuff'].split()[1]
181 if keyword[0] == '#':
182 keyword = keyword[1:]
42fde775 183 # Kill old process
184 os.kill(g['stream_pid'], signal.SIGKILL)
42fde775 185 args.track_keywords = keyword
42fde775 186 # Start new process
187 p = Process(
d51b4107 188 target=stream,
42fde775 189 args=(
632c6fa5 190 c['PUBLIC_DOMAIN'],
42fde775 191 args))
192 p.start()
193 g['stream_pid'] = p.pid
42fde775 194 # Personal stream
195 elif target == 'mine':
42fde775 196 # Kill old process
197 os.kill(g['stream_pid'], signal.SIGKILL)
42fde775 198 # Start new process
199 p = Process(
200 target=stream,
201 args=(
632c6fa5 202 c['USER_DOMAIN'],
42fde775 203 args,
204 g['original_name']))
205 p.start()
206 g['stream_pid'] = p.pid
d51b4107 207 printNicely('')
d51b4107
O
208 if args.filter:
209 printNicely(cyan('Only: ' + str(args.filter)))
210 if args.ignore:
211 printNicely(red('Ignore: ' + str(args.ignore)))
212 printNicely('')
42fde775 213 except:
214 printNicely(red('Sorry I can\'t understand.'))
42fde775 215
216
4592d231 217def trend():
218 """
219 Trend
220 """
221 t = Twitter(auth=authen())
48a25fe8 222 # Get country and town
4592d231 223 try:
224 country = g['stuff'].split()[0]
225 except:
226 country = ''
48a25fe8 227 try:
228 town = g['stuff'].split()[1]
229 except:
230 town = ''
48a25fe8 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)
4592d231 251
252
7b674cef 253def home():
254 """
255 Home
256 """
257 t = Twitter(auth=authen())
632c6fa5 258 num = c['HOME_TWEET_NUM']
7b674cef 259 if g['stuff'].isdigit():
305ce127 260 num = int(g['stuff'])
94a5f62e 261 for tweet in reversed(t.statuses.home_timeline(count=num)):
c1fa7c94 262 draw(t=tweet, iot=g['iot'])
94a5f62e 263 printNicely('')
7b674cef 264
265
266def view():
267 """
268 Friend view
269 """
270 t = Twitter(auth=authen())
271 user = g['stuff'].split()[0]
b8fbcb70 272 if user[0] == '@':
273 try:
94a5f62e 274 num = int(g['stuff'].split()[1])
b8fbcb70 275 except:
632c6fa5 276 num = c['HOME_TWEET_NUM']
94a5f62e 277 for tweet in reversed(t.statuses.user_timeline(count=num, screen_name=user[1:])):
c1fa7c94 278 draw(t=tweet, iot=g['iot'])
94a5f62e 279 printNicely('')
b8fbcb70 280 else:
c91f75f2 281 printNicely(red('A name should begin with a \'@\''))
7b674cef 282
283
305ce127 284def mentions():
285 """
286 Mentions timeline
287 """
288 t = Twitter(auth=authen())
632c6fa5 289 num = c['HOME_TWEET_NUM']
305ce127 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
f405a7d0 297def tweet():
54277114 298 """
7b674cef 299 Tweet
54277114
O
300 """
301 t = Twitter(auth=authen())
f405a7d0 302 t.statuses.update(status=g['stuff'])
f405a7d0 303
b2b933a9 304
1ba4abfd
O
305def retweet():
306 """
307 ReTweet
308 """
309 t = Twitter(auth=authen())
310 try:
311 id = int(g['stuff'].split()[0])
1ba4abfd 312 except:
b8c1f42a
O
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)
1ba4abfd
O
317
318
80b70d60
O
319def 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')
595fdb16
O
335 notice = light_magenta('Compose mode ')
336 notice += light_yellow('(Enter nothing will cancel the quote)')
337 notice += light_magenta(':')
338 printNicely(notice)
80b70d60
O
339 extra = raw_input(quote)
340 if extra:
422dd385 341 t.statuses.update(status=quote + extra)
80b70d60
O
342 else:
343 printNicely(light_magenta('No text added.'))
344
345
1f24a05a 346def 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:
632c6fa5 362 num = c['RETWEETS_SHOW_NUM']
1f24a05a 363 # Get result and display
d8e901a4 364 rt_ary = t.statuses.retweets(id=tid, count=num)
1f24a05a 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
7e4ccbf3 373def favorite():
374 """
375 Favorite
376 """
377 t = Twitter(auth=authen())
378 try:
379 id = int(g['stuff'].split()[0])
7e4ccbf3 380 except:
b8c1f42a
O
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('')
7e4ccbf3 388
389
7b674cef 390def reply():
829cc2d8 391 """
7b674cef 392 Reply
829cc2d8
O
393 """
394 t = Twitter(auth=authen())
7b674cef 395 try:
396 id = int(g['stuff'].split()[0])
7b674cef 397 except:
c91f75f2 398 printNicely(red('Sorry I can\'t understand.'))
b8c1f42a
O
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)
7b674cef 405
406
407def delete():
408 """
409 Delete
410 """
411 t = Twitter(auth=authen())
412 try:
305ce127 413 rid = int(g['stuff'].split()[0])
7b674cef 414 except:
305ce127 415 printNicely(red('Sorry I can\'t understand.'))
b8c1f42a
O
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.'))
829cc2d8
O
420
421
7e4ccbf3 422def unfavorite():
423 """
424 Unfavorite
425 """
426 t = Twitter(auth=authen())
427 try:
428 id = int(g['stuff'].split()[0])
7e4ccbf3 429 except:
b8c1f42a
O
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('')
7e4ccbf3 437
438
f405a7d0
O
439def search():
440 """
7b674cef 441 Search
f405a7d0
O
442 """
443 t = Twitter(auth=authen())
59262e95
O
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('')
b8c1f42a 453 else:
59262e95 454 printNicely(magenta('I\'m afraid there is no result'))
b2b933a9 455
f405a7d0 456
305ce127 457def message():
458 """
459 Send a direct message
460 """
461 t = Twitter(auth=authen())
462 user = g['stuff'].split()[0]
b8c1f42a 463 if user[0].startswith('@'):
305ce127 464 try:
465 content = g['stuff'].split()[1]
305ce127 466 except:
467 printNicely(red('Sorry I can\'t understand.'))
b8c1f42a
O
468 t.direct_messages.new(
469 screen_name=user[1:],
470 text=content
471 )
472 printNicely(green('Message sent.'))
305ce127 473 else:
474 printNicely(red('A name should begin with a \'@\''))
475
476
f5677fb1 477def show():
843647ad 478 """
f5677fb1 479 Show image
843647ad
O
480 """
481 t = Twitter(auth=authen())
f5677fb1
O
482 try:
483 target = g['stuff'].split()[0]
484 if target != 'image':
485 return
486 id = int(g['stuff'].split()[1])
305ce127 487 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
f5677fb1
O
488 tweet = t.statuses.show(id=tid)
489 media = tweet['entities']['media']
490 for m in media:
491 res = requests.get(m['media_url'])
b3164e62 492 img = Image.open(BytesIO(res.content))
f5677fb1
O
493 img.show()
494 except:
495 printNicely(red('Sorry I can\'t show this image.'))
843647ad
O
496
497
80bb2040 498def urlopen():
80b70d60
O
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)
422dd385
O
508 link_ary = [
509 u for u in tweet['text'].split() if u.startswith('http://')]
80b70d60
O
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
2d341029 519def ls():
0f6e4daf 520 """
521 List friends for followers
522 """
523 t = Twitter(auth=authen())
e2b81717
O
524 # Get name
525 try:
526 name = g['stuff'].split()[1]
b8c1f42a 527 if name.startswith('@'):
e2b81717
O
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
0f6e4daf 535 try:
536 target = g['stuff'].split()[0]
0f6e4daf 537 except:
538 printNicely(red('Omg some syntax is wrong.'))
b8c1f42a
O
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
2d341029 555 printNicely('All: ' + str(len(rel)) + ' ' + d[target] + '.')
b8c1f42a 556 for name in rel:
2d341029 557 user = ' ' + cycle_color(name)
422dd385 558 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
b8c1f42a 559 printNicely(user)
0f6e4daf 560
561
305ce127 562def inbox():
563 """
564 Inbox direct messages
565 """
566 t = Twitter(auth=authen())
632c6fa5 567 num = c['MESSAGES_DISPLAY']
305ce127 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
48a25fe8 579 )
305ce127 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
48a25fe8 587 )
e2b81717 588 # Display
305ce127 589 printNicely('Inbox: newest ' + str(len(rel)) + ' messages.')
590 for m in reversed(rel):
591 print_message(m)
592 printNicely('')
593
e2b81717 594
305ce127 595def sent():
596 """
597 Sent direct messages
598 """
599 t = Twitter(auth=authen())
632c6fa5 600 num = c['MESSAGES_DISPLAY']
305ce127 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
48a25fe8 612 )
305ce127 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
48a25fe8 620 )
e2b81717 621 # Display
305ce127 622 printNicely('Sent: newest ' + str(len(rel)) + ' messages.')
623 for m in reversed(rel):
624 print_message(m)
625 printNicely('')
e2b81717 626
305ce127 627
628def trash():
629 """
630 Remove message
631 """
632 t = Twitter(auth=authen())
633 try:
634 rid = int(g['stuff'].split()[0])
305ce127 635 except:
636 printNicely(red('Sorry I can\'t understand.'))
b8c1f42a
O
637 mid = db.rainbow_to_message_query(rid)[0].message_id
638 t.direct_messages.destroy(id=mid)
639 printNicely(green('Message deleted.'))
305ce127 640
641
e2b81717
O
642def whois():
643 """
644 Show profile of a specific user
645 """
646 t = Twitter(auth=authen())
647 screen_name = g['stuff'].split()[0]
b8c1f42a 648 if screen_name.startswith('@'):
e2b81717
O
649 try:
650 user = t.users.show(
651 screen_name=screen_name[1:],
652 include_entities=False)
7500d90b 653 show_profile(user, g['iot'])
e2b81717
O
654 except:
655 printNicely(red('Omg no user.'))
656 else:
b8c1f42a 657 printNicely(red('A name should begin with a \'@\''))
e2b81717
O
658
659
f5677fb1 660def follow():
843647ad 661 """
f5677fb1 662 Follow a user
843647ad
O
663 """
664 t = Twitter(auth=authen())
f5677fb1 665 screen_name = g['stuff'].split()[0]
b8c1f42a
O
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!'))
f5677fb1 669 else:
b8c1f42a 670 printNicely(red('A name should begin with a \'@\''))
f5677fb1
O
671
672
673def unfollow():
674 """
675 Unfollow a user
676 """
677 t = Twitter(auth=authen())
678 screen_name = g['stuff'].split()[0]
b8c1f42a
O
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!'))
f5677fb1 684 else:
b8c1f42a 685 printNicely(red('A name should begin with a \'@\''))
843647ad
O
686
687
5b2c4faf 688def 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
708def 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
728def muting():
729 """
730 List muting user
731 """
732 t = Twitter(auth=authen())
733 # Init cursor
5b2c4faf 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:
2d341029 750 user = ' ' + cycle_color(name)
422dd385 751 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
5b2c4faf 752 printNicely(user)
753
754
305ce127 755def block():
756 """
757 Block a user
758 """
759 t = Twitter(auth=authen())
760 screen_name = g['stuff'].split()[0]
b8c1f42a
O
761 if screen_name.startswith('@'):
762 t.blocks.create(
5b2c4faf 763 screen_name=screen_name[1:],
764 include_entities=False,
765 skip_status=True)
b8c1f42a 766 printNicely(green('You blocked ' + screen_name + '.'))
305ce127 767 else:
b8c1f42a 768 printNicely(red('A name should begin with a \'@\''))
305ce127 769
770
771def unblock():
772 """
773 Unblock a user
774 """
775 t = Twitter(auth=authen())
776 screen_name = g['stuff'].split()[0]
b8c1f42a
O
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!'))
305ce127 783 else:
b8c1f42a 784 printNicely(red('A name should begin with a \'@\''))
305ce127 785
786
787def report():
788 """
789 Report a user as a spam account
790 """
791 t = Twitter(auth=authen())
792 screen_name = g['stuff'].split()[0]
b8c1f42a
O
793 if screen_name.startswith('@'):
794 t.users.report_spam(
795 screen_name=screen_name[1:])
796 printNicely(green('You reported ' + screen_name + '.'))
305ce127 797 else:
798 printNicely(red('Sorry I can\'t understand.'))
799
800
8b8566d1
O
801def get_slug():
802 """
803 Get Slug Decorator
804 """
a8c5fce4 805 # Get list name
8b8566d1
O
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:
a8c5fce4
O
814 printNicely(
815 light_magenta('List name should follow "@owner/list_name" format.'))
8b8566d1
O
816 raise Exception('Wrong list name')
817
818
2d341029
O
819def show_lists(t):
820 """
422dd385 821 List list
2d341029
O
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
830def list_home(t):
831 """
832 List home
833 """
8b8566d1 834 owner, slug = get_slug()
2d341029 835 res = t.lists.statuses(
422dd385
O
836 slug=slug,
837 owner_screen_name=owner,
838 count=c['LIST_MAX'],
2d341029
O
839 include_entities=False)
840 for tweet in res:
841 draw(t=tweet)
842 printNicely('')
843
844
845def list_members(t):
846 """
847 List members
848 """
8b8566d1 849 owner, slug = get_slug()
422dd385 850 # Get members
2d341029
O
851 rel = {}
852 next_cursor = -1
422dd385 853 while next_cursor != 0:
2d341029 854 m = t.lists.members(
422dd385
O
855 slug=slug,
856 owner_screen_name=owner,
857 cursor=next_cursor,
2d341029
O
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)
422dd385 865 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
2d341029
O
866 printNicely(user)
867
868
869def list_subscribers(t):
870 """
871 List subscribers
872 """
8b8566d1 873 owner, slug = get_slug()
422dd385 874 # Get subscribers
2d341029
O
875 rel = {}
876 next_cursor = -1
422dd385 877 while next_cursor != 0:
2d341029 878 m = t.lists.subscribers(
422dd385
O
879 slug=slug,
880 owner_screen_name=owner,
881 cursor=next_cursor,
2d341029
O
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)
422dd385 889 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
2d341029
O
890 printNicely(user)
891
892
422dd385
O
893def list_add(t):
894 """
895 Add specific user to a list
896 """
8b8566d1 897 owner, slug = get_slug()
422dd385
O
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
2d341029
O
912def list_remove(t):
913 """
914 Remove specific user from a list
915 """
8b8566d1 916 owner, slug = get_slug()
2d341029 917 # Remove
422dd385
O
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:]
2d341029
O
921 try:
922 t.lists.members.destroy(
422dd385
O
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
931def list_subscribe(t):
932 """
933 Subscribe to a list
934 """
8b8566d1 935 owner, slug = get_slug()
422dd385
O
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
947def list_unsubscribe(t):
948 """
949 Unsubscribe a list
950 """
8b8566d1 951 owner, slug = get_slug()
422dd385
O
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
963def 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
981def 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
998def 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.'))
3c85d8fc 1021 except:
422dd385
O
1022 printNicely(red('Oops something is wrong with Twitter :('))
1023
1024
1025def 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.'))
2d341029 1035 except:
422dd385 1036 printNicely(red('Oops something is wrong with Twitter :('))
2d341029
O
1037
1038
1039def 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
422dd385 1050 # Sub-function
2d341029
O
1051 action_ary = {
1052 'home': list_home,
1053 'all_mem': list_members,
1054 'all_sub': list_subscribers,
422dd385 1055 'add': list_add,
2d341029 1056 'rm': list_remove,
422dd385
O
1057 'sub': list_subscribe,
1058 'unsub': list_unsubscribe,
1059 'own': list_own,
1060 'new': list_new,
1061 'update': list_update,
1062 'del': list_delete,
2d341029
O
1063 }
1064 try:
1065 return action_ary[g['list_action']](t)
3c85d8fc 1066 except:
8b8566d1 1067 printNicely(red('Please try again.'))
2d341029
O
1068
1069
813a5d80 1070def cal():
1071 """
1072 Unix's command `cal`
1073 """
1074 # Format
1075 rel = os.popen('cal').read().split('\n')
1076 month = rel.pop(0)
813a5d80 1077 date = rel.pop(0)
2a0cabee 1078 show_calendar(month, date, rel)
813a5d80 1079
1080
29fd0be6
O
1081def 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:
a8c5fce4
O
1090 line = ' ' * 2 + \
1091 light_green(k) + ': ' + light_yellow(str(all_config[k]))
29fd0be6
O
1092 printNicely(line)
1093 guide = 'Detailed explanation can be found at ' + \
a8c5fce4
O
1094 color_func(c['TWEET']['link'])(
1095 'http://rainbowstream.readthedocs.org/en/latest/#config-explanation')
29fd0be6
O
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']
a8c5fce4
O
1101 line = ' ' * 2 + \
1102 light_green(k) + ': ' + light_yellow(str(all_config[k]))
29fd0be6
O
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)
a8c5fce4 1110 line = ' ' * 2 + light_green(key) + ': ' + light_magenta(value)
29fd0be6
O
1111 printNicely(line)
1112 # Set specific config
a8c5fce4 1113 elif len(g['stuff'].split()) == 3 and g['stuff'].split()[1] == '=':
29fd0be6
O
1114 key = g['stuff'].split()[0]
1115 value = g['stuff'].split()[-1]
3c01ba57 1116 try:
a8c5fce4 1117 set_config(key, value)
720123f8 1118 printNicely(light_green('Updated successfully.'))
3c01ba57
O
1119 except:
1120 printNicely(light_magenta('Not valid value.'))
1121 return
29fd0be6
O
1122 reload_config()
1123 else:
1124 printNicely(light_magenta('Sorry I can\'s understand.'))
1125
1126
632c6fa5
O
1127def theme():
1128 """
1129 List and change theme
1130 """
1131 if not g['stuff']:
1132 # List themes
1133 for theme in g['themes']:
1f2f6159
O
1134 line = light_magenta(theme)
1135 if c['THEME'] == theme:
422dd385 1136 line = ' ' * 2 + light_yellow('* ') + line
ddb1e615 1137 else:
422dd385 1138 line = ' ' * 4 + line
632c6fa5 1139 printNicely(line)
1c8a5082 1140 elif g['stuff'] == 'current_as_default':
1f2f6159 1141 # Set as default
a8c5fce4 1142 set_config('THEME', c['THEME'])
1c8a5082 1143 printNicely(light_green('Okay it will be applied from next time :)'))
632c6fa5
O
1144 else:
1145 # Change theme
c075e6dc
O
1146 try:
1147 # Load new config
bb03272e 1148 if g['stuff'] != 'custom':
422dd385
O
1149 new_config = os.path.dirname(
1150 __file__) + '/colorset/' + g['stuff'] + '.json'
bb03272e
VNM
1151 else:
1152 new_config = os.environ.get(
422dd385 1153 'HOME', os.environ.get(
bb03272e
VNM
1154 'USERPROFILE',
1155 '')) + os.sep + '.rainbow_config.json'
632c6fa5 1156 new_config = load_config(new_config)
9e3418f1 1157 if new_config:
a5301bc0
VNM
1158 for nc in new_config:
1159 c[nc] = new_config[nc]
77c9b04e 1160 # Update db and reset colors
ddb1e615 1161 db.theme_update(g['stuff'])
1f2f6159 1162 c['THEME'] = g['stuff']
59262e95 1163 start_cycle()
c075e6dc
O
1164 g['decorated_name'] = color_func(
1165 c['DECORATED_NAME'])(
1166 '[@' + g['original_name'] + ']: ')
632c6fa5 1167 printNicely(green('Theme changed.'))
c075e6dc 1168 except:
1f2f6159 1169 printNicely(red('No such theme exists.'))
632c6fa5
O
1170
1171
2d341029 1172def help_discover():
f405a7d0 1173 """
2d341029 1174 Discover the world
f405a7d0 1175 """
7e4ccbf3 1176 s = ' ' * 2
1f24a05a 1177 # Discover the world
2d341029 1178 usage = '\n'
8bc30efd 1179 usage += s + grey(u'\u266A' + ' Discover the world \n')
c075e6dc
O
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 ' + \
8bc30efd 1188 magenta('@mdo') + '.\n'
c075e6dc 1189 usage += s * 2 + light_green('view @mdo') + \
8bc30efd 1190 ' will show ' + magenta('@mdo') + '\'s home.\n'
03e08f86
O
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'
2d341029
O
1194 printNicely(usage)
1195
8bc30efd 1196
2d341029
O
1197def help_tweets():
1198 """
1199 Tweets
1200 """
1201 s = ' ' * 2
1f24a05a 1202 # Tweet
2d341029 1203 usage = '\n'
8bc30efd 1204 usage += s + grey(u'\u266A' + ' Tweets \n')
c075e6dc
O
1205 usage += s * 2 + light_green('t oops ') + \
1206 'will tweet "' + light_yellow('oops') + '" immediately.\n'
7e4ccbf3 1207 usage += s * 2 + \
c075e6dc
O
1208 light_green('rt 12 ') + ' will retweet to tweet with ' + \
1209 light_yellow('[id=12]') + '.\n'
1f24a05a 1210 usage += s * 2 + \
80b70d60
O
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 + \
c075e6dc
O
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'
7e4ccbf3 1220 usage += s * 2 + \
c075e6dc
O
1221 light_green('fav 12 ') + ' will favorite the tweet with ' + \
1222 light_yellow('[id=12]') + '.\n'
7e4ccbf3 1223 usage += s * 2 + \
c075e6dc
O
1224 light_green('ufav 12 ') + ' will unfavorite tweet with ' + \
1225 light_yellow('[id=12]') + '.\n'
8bc30efd 1226 usage += s * 2 + \
c075e6dc
O
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'
80b70d60
O
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'
2d341029 1233 printNicely(usage)
8bc30efd 1234
2d341029
O
1235
1236def help_messages():
1237 """
1238 Messages
1239 """
1240 s = ' ' * 2
5b2c4faf 1241 # Direct message
2d341029 1242 usage = '\n'
8bc30efd 1243 usage += s + grey(u'\u266A' + ' Direct messages \n')
c075e6dc
O
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 ' + \
8bc30efd 1249 magenta('@dtvd88') + '.\n'
c075e6dc
O
1250 usage += s * 2 + light_green('trash 5') + ' will remove message with ' + \
1251 light_yellow('[message_id=5]') + '.\n'
2d341029 1252 printNicely(usage)
8bc30efd 1253
2d341029
O
1254
1255def help_friends_and_followers():
1256 """
1257 Friends and Followers
1258 """
1259 s = ' ' * 2
8bc30efd 1260 # Follower and following
2d341029 1261 usage = '\n'
cdccb0d6 1262 usage += s + grey(u'\u266A' + ' Friends and followers \n')
8bc30efd 1263 usage += s * 2 + \
c075e6dc 1264 light_green('ls fl') + \
8bc30efd 1265 ' will list all followers (people who are following you).\n'
1266 usage += s * 2 + \
c075e6dc 1267 light_green('ls fr') + \
8bc30efd 1268 ' will list all friends (people who you are following).\n'
c075e6dc 1269 usage += s * 2 + light_green('fl @dtvd88') + ' will follow ' + \
305ce127 1270 magenta('@dtvd88') + '.\n'
c075e6dc 1271 usage += s * 2 + light_green('ufl @dtvd88') + ' will unfollow ' + \
305ce127 1272 magenta('@dtvd88') + '.\n'
c075e6dc 1273 usage += s * 2 + light_green('mute @dtvd88') + ' will mute ' + \
5b2c4faf 1274 magenta('@dtvd88') + '.\n'
c075e6dc 1275 usage += s * 2 + light_green('unmute @dtvd88') + ' will unmute ' + \
5b2c4faf 1276 magenta('@dtvd88') + '.\n'
c075e6dc
O
1277 usage += s * 2 + light_green('muting') + ' will list muting users.\n'
1278 usage += s * 2 + light_green('block @dtvd88') + ' will block ' + \
305ce127 1279 magenta('@dtvd88') + '.\n'
c075e6dc 1280 usage += s * 2 + light_green('unblock @dtvd88') + ' will unblock ' + \
305ce127 1281 magenta('@dtvd88') + '.\n'
c075e6dc 1282 usage += s * 2 + light_green('report @dtvd88') + ' will report ' + \
305ce127 1283 magenta('@dtvd88') + ' as a spam account.\n'
2d341029
O
1284 printNicely(usage)
1285
1286
1287def 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') + \
bef33491 1298 ' will show timeline of list. You will be asked for list\'s name.\n'
a65bd34c 1299 usage += s * 2 + light_green('list all_mem') + \
2d341029 1300 ' will show list\'s all members.\n'
a65bd34c 1301 usage += s * 2 + light_green('list all_sub') + \
2d341029 1302 ' will show list\'s all subscribers.\n'
422dd385
O
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'
2d341029
O
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'
422dd385
O
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'
2d341029 1321 printNicely(usage)
8bc30efd 1322
2d341029
O
1323
1324def help_stream():
1325 """
1326 Stream switch
1327 """
1328 s = ' ' * 2
8bc30efd 1329 # Switch
2d341029 1330 usage = '\n'
8bc30efd 1331 usage += s + grey(u'\u266A' + ' Switching streams \n')
c075e6dc 1332 usage += s * 2 + light_green('switch public #AKB') + \
48a25fe8 1333 ' will switch to public stream and follow "' + \
c075e6dc
O
1334 light_yellow('AKB') + '" keyword.\n'
1335 usage += s * 2 + light_green('switch mine') + \
48a25fe8 1336 ' will switch to your personal stream.\n'
c075e6dc 1337 usage += s * 2 + light_green('switch mine -f ') + \
48a25fe8 1338 ' will prompt to enter the filter.\n'
c075e6dc 1339 usage += s * 3 + light_yellow('Only nicks') + \
48a25fe8 1340 ' filter will decide nicks will be INCLUDE ONLY.\n'
c075e6dc 1341 usage += s * 3 + light_yellow('Ignore nicks') + \
48a25fe8 1342 ' filter will decide nicks will be EXCLUDE.\n'
c075e6dc 1343 usage += s * 2 + light_green('switch mine -d') + \
48a25fe8 1344 ' will use the config\'s ONLY_LIST and IGNORE_LIST.\n'
2d341029
O
1345 printNicely(usage)
1346
1347
1348def help():
1349 """
1350 Help
1351 """
1352 s = ' ' * 2
1353 h, w = os.popen('stty size', 'r').read().split()
2d341029
O
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'
2d341029
O
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'
1f24a05a 1378 # Smart shell
1379 usage += '\n'
1380 usage += s + grey(u'\u266A' + ' Smart shell\n')
c075e6dc 1381 usage += s * 2 + light_green('111111 * 9 / 7') + ' or any math expression ' + \
1f24a05a 1382 'will be evaluate by Python interpreter.\n'
c075e6dc 1383 usage += s * 2 + 'Even ' + light_green('cal') + ' will show the calendar' + \
1f24a05a 1384 ' for current month.\n'
29fd0be6 1385 # Config
1f24a05a 1386 usage += '\n'
29fd0be6
O
1387 usage += s + grey(u'\u266A' + ' Config \n')
1388 usage += s * 2 + light_green('theme') + ' will list available theme. ' + \
c075e6dc 1389 light_green('theme monokai') + ' will apply ' + light_yellow('monokai') + \
632c6fa5 1390 ' theme immediately.\n'
29fd0be6
O
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 ' +\
a8c5fce4 1394 light_yellow('ASCII_ART') + ' config key.\n'
29fd0be6
O
1395 usage += s * 3 + \
1396 light_green('config ASCII_ART default') + ' will output default value of ' + \
a8c5fce4 1397 light_yellow('ASCII_ART') + ' config key.\n'
29fd0be6
O
1398 usage += s * 3 + \
1399 light_green('config ASCII_ART = False') + ' will set value of ' + \
a8c5fce4
O
1400 light_yellow('ASCII_ART') + ' config key to ' + \
1401 light_yellow('False') + '.\n'
29fd0be6
O
1402 # Screening
1403 usage += '\n'
1404 usage += s + grey(u'\u266A' + ' Screening \n')
c075e6dc
O
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'
8bc30efd 1408 # End
1409 usage += '\n'
7e4ccbf3 1410 usage += s + '-' * (int(w) - 4) + '\n'
8bc30efd 1411 usage += s + 'Have fun and hang tight! \n'
2d341029
O
1412 # Show help
1413 d = {
422dd385
O
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,
2d341029
O
1420 }
1421 if g['stuff']:
1422 d[g['stuff'].strip()]()
1423 else:
1424 printNicely(usage)
f405a7d0
O
1425
1426
843647ad 1427def clear():
f405a7d0 1428 """
7b674cef 1429 Clear screen
f405a7d0 1430 """
843647ad 1431 os.system('clear')
f405a7d0
O
1432
1433
843647ad 1434def quit():
b8dda704
O
1435 """
1436 Exit all
1437 """
f5677fb1 1438 save_history()
8e633322 1439 os.system('rm -rf rainbow.db')
843647ad
O
1440 os.kill(g['stream_pid'], signal.SIGKILL)
1441 sys.exit()
b8dda704
O
1442
1443
94a5f62e 1444def reset():
f405a7d0 1445 """
94a5f62e 1446 Reset prefix of line
f405a7d0 1447 """
c91f75f2 1448 if g['reset']:
e3885f55 1449 printNicely(magenta('Need tips ? Type "h" and hit Enter key!'))
c91f75f2 1450 g['reset'] = False
d0a726d6 1451 try:
2a0cabee
O
1452 printNicely(str(eval(g['cmd'])))
1453 except Exception:
d0a726d6 1454 pass
54277114
O
1455
1456
94a5f62e 1457def process(cmd):
54277114 1458 """
94a5f62e 1459 Process switch
54277114 1460 """
94a5f62e 1461 return dict(zip(
1462 cmdset,
b2b933a9 1463 [
42fde775 1464 switch,
4592d231 1465 trend,
b2b933a9 1466 home,
1467 view,
305ce127 1468 mentions,
b2b933a9 1469 tweet,
1470 retweet,
80b70d60 1471 quote,
1f24a05a 1472 allretweet,
7e4ccbf3 1473 favorite,
b2b933a9 1474 reply,
1475 delete,
7e4ccbf3 1476 unfavorite,
b2b933a9 1477 search,
305ce127 1478 message,
f5677fb1 1479 show,
80bb2040 1480 urlopen,
2d341029 1481 ls,
305ce127 1482 inbox,
1483 sent,
1484 trash,
e2b81717 1485 whois,
f5677fb1
O
1486 follow,
1487 unfollow,
5b2c4faf 1488 mute,
1489 unmute,
1490 muting,
305ce127 1491 block,
1492 unblock,
1493 report,
2d341029 1494 list,
813a5d80 1495 cal,
29fd0be6 1496 config,
632c6fa5 1497 theme,
b2b933a9 1498 help,
1499 clear,
1500 quit
1501 ]
94a5f62e 1502 )).get(cmd, reset)
1503
1504
1505def listen():
42fde775 1506 """
1507 Listen to user's input
1508 """
d51b4107
O
1509 d = dict(zip(
1510 cmdset,
1511 [
affcb149 1512 ['public', 'mine'], # switch
4592d231 1513 [], # trend
7e4ccbf3 1514 [], # home
1515 ['@'], # view
305ce127 1516 [], # mentions
7e4ccbf3 1517 [], # tweet
1518 [], # retweet
80b70d60 1519 [], # quote
1f24a05a 1520 [], # allretweet
f5677fb1 1521 [], # favorite
7e4ccbf3 1522 [], # reply
1523 [], # delete
f5677fb1 1524 [], # unfavorite
7e4ccbf3 1525 ['#'], # search
305ce127 1526 ['@'], # message
f5677fb1 1527 ['image'], # show image
80b70d60 1528 [''], # open url
305ce127 1529 ['fl', 'fr'], # list
1530 [], # inbox
1531 [], # sent
1532 [], # trash
e2b81717 1533 ['@'], # whois
affcb149
O
1534 ['@'], # follow
1535 ['@'], # unfollow
5b2c4faf 1536 ['@'], # mute
1537 ['@'], # unmute
1538 ['@'], # muting
305ce127 1539 ['@'], # block
1540 ['@'], # unblock
1541 ['@'], # report
422dd385
O
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
813a5d80 1555 [], # cal
a8c5fce4 1556 [key for key in dict(get_all_config())], # config
1c8a5082 1557 g['themes'] + ['current_as_default'], # theme
422dd385
O
1558 [
1559 'discover',
1560 'tweets',
1561 'messages',
1562 'friends_and_followers',
1563 'list',
1564 'stream'
1565 ], # help
7e4ccbf3 1566 [], # clear
1567 [], # quit
d51b4107 1568 ]
7e4ccbf3 1569 ))
d51b4107 1570 init_interactive_shell(d)
f5677fb1 1571 read_history()
819569e8 1572 reset()
b2b933a9 1573 while True:
1dd312f5
O
1574 if g['prefix']:
1575 line = raw_input(g['decorated_name'])
1576 else:
1577 line = raw_input()
843647ad
O
1578 try:
1579 cmd = line.split()[0]
1580 except:
1581 cmd = ''
d0a726d6 1582 g['cmd'] = cmd
b8c1f42a 1583 try:
9683e61d
O
1584 # Lock the semaphore
1585 db.semaphore_update(True)
1586 # Save cmd to global variable and call process
b8c1f42a 1587 g['stuff'] = ' '.join(line.split()[1:])
9683e61d 1588 # Process the command
b8c1f42a 1589 process(cmd)()
9683e61d
O
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)
2d341029 1597 except Exception:
b8c1f42a 1598 printNicely(red('OMG something is wrong with Twitter right now.'))
54277114
O
1599
1600
42fde775 1601def stream(domain, args, name='Rainbow Stream'):
54277114 1602 """
f405a7d0 1603 Track the stream
54277114 1604 """
54277114 1605 # The Logo
42fde775 1606 art_dict = {
632c6fa5
O
1607 c['USER_DOMAIN']: name,
1608 c['PUBLIC_DOMAIN']: args.track_keywords,
1f2f6159 1609 c['SITE_DOMAIN']: name,
42fde775 1610 }
687567eb 1611 if c['ASCII_ART']:
c075e6dc 1612 ascii_art(art_dict[domain])
91476ec3
O
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)
91476ec3
O
1618 # Track keyword
1619 query_args = dict()
1620 if args.track_keywords:
1621 query_args['track'] = args.track_keywords
91476ec3 1622 # Get stream
2a6238f5 1623 stream = TwitterStream(
22be990e 1624 auth=authen(),
42fde775 1625 domain=domain,
2a6238f5 1626 **stream_args)
2a0cabee
O
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)
42fde775 1632 else:
2a0cabee
O
1633 if args.track_keywords:
1634 tweet_iter = stream.statuses.filter(**query_args)
1635 else:
1636 tweet_iter = stream.statuses.sample()
72c02928
VNM
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,
9683e61d 1651 check_semaphore=True,
72c02928
VNM
1652 fil=args.filter,
1653 ig=args.ignore,
1654 )
2a0cabee
O
1655 except TwitterHTTPError:
1656 printNicely('')
c075e6dc 1657 printNicely(
2a0cabee 1658 magenta("We have maximum connection problem with twitter'stream API right now :("))
54277114
O
1659
1660
1661def fly():
1662 """
1663 Main function
1664 """
531f5682 1665 # Initial
42fde775 1666 args = parse_arguments()
2a0cabee 1667 try:
531f5682 1668 init()
2a0cabee
O
1669 except TwitterHTTPError:
1670 printNicely('')
1671 printNicely(
2e1241c7 1672 magenta("Something wrong with Twitter Oauth right now :("))
1673 printNicely(
1674 magenta("Please delete ~/.rainbow_oauth and try again."))
2a0cabee
O
1675 save_history()
1676 os.system('rm -rf rainbow.db')
1677 sys.exit()
531f5682 1678 # Spawn stream process
c075e6dc
O
1679 p = Process(
1680 target=stream,
1681 args=(
422dd385 1682 c['USER_DOMAIN'],
c075e6dc
O
1683 args,
1684 g['original_name']))
42fde775 1685 p.start()
42fde775 1686 # Start listen process
819569e8 1687 time.sleep(0.5)
c91f75f2 1688 g['reset'] = True
1dd312f5 1689 g['prefix'] = True
f405a7d0 1690 g['stream_pid'] = p.pid
c1fa7c94 1691 g['iot'] = args.image_on_term
0f6e4daf 1692 listen()