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