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