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