drop custom config, change IMAGE_ON_TERM on app running
[rainbowstream.git] / rainbowstream / rainbow.py
CommitLineData
91476ec3
O
1"""
2Colorful user's timeline stream
3"""
78b81730 4from multiprocessing import Process
78b81730 5
b2b933a9 6import os
7import os.path
8import sys
9import signal
10import argparse
11import time
991c30af 12import requests
80b70d60 13import webbrowser
91476ec3 14
91476ec3 15from twitter.stream import TwitterStream, Timeout, HeartbeatTimeout, Hangup
54277114 16from twitter.api import *
91476ec3 17from twitter.oauth import OAuth, read_token_file
8c840a83 18from twitter.oauth_dance import oauth_dance
91476ec3 19from twitter.util import printNicely
91476ec3 20
7500d90b 21from .draw import *
2a6238f5
O
22from .colors import *
23from .config import *
777c52d4 24from .consumer import *
94a5f62e 25from .interactive import *
18cab06a 26from .db import *
991c30af 27from .c_image import *
c3bab4ef 28from .py3patch import *
29
531f5682 30# Global values
f405a7d0 31g = {}
531f5682
O
32
33# Database
18cab06a 34db = RainbowDB()
531f5682
O
35
36# Commands
94a5f62e 37cmdset = [
42fde775 38 'switch',
4592d231 39 'trend',
94a5f62e 40 'home',
41 'view',
305ce127 42 'mentions',
94a5f62e 43 't',
44 'rt',
80b70d60 45 'quote',
1f24a05a 46 'allrt',
7e4ccbf3 47 'fav',
94a5f62e 48 'rep',
49 'del',
7e4ccbf3 50 'ufav',
94a5f62e 51 's',
305ce127 52 'mes',
f5677fb1 53 'show',
80b70d60 54 'open',
0f6e4daf 55 'ls',
305ce127 56 'inbox',
57 'sent',
58 'trash',
e2b81717 59 'whois',
94a5f62e 60 'fl',
f5677fb1 61 'ufl',
5b2c4faf 62 'mute',
63 'unmute',
64 'muting',
305ce127 65 'block',
66 'unblock',
67 'report',
2d341029 68 'list',
813a5d80 69 'cal',
29fd0be6 70 'config',
632c6fa5 71 'theme',
94a5f62e 72 'h',
73 'c',
74 'q'
75]
22be990e 76
c075e6dc 77
91476ec3
O
78def parse_arguments():
79 """
80 Parse the arguments
81 """
91476ec3 82 parser = argparse.ArgumentParser(description=__doc__ or "")
2a6238f5
O
83 parser.add_argument(
84 '-to',
85 '--timeout',
86 help='Timeout for the stream (seconds).')
87 parser.add_argument(
88 '-ht',
89 '--heartbeat-timeout',
90 help='Set heartbeat timeout.',
91 default=90)
92 parser.add_argument(
93 '-nb',
94 '--no-block',
95 action='store_true',
96 help='Set stream to non-blocking.')
97 parser.add_argument(
98 '-tt',
99 '--track-keywords',
100 help='Search the stream for specific text.')
d51b4107
O
101 parser.add_argument(
102 '-fil',
103 '--filter',
104 help='Filter specific screen_name.')
105 parser.add_argument(
106 '-ig',
107 '--ignore',
108 help='Ignore specific screen_name.')
88af38d8 109 parser.add_argument(
c1fa7c94
O
110 '-iot',
111 '--image-on-term',
112 action='store_true',
113 help='Display all image on terminal.')
91476ec3
O
114 return parser.parse_args()
115
116
54277114
O
117def authen():
118 """
7b674cef 119 Authenticate with Twitter OAuth
54277114 120 """
8c840a83 121 # When using rainbow stream you must authorize.
2a6238f5
O
122 twitter_credential = os.environ.get(
123 'HOME',
124 os.environ.get(
125 'USERPROFILE',
126 '')) + os.sep + '.rainbow_oauth'
8c840a83
O
127 if not os.path.exists(twitter_credential):
128 oauth_dance("Rainbow Stream",
129 CONSUMER_KEY,
130 CONSUMER_SECRET,
131 twitter_credential)
132 oauth_token, oauth_token_secret = read_token_file(twitter_credential)
54277114 133 return OAuth(
2a6238f5
O
134 oauth_token,
135 oauth_token_secret,
136 CONSUMER_KEY,
137 CONSUMER_SECRET)
91476ec3 138
54277114 139
fe9bb33b 140def init(args):
54277114 141 """
9683e61d 142 Init function
54277114 143 """
9683e61d 144 # Get name
54277114 145 t = Twitter(auth=authen())
c5ff542b 146 name = '@' + t.account.verify_credentials()['screen_name']
42fde775 147 g['original_name'] = name[1:]
c075e6dc 148 g['decorated_name'] = color_func(c['DECORATED_NAME'])('[' + name + ']: ')
9683e61d 149 # Theme init
422dd385 150 files = os.listdir(os.path.dirname(__file__) + '/colorset')
c075e6dc 151 themes = [f.split('.')[0] for f in files if f.split('.')[-1] == 'json']
632c6fa5 152 g['themes'] = themes
1f2f6159 153 db.theme_store(c['THEME'])
9683e61d
O
154 # Semaphore init
155 db.semaphore_store(False)
fe9bb33b 156 # Image on term
157 c['IMAGE_ON_TERM'] = args.image_on_term
f405a7d0 158
42fde775 159def switch():
160 """
161 Switch stream
162 """
163 try:
164 target = g['stuff'].split()[0]
d51b4107
O
165 # Filter and ignore
166 args = parse_arguments()
7e4ccbf3 167 try:
d51b4107 168 if g['stuff'].split()[-1] == '-f':
14db58c7 169 guide = 'To ignore an option, just hit Enter key.'
170 printNicely(light_magenta(guide))
171 only = raw_input('Only nicks [Ex: @xxx,@yy]: ')
172 ignore = raw_input('Ignore nicks [Ex: @xxx,@yy]: ')
7e4ccbf3 173 args.filter = filter(None, only.split(','))
174 args.ignore = filter(None, ignore.split(','))
d51b4107 175 elif g['stuff'].split()[-1] == '-d':
632c6fa5
O
176 args.filter = c['ONLY_LIST']
177 args.ignore = c['IGNORE_LIST']
d51b4107
O
178 except:
179 printNicely(red('Sorry, wrong format.'))
180 return
42fde775 181 # Public stream
182 if target == 'public':
183 keyword = g['stuff'].split()[1]
184 if keyword[0] == '#':
185 keyword = keyword[1:]
42fde775 186 # Kill old process
187 os.kill(g['stream_pid'], signal.SIGKILL)
42fde775 188 args.track_keywords = keyword
42fde775 189 # Start new process
190 p = Process(
d51b4107 191 target=stream,
42fde775 192 args=(
632c6fa5 193 c['PUBLIC_DOMAIN'],
42fde775 194 args))
195 p.start()
196 g['stream_pid'] = p.pid
42fde775 197 # Personal stream
198 elif target == 'mine':
42fde775 199 # Kill old process
200 os.kill(g['stream_pid'], signal.SIGKILL)
42fde775 201 # Start new process
202 p = Process(
203 target=stream,
204 args=(
632c6fa5 205 c['USER_DOMAIN'],
42fde775 206 args,
207 g['original_name']))
208 p.start()
209 g['stream_pid'] = p.pid
d51b4107 210 printNicely('')
d51b4107
O
211 if args.filter:
212 printNicely(cyan('Only: ' + str(args.filter)))
213 if args.ignore:
214 printNicely(red('Ignore: ' + str(args.ignore)))
215 printNicely('')
42fde775 216 except:
217 printNicely(red('Sorry I can\'t understand.'))
42fde775 218
219
4592d231 220def trend():
221 """
222 Trend
223 """
224 t = Twitter(auth=authen())
48a25fe8 225 # Get country and town
4592d231 226 try:
227 country = g['stuff'].split()[0]
228 except:
229 country = ''
48a25fe8 230 try:
231 town = g['stuff'].split()[1]
232 except:
233 town = ''
48a25fe8 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)):
fe9bb33b 265 draw(t=tweet)
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:])):
fe9bb33b 281 draw(t=tweet)
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)):
fe9bb33b 296 draw(t=tweet)
305ce127 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):
fe9bb33b 372 draw(t=tweet)
1f24a05a 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.'))
fe9bb33b 389 draw(t.statuses.show(id=tid))
b8c1f42a 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.'))
fe9bb33b 438 draw(t.statuses.show(id=tid))
b8c1f42a 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],
59262e95
O
453 keyword=g['stuff'])
454 printNicely('')
b8c1f42a 455 else:
59262e95 456 printNicely(magenta('I\'m afraid there is no result'))
b2b933a9 457
f405a7d0 458
305ce127 459def message():
460 """
461 Send a direct message
462 """
463 t = Twitter(auth=authen())
464 user = g['stuff'].split()[0]
b8c1f42a 465 if user[0].startswith('@'):
305ce127 466 try:
467 content = g['stuff'].split()[1]
305ce127 468 except:
469 printNicely(red('Sorry I can\'t understand.'))
b8c1f42a
O
470 t.direct_messages.new(
471 screen_name=user[1:],
472 text=content
473 )
474 printNicely(green('Message sent.'))
305ce127 475 else:
476 printNicely(red('A name should begin with a \'@\''))
477
478
f5677fb1 479def show():
843647ad 480 """
f5677fb1 481 Show image
843647ad
O
482 """
483 t = Twitter(auth=authen())
f5677fb1
O
484 try:
485 target = g['stuff'].split()[0]
486 if target != 'image':
487 return
488 id = int(g['stuff'].split()[1])
305ce127 489 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
f5677fb1
O
490 tweet = t.statuses.show(id=tid)
491 media = tweet['entities']['media']
492 for m in media:
493 res = requests.get(m['media_url'])
b3164e62 494 img = Image.open(BytesIO(res.content))
f5677fb1
O
495 img.show()
496 except:
497 printNicely(red('Sorry I can\'t show this image.'))
843647ad
O
498
499
80bb2040 500def urlopen():
80b70d60
O
501 """
502 Open url
503 """
504 t = Twitter(auth=authen())
505 try:
506 if not g['stuff'].isdigit():
507 return
508 tid = db.rainbow_to_tweet_query(g['stuff'])[0].tweet_id
509 tweet = t.statuses.show(id=tid)
422dd385
O
510 link_ary = [
511 u for u in tweet['text'].split() if u.startswith('http://')]
80b70d60
O
512 if not link_ary:
513 printNicely(light_magenta('No url here @.@!'))
514 return
515 for link in link_ary:
516 webbrowser.open(link)
517 except:
518 printNicely(red('Sorry I can\'t open url in this tweet.'))
519
520
2d341029 521def ls():
0f6e4daf 522 """
523 List friends for followers
524 """
525 t = Twitter(auth=authen())
e2b81717
O
526 # Get name
527 try:
528 name = g['stuff'].split()[1]
b8c1f42a 529 if name.startswith('@'):
e2b81717
O
530 name = name[1:]
531 else:
532 printNicely(red('A name should begin with a \'@\''))
533 raise Exception('Invalid name')
534 except:
535 name = g['original_name']
536 # Get list followers or friends
0f6e4daf 537 try:
538 target = g['stuff'].split()[0]
0f6e4daf 539 except:
540 printNicely(red('Omg some syntax is wrong.'))
b8c1f42a
O
541 # Init cursor
542 d = {'fl': 'followers', 'fr': 'friends'}
543 next_cursor = -1
544 rel = {}
545 # Cursor loop
546 while next_cursor != 0:
547 list = getattr(t, d[target]).list(
548 screen_name=name,
549 cursor=next_cursor,
550 skip_status=True,
551 include_entities=False,
552 )
553 for u in list['users']:
554 rel[u['name']] = '@' + u['screen_name']
555 next_cursor = list['next_cursor']
556 # Print out result
2d341029 557 printNicely('All: ' + str(len(rel)) + ' ' + d[target] + '.')
b8c1f42a 558 for name in rel:
2d341029 559 user = ' ' + cycle_color(name)
422dd385 560 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
b8c1f42a 561 printNicely(user)
0f6e4daf 562
563
305ce127 564def inbox():
565 """
566 Inbox direct messages
567 """
568 t = Twitter(auth=authen())
632c6fa5 569 num = c['MESSAGES_DISPLAY']
305ce127 570 rel = []
571 if g['stuff'].isdigit():
572 num = g['stuff']
573 cur_page = 1
574 # Max message per page is 20 so we have to loop
575 while num > 20:
576 rel = rel + t.direct_messages(
577 count=20,
578 page=cur_page,
579 include_entities=False,
580 skip_status=False
48a25fe8 581 )
305ce127 582 num -= 20
583 cur_page += 1
584 rel = rel + t.direct_messages(
585 count=num,
586 page=cur_page,
587 include_entities=False,
588 skip_status=False
48a25fe8 589 )
e2b81717 590 # Display
305ce127 591 printNicely('Inbox: newest ' + str(len(rel)) + ' messages.')
592 for m in reversed(rel):
593 print_message(m)
594 printNicely('')
595
e2b81717 596
305ce127 597def sent():
598 """
599 Sent direct messages
600 """
601 t = Twitter(auth=authen())
632c6fa5 602 num = c['MESSAGES_DISPLAY']
305ce127 603 rel = []
604 if g['stuff'].isdigit():
605 num = int(g['stuff'])
606 cur_page = 1
607 # Max message per page is 20 so we have to loop
608 while num > 20:
609 rel = rel + t.direct_messages.sent(
610 count=20,
611 page=cur_page,
612 include_entities=False,
613 skip_status=False
48a25fe8 614 )
305ce127 615 num -= 20
616 cur_page += 1
617 rel = rel + t.direct_messages.sent(
618 count=num,
619 page=cur_page,
620 include_entities=False,
621 skip_status=False
48a25fe8 622 )
e2b81717 623 # Display
305ce127 624 printNicely('Sent: newest ' + str(len(rel)) + ' messages.')
625 for m in reversed(rel):
626 print_message(m)
627 printNicely('')
e2b81717 628
305ce127 629
630def trash():
631 """
632 Remove message
633 """
634 t = Twitter(auth=authen())
635 try:
636 rid = int(g['stuff'].split()[0])
305ce127 637 except:
638 printNicely(red('Sorry I can\'t understand.'))
b8c1f42a
O
639 mid = db.rainbow_to_message_query(rid)[0].message_id
640 t.direct_messages.destroy(id=mid)
641 printNicely(green('Message deleted.'))
305ce127 642
643
e2b81717
O
644def whois():
645 """
646 Show profile of a specific user
647 """
648 t = Twitter(auth=authen())
649 screen_name = g['stuff'].split()[0]
b8c1f42a 650 if screen_name.startswith('@'):
e2b81717
O
651 try:
652 user = t.users.show(
653 screen_name=screen_name[1:],
654 include_entities=False)
fe9bb33b 655 show_profile(user)
e2b81717
O
656 except:
657 printNicely(red('Omg no user.'))
658 else:
b8c1f42a 659 printNicely(red('A name should begin with a \'@\''))
e2b81717
O
660
661
f5677fb1 662def follow():
843647ad 663 """
f5677fb1 664 Follow a user
843647ad
O
665 """
666 t = Twitter(auth=authen())
f5677fb1 667 screen_name = g['stuff'].split()[0]
b8c1f42a
O
668 if screen_name.startswith('@'):
669 t.friendships.create(screen_name=screen_name[1:], follow=True)
670 printNicely(green('You are following ' + screen_name + ' now!'))
f5677fb1 671 else:
b8c1f42a 672 printNicely(red('A name should begin with a \'@\''))
f5677fb1
O
673
674
675def unfollow():
676 """
677 Unfollow a user
678 """
679 t = Twitter(auth=authen())
680 screen_name = g['stuff'].split()[0]
b8c1f42a
O
681 if screen_name.startswith('@'):
682 t.friendships.destroy(
683 screen_name=screen_name[1:],
684 include_entities=False)
685 printNicely(green('Unfollow ' + screen_name + ' success!'))
f5677fb1 686 else:
b8c1f42a 687 printNicely(red('A name should begin with a \'@\''))
843647ad
O
688
689
5b2c4faf 690def mute():
691 """
692 Mute a user
693 """
694 t = Twitter(auth=authen())
695 try:
696 screen_name = g['stuff'].split()[0]
697 except:
698 printNicely(red('A name should be specified. '))
699 return
700 if screen_name.startswith('@'):
701 rel = t.mutes.users.create(screen_name=screen_name[1:])
702 if isinstance(rel, dict):
703 printNicely(green(screen_name + ' is muted.'))
704 else:
705 printNicely(red(rel))
706 else:
707 printNicely(red('A name should begin with a \'@\''))
708
709
710def unmute():
711 """
712 Unmute a user
713 """
714 t = Twitter(auth=authen())
715 try:
716 screen_name = g['stuff'].split()[0]
717 except:
718 printNicely(red('A name should be specified. '))
719 return
720 if screen_name.startswith('@'):
721 rel = t.mutes.users.destroy(screen_name=screen_name[1:])
722 if isinstance(rel, dict):
723 printNicely(green(screen_name + ' is unmuted.'))
724 else:
725 printNicely(red(rel))
726 else:
727 printNicely(red('A name should begin with a \'@\''))
728
729
730def muting():
731 """
732 List muting user
733 """
734 t = Twitter(auth=authen())
735 # Init cursor
5b2c4faf 736 next_cursor = -1
737 rel = {}
738 # Cursor loop
739 while next_cursor != 0:
740 list = t.mutes.users.list(
741 screen_name=g['original_name'],
742 cursor=next_cursor,
743 skip_status=True,
744 include_entities=False,
745 )
746 for u in list['users']:
747 rel[u['name']] = '@' + u['screen_name']
748 next_cursor = list['next_cursor']
749 # Print out result
750 printNicely('All: ' + str(len(rel)) + ' people.')
751 for name in rel:
2d341029 752 user = ' ' + cycle_color(name)
422dd385 753 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
5b2c4faf 754 printNicely(user)
755
756
305ce127 757def block():
758 """
759 Block a user
760 """
761 t = Twitter(auth=authen())
762 screen_name = g['stuff'].split()[0]
b8c1f42a
O
763 if screen_name.startswith('@'):
764 t.blocks.create(
5b2c4faf 765 screen_name=screen_name[1:],
766 include_entities=False,
767 skip_status=True)
b8c1f42a 768 printNicely(green('You blocked ' + screen_name + '.'))
305ce127 769 else:
b8c1f42a 770 printNicely(red('A name should begin with a \'@\''))
305ce127 771
772
773def unblock():
774 """
775 Unblock a user
776 """
777 t = Twitter(auth=authen())
778 screen_name = g['stuff'].split()[0]
b8c1f42a
O
779 if screen_name.startswith('@'):
780 t.blocks.destroy(
781 screen_name=screen_name[1:],
782 include_entities=False,
783 skip_status=True)
784 printNicely(green('Unblock ' + screen_name + ' success!'))
305ce127 785 else:
b8c1f42a 786 printNicely(red('A name should begin with a \'@\''))
305ce127 787
788
789def report():
790 """
791 Report a user as a spam account
792 """
793 t = Twitter(auth=authen())
794 screen_name = g['stuff'].split()[0]
b8c1f42a
O
795 if screen_name.startswith('@'):
796 t.users.report_spam(
797 screen_name=screen_name[1:])
798 printNicely(green('You reported ' + screen_name + '.'))
305ce127 799 else:
800 printNicely(red('Sorry I can\'t understand.'))
801
802
8b8566d1
O
803def get_slug():
804 """
805 Get Slug Decorator
806 """
a8c5fce4 807 # Get list name
8b8566d1
O
808 list_name = raw_input(light_magenta('Give me the list\'s name: '))
809 # Get list name and owner
810 try:
811 owner, slug = list_name.split('/')
812 if slug.startswith('@'):
813 slug = slug[1:]
814 return owner, slug
815 except:
a8c5fce4
O
816 printNicely(
817 light_magenta('List name should follow "@owner/list_name" format.'))
8b8566d1
O
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:
a8c5fce4
O
1092 line = ' ' * 2 + \
1093 light_green(k) + ': ' + light_yellow(str(all_config[k]))
29fd0be6
O
1094 printNicely(line)
1095 guide = 'Detailed explanation can be found at ' + \
a8c5fce4
O
1096 color_func(c['TWEET']['link'])(
1097 'http://rainbowstream.readthedocs.org/en/latest/#config-explanation')
29fd0be6
O
1098 printNicely(guide)
1099 # Print specific config
1100 elif len(g['stuff'].split()) == 1:
1101 if g['stuff'] in all_config:
1102 k = g['stuff']
a8c5fce4
O
1103 line = ' ' * 2 + \
1104 light_green(k) + ': ' + light_yellow(str(all_config[k]))
29fd0be6
O
1105 printNicely(line)
1106 else:
fe9bb33b 1107 printNicely(red('No such config key.'))
29fd0be6
O
1108 # Print specific config's default value
1109 elif len(g['stuff'].split()) == 2 and g['stuff'].split()[-1] == 'default':
1110 key = g['stuff'].split()[0]
fe9bb33b 1111 try:
1112 value = get_default_config(key)
1113 line = ' ' * 2 + light_green(key) + ': ' + light_magenta(value)
1114 printNicely(line)
1115 except:
1116 printNicely(light_magenta('This config key does not exist in default.'))
1117 # Delete specific config key in config file
1118 elif len(g['stuff'].split()) == 2 and g['stuff'].split()[-1] == 'drop':
1119 key = g['stuff'].split()[0]
1120 try:
1121 delete_config(key)
1122 printNicely(light_green('Config key is dropped.'))
1123 except:
1124 printNicely(red('No such config key.'))
29fd0be6 1125 # Set specific config
a8c5fce4 1126 elif len(g['stuff'].split()) == 3 and g['stuff'].split()[1] == '=':
29fd0be6
O
1127 key = g['stuff'].split()[0]
1128 value = g['stuff'].split()[-1]
3c01ba57 1129 try:
a8c5fce4 1130 set_config(key, value)
720123f8 1131 printNicely(light_green('Updated successfully.'))
3c01ba57
O
1132 except:
1133 printNicely(light_magenta('Not valid value.'))
1134 return
29fd0be6
O
1135 reload_config()
1136 else:
1137 printNicely(light_magenta('Sorry I can\'s understand.'))
1138
1139
632c6fa5
O
1140def theme():
1141 """
1142 List and change theme
1143 """
1144 if not g['stuff']:
1145 # List themes
1146 for theme in g['themes']:
1f2f6159
O
1147 line = light_magenta(theme)
1148 if c['THEME'] == theme:
422dd385 1149 line = ' ' * 2 + light_yellow('* ') + line
ddb1e615 1150 else:
422dd385 1151 line = ' ' * 4 + line
632c6fa5 1152 printNicely(line)
1c8a5082 1153 elif g['stuff'] == 'current_as_default':
1f2f6159 1154 # Set as default
a8c5fce4 1155 set_config('THEME', c['THEME'])
1c8a5082 1156 printNicely(light_green('Okay it will be applied from next time :)'))
632c6fa5
O
1157 else:
1158 # Change theme
c075e6dc
O
1159 try:
1160 # Load new config
bb03272e 1161 if g['stuff'] != 'custom':
422dd385
O
1162 new_config = os.path.dirname(
1163 __file__) + '/colorset/' + g['stuff'] + '.json'
bb03272e
VNM
1164 else:
1165 new_config = os.environ.get(
422dd385 1166 'HOME', os.environ.get(
bb03272e
VNM
1167 'USERPROFILE',
1168 '')) + os.sep + '.rainbow_config.json'
632c6fa5 1169 new_config = load_config(new_config)
9e3418f1 1170 if new_config:
a5301bc0
VNM
1171 for nc in new_config:
1172 c[nc] = new_config[nc]
77c9b04e 1173 # Update db and reset colors
ddb1e615 1174 db.theme_update(g['stuff'])
1f2f6159 1175 c['THEME'] = g['stuff']
59262e95 1176 start_cycle()
c075e6dc
O
1177 g['decorated_name'] = color_func(
1178 c['DECORATED_NAME'])(
1179 '[@' + g['original_name'] + ']: ')
632c6fa5 1180 printNicely(green('Theme changed.'))
c075e6dc 1181 except:
1f2f6159 1182 printNicely(red('No such theme exists.'))
632c6fa5
O
1183
1184
2d341029 1185def help_discover():
f405a7d0 1186 """
2d341029 1187 Discover the world
f405a7d0 1188 """
7e4ccbf3 1189 s = ' ' * 2
1f24a05a 1190 # Discover the world
2d341029 1191 usage = '\n'
8bc30efd 1192 usage += s + grey(u'\u266A' + ' Discover the world \n')
c075e6dc
O
1193 usage += s * 2 + light_green('trend') + ' will show global trending topics. ' + \
1194 'You can try ' + light_green('trend US') + ' or ' + \
1195 light_green('trend JP Tokyo') + '.\n'
1196 usage += s * 2 + light_green('home') + ' will show your timeline. ' + \
1197 light_green('home 7') + ' will show 7 tweets.\n'
1198 usage += s * 2 + light_green('mentions') + ' will show mentions timeline. ' + \
1199 light_green('mentions 7') + ' will show 7 mention tweets.\n'
1200 usage += s * 2 + light_green('whois @mdo') + ' will show profile of ' + \
8bc30efd 1201 magenta('@mdo') + '.\n'
c075e6dc 1202 usage += s * 2 + light_green('view @mdo') + \
8bc30efd 1203 ' will show ' + magenta('@mdo') + '\'s home.\n'
03e08f86
O
1204 usage += s * 2 + light_green('s AKB48') + ' will search for "' + \
1205 light_yellow('AKB48') + '" and return 5 newest tweet. ' + \
1206 'Search can be performed with or without hashtag.\n'
2d341029
O
1207 printNicely(usage)
1208
8bc30efd 1209
2d341029
O
1210def help_tweets():
1211 """
1212 Tweets
1213 """
1214 s = ' ' * 2
1f24a05a 1215 # Tweet
2d341029 1216 usage = '\n'
8bc30efd 1217 usage += s + grey(u'\u266A' + ' Tweets \n')
c075e6dc
O
1218 usage += s * 2 + light_green('t oops ') + \
1219 'will tweet "' + light_yellow('oops') + '" immediately.\n'
7e4ccbf3 1220 usage += s * 2 + \
c075e6dc
O
1221 light_green('rt 12 ') + ' will retweet to tweet with ' + \
1222 light_yellow('[id=12]') + '.\n'
80b70d60
O
1223 usage += s * 2 + \
1224 light_green('quote 12 ') + ' will quote the tweet with ' + \
1225 light_yellow('[id=12]') + '. If no extra text is added, ' + \
1226 'the quote will be canceled.\n'
1f24a05a 1227 usage += s * 2 + \
c075e6dc
O
1228 light_green('allrt 12 20 ') + ' will list 20 newest retweet of the tweet with ' + \
1229 light_yellow('[id=12]') + '.\n'
1230 usage += s * 2 + light_green('rep 12 oops') + ' will reply "' + \
1231 light_yellow('oops') + '" to tweet with ' + \
1232 light_yellow('[id=12]') + '.\n'
7e4ccbf3 1233 usage += s * 2 + \
c075e6dc
O
1234 light_green('fav 12 ') + ' will favorite the tweet with ' + \
1235 light_yellow('[id=12]') + '.\n'
7e4ccbf3 1236 usage += s * 2 + \
c075e6dc
O
1237 light_green('ufav 12 ') + ' will unfavorite tweet with ' + \
1238 light_yellow('[id=12]') + '.\n'
8bc30efd 1239 usage += s * 2 + \
c075e6dc
O
1240 light_green('del 12 ') + ' will delete tweet with ' + \
1241 light_yellow('[id=12]') + '.\n'
1242 usage += s * 2 + light_green('show image 12') + ' will show image in tweet with ' + \
1243 light_yellow('[id=12]') + ' in your OS\'s image viewer.\n'
80b70d60
O
1244 usage += s * 2 + light_green('open 12') + ' will open url in tweet with ' + \
1245 light_yellow('[id=12]') + ' in your OS\'s default browser.\n'
2d341029 1246 printNicely(usage)
8bc30efd 1247
2d341029
O
1248
1249def help_messages():
1250 """
1251 Messages
1252 """
1253 s = ' ' * 2
5b2c4faf 1254 # Direct message
2d341029 1255 usage = '\n'
8bc30efd 1256 usage += s + grey(u'\u266A' + ' Direct messages \n')
c075e6dc
O
1257 usage += s * 2 + light_green('inbox') + ' will show inbox messages. ' + \
1258 light_green('inbox 7') + ' will show newest 7 messages.\n'
1259 usage += s * 2 + light_green('sent') + ' will show sent messages. ' + \
1260 light_green('sent 7') + ' will show newest 7 messages.\n'
1261 usage += s * 2 + light_green('mes @dtvd88 hi') + ' will send a "hi" messege to ' + \
8bc30efd 1262 magenta('@dtvd88') + '.\n'
c075e6dc
O
1263 usage += s * 2 + light_green('trash 5') + ' will remove message with ' + \
1264 light_yellow('[message_id=5]') + '.\n'
2d341029 1265 printNicely(usage)
8bc30efd 1266
2d341029
O
1267
1268def help_friends_and_followers():
1269 """
1270 Friends and Followers
1271 """
1272 s = ' ' * 2
8bc30efd 1273 # Follower and following
2d341029 1274 usage = '\n'
cdccb0d6 1275 usage += s + grey(u'\u266A' + ' Friends and followers \n')
8bc30efd 1276 usage += s * 2 + \
c075e6dc 1277 light_green('ls fl') + \
8bc30efd 1278 ' will list all followers (people who are following you).\n'
1279 usage += s * 2 + \
c075e6dc 1280 light_green('ls fr') + \
8bc30efd 1281 ' will list all friends (people who you are following).\n'
c075e6dc 1282 usage += s * 2 + light_green('fl @dtvd88') + ' will follow ' + \
305ce127 1283 magenta('@dtvd88') + '.\n'
c075e6dc 1284 usage += s * 2 + light_green('ufl @dtvd88') + ' will unfollow ' + \
305ce127 1285 magenta('@dtvd88') + '.\n'
c075e6dc 1286 usage += s * 2 + light_green('mute @dtvd88') + ' will mute ' + \
5b2c4faf 1287 magenta('@dtvd88') + '.\n'
c075e6dc 1288 usage += s * 2 + light_green('unmute @dtvd88') + ' will unmute ' + \
5b2c4faf 1289 magenta('@dtvd88') + '.\n'
c075e6dc
O
1290 usage += s * 2 + light_green('muting') + ' will list muting users.\n'
1291 usage += s * 2 + light_green('block @dtvd88') + ' will block ' + \
305ce127 1292 magenta('@dtvd88') + '.\n'
c075e6dc 1293 usage += s * 2 + light_green('unblock @dtvd88') + ' will unblock ' + \
305ce127 1294 magenta('@dtvd88') + '.\n'
c075e6dc 1295 usage += s * 2 + light_green('report @dtvd88') + ' will report ' + \
305ce127 1296 magenta('@dtvd88') + ' as a spam account.\n'
2d341029
O
1297 printNicely(usage)
1298
1299
1300def help_list():
1301 """
1302 Lists
1303 """
1304 s = ' ' * 2
1305 # Twitter list
1306 usage = '\n'
1307 usage += s + grey(u'\u266A' + ' Twitter list\n')
1308 usage += s * 2 + light_green('list') + \
1309 ' will show all lists you are belong to.\n'
1310 usage += s * 2 + light_green('list home') + \
bef33491 1311 ' will show timeline of list. You will be asked for list\'s name.\n'
a65bd34c 1312 usage += s * 2 + light_green('list all_mem') + \
2d341029 1313 ' will show list\'s all members.\n'
a65bd34c 1314 usage += s * 2 + light_green('list all_sub') + \
2d341029 1315 ' will show list\'s all subscribers.\n'
422dd385
O
1316 usage += s * 2 + light_green('list add') + \
1317 ' will add specific person to a list owned by you.' + \
1318 ' You will be asked for list\'s name and person\'s name.\n'
2d341029
O
1319 usage += s * 2 + light_green('list rm') + \
1320 ' will remove specific person from a list owned by you.' + \
1321 ' You will be asked for list\'s name and person\'s name.\n'
422dd385
O
1322 usage += s * 2 + light_green('list sub') + \
1323 ' will subscribe you to a specific list.\n'
1324 usage += s * 2 + light_green('list unsub') + \
1325 ' will unsubscribe you from a specific list.\n'
1326 usage += s * 2 + light_green('list own') + \
1327 ' will show all list owned by you.\n'
1328 usage += s * 2 + light_green('list new') + \
1329 ' will create a new list.\n'
1330 usage += s * 2 + light_green('list update') + \
1331 ' will update a list owned by you.\n'
1332 usage += s * 2 + light_green('list del') + \
1333 ' will delete a list owned by you.\n'
2d341029 1334 printNicely(usage)
8bc30efd 1335
2d341029
O
1336
1337def help_stream():
1338 """
1339 Stream switch
1340 """
1341 s = ' ' * 2
8bc30efd 1342 # Switch
2d341029 1343 usage = '\n'
8bc30efd 1344 usage += s + grey(u'\u266A' + ' Switching streams \n')
c075e6dc 1345 usage += s * 2 + light_green('switch public #AKB') + \
48a25fe8 1346 ' will switch to public stream and follow "' + \
c075e6dc
O
1347 light_yellow('AKB') + '" keyword.\n'
1348 usage += s * 2 + light_green('switch mine') + \
48a25fe8 1349 ' will switch to your personal stream.\n'
c075e6dc 1350 usage += s * 2 + light_green('switch mine -f ') + \
48a25fe8 1351 ' will prompt to enter the filter.\n'
c075e6dc 1352 usage += s * 3 + light_yellow('Only nicks') + \
48a25fe8 1353 ' filter will decide nicks will be INCLUDE ONLY.\n'
c075e6dc 1354 usage += s * 3 + light_yellow('Ignore nicks') + \
48a25fe8 1355 ' filter will decide nicks will be EXCLUDE.\n'
c075e6dc 1356 usage += s * 2 + light_green('switch mine -d') + \
48a25fe8 1357 ' will use the config\'s ONLY_LIST and IGNORE_LIST.\n'
2d341029
O
1358 printNicely(usage)
1359
1360
1361def help():
1362 """
1363 Help
1364 """
1365 s = ' ' * 2
1366 h, w = os.popen('stty size', 'r').read().split()
2d341029
O
1367 # Start
1368 usage = '\n'
1369 usage += s + 'Hi boss! I\'m ready to serve you right now!\n'
1370 usage += s + '-' * (int(w) - 4) + '\n'
1371 usage += s + 'You are ' + \
1372 light_yellow('already') + ' on your personal stream.\n'
1373 usage += s + 'Any update from Twitter will show up ' + \
1374 light_yellow('immediately') + '.\n'
1375 usage += s + 'In addtion, following commands are available right now:\n'
2d341029
O
1376 # Twitter help section
1377 usage += '\n'
1378 usage += s + grey(u'\u266A' + ' Twitter help\n')
1379 usage += s * 2 + light_green('h discover') + \
1380 ' will show help for discover commands.\n'
1381 usage += s * 2 + light_green('h tweets') + \
1382 ' will show help for tweets commands.\n'
1383 usage += s * 2 + light_green('h messages') + \
1384 ' will show help for messages commands.\n'
1385 usage += s * 2 + light_green('h friends_and_followers') + \
1386 ' will show help for friends and followers commands.\n'
1387 usage += s * 2 + light_green('h list') + \
1388 ' will show help for list commands.\n'
1389 usage += s * 2 + light_green('h stream') + \
1390 ' will show help for stream commands.\n'
1f24a05a 1391 # Smart shell
1392 usage += '\n'
1393 usage += s + grey(u'\u266A' + ' Smart shell\n')
c075e6dc 1394 usage += s * 2 + light_green('111111 * 9 / 7') + ' or any math expression ' + \
1f24a05a 1395 'will be evaluate by Python interpreter.\n'
c075e6dc 1396 usage += s * 2 + 'Even ' + light_green('cal') + ' will show the calendar' + \
1f24a05a 1397 ' for current month.\n'
29fd0be6 1398 # Config
1f24a05a 1399 usage += '\n'
29fd0be6
O
1400 usage += s + grey(u'\u266A' + ' Config \n')
1401 usage += s * 2 + light_green('theme') + ' will list available theme. ' + \
c075e6dc 1402 light_green('theme monokai') + ' will apply ' + light_yellow('monokai') + \
632c6fa5 1403 ' theme immediately.\n'
29fd0be6
O
1404 usage += s * 2 + light_green('config') + ' will list all config.\n'
1405 usage += s * 3 + \
1406 light_green('config ASCII_ART') + ' will output current value of ' +\
a8c5fce4 1407 light_yellow('ASCII_ART') + ' config key.\n'
29fd0be6 1408 usage += s * 3 + \
fe9bb33b 1409 light_green('config TREND_MAX default') + ' will output default value of ' + \
1410 light_yellow('TREND_MAX') + ' config key.\n'
1411 usage += s * 3 + \
1412 light_green('config CUSTOM_CONFIG drop') + ' will drop ' + \
1413 light_yellow('CUSTOM_CONFIG') + ' config key.\n'
29fd0be6 1414 usage += s * 3 + \
fe9bb33b 1415 light_green('config IMAGE_ON_TERM = true') + ' will set value of ' + \
1416 light_yellow('IMAGE_ON_TERM') + ' config key to ' + \
1417 light_yellow('True') + '.\n'
29fd0be6
O
1418 # Screening
1419 usage += '\n'
1420 usage += s + grey(u'\u266A' + ' Screening \n')
c075e6dc
O
1421 usage += s * 2 + light_green('h') + ' will show this help again.\n'
1422 usage += s * 2 + light_green('c') + ' will clear the screen.\n'
1423 usage += s * 2 + light_green('q') + ' will quit.\n'
8bc30efd 1424 # End
1425 usage += '\n'
7e4ccbf3 1426 usage += s + '-' * (int(w) - 4) + '\n'
8bc30efd 1427 usage += s + 'Have fun and hang tight! \n'
2d341029
O
1428 # Show help
1429 d = {
422dd385
O
1430 'discover': help_discover,
1431 'tweets': help_tweets,
1432 'messages': help_messages,
1433 'friends_and_followers': help_friends_and_followers,
1434 'list': help_list,
1435 'stream': help_stream,
2d341029
O
1436 }
1437 if g['stuff']:
1438 d[g['stuff'].strip()]()
1439 else:
1440 printNicely(usage)
f405a7d0
O
1441
1442
843647ad 1443def clear():
f405a7d0 1444 """
7b674cef 1445 Clear screen
f405a7d0 1446 """
843647ad 1447 os.system('clear')
f405a7d0
O
1448
1449
843647ad 1450def quit():
b8dda704
O
1451 """
1452 Exit all
1453 """
f5677fb1 1454 save_history()
8e633322 1455 os.system('rm -rf rainbow.db')
843647ad
O
1456 os.kill(g['stream_pid'], signal.SIGKILL)
1457 sys.exit()
b8dda704
O
1458
1459
94a5f62e 1460def reset():
f405a7d0 1461 """
94a5f62e 1462 Reset prefix of line
f405a7d0 1463 """
c91f75f2 1464 if g['reset']:
e3885f55 1465 printNicely(magenta('Need tips ? Type "h" and hit Enter key!'))
c91f75f2 1466 g['reset'] = False
d0a726d6 1467 try:
2a0cabee
O
1468 printNicely(str(eval(g['cmd'])))
1469 except Exception:
d0a726d6 1470 pass
54277114
O
1471
1472
94a5f62e 1473def process(cmd):
54277114 1474 """
94a5f62e 1475 Process switch
54277114 1476 """
94a5f62e 1477 return dict(zip(
1478 cmdset,
b2b933a9 1479 [
42fde775 1480 switch,
4592d231 1481 trend,
b2b933a9 1482 home,
1483 view,
305ce127 1484 mentions,
b2b933a9 1485 tweet,
1486 retweet,
80b70d60 1487 quote,
1f24a05a 1488 allretweet,
7e4ccbf3 1489 favorite,
b2b933a9 1490 reply,
1491 delete,
7e4ccbf3 1492 unfavorite,
b2b933a9 1493 search,
305ce127 1494 message,
f5677fb1 1495 show,
80bb2040 1496 urlopen,
2d341029 1497 ls,
305ce127 1498 inbox,
1499 sent,
1500 trash,
e2b81717 1501 whois,
f5677fb1
O
1502 follow,
1503 unfollow,
5b2c4faf 1504 mute,
1505 unmute,
1506 muting,
305ce127 1507 block,
1508 unblock,
1509 report,
2d341029 1510 list,
813a5d80 1511 cal,
29fd0be6 1512 config,
632c6fa5 1513 theme,
b2b933a9 1514 help,
1515 clear,
1516 quit
1517 ]
94a5f62e 1518 )).get(cmd, reset)
1519
1520
1521def listen():
42fde775 1522 """
1523 Listen to user's input
1524 """
d51b4107
O
1525 d = dict(zip(
1526 cmdset,
1527 [
affcb149 1528 ['public', 'mine'], # switch
4592d231 1529 [], # trend
7e4ccbf3 1530 [], # home
1531 ['@'], # view
305ce127 1532 [], # mentions
7e4ccbf3 1533 [], # tweet
1534 [], # retweet
80b70d60 1535 [], # quote
1f24a05a 1536 [], # allretweet
f5677fb1 1537 [], # favorite
7e4ccbf3 1538 [], # reply
1539 [], # delete
f5677fb1 1540 [], # unfavorite
7e4ccbf3 1541 ['#'], # search
305ce127 1542 ['@'], # message
f5677fb1 1543 ['image'], # show image
80b70d60 1544 [''], # open url
305ce127 1545 ['fl', 'fr'], # list
1546 [], # inbox
1547 [], # sent
1548 [], # trash
e2b81717 1549 ['@'], # whois
affcb149
O
1550 ['@'], # follow
1551 ['@'], # unfollow
5b2c4faf 1552 ['@'], # mute
1553 ['@'], # unmute
1554 ['@'], # muting
305ce127 1555 ['@'], # block
1556 ['@'], # unblock
1557 ['@'], # report
422dd385
O
1558 [
1559 'home',
1560 'all_mem',
1561 'all_sub',
1562 'add',
1563 'rm',
1564 'sub',
1565 'unsub',
1566 'own',
1567 'new',
1568 'update',
1569 'del'
1570 ], # list
813a5d80 1571 [], # cal
a8c5fce4 1572 [key for key in dict(get_all_config())], # config
1c8a5082 1573 g['themes'] + ['current_as_default'], # theme
422dd385
O
1574 [
1575 'discover',
1576 'tweets',
1577 'messages',
1578 'friends_and_followers',
1579 'list',
1580 'stream'
1581 ], # help
7e4ccbf3 1582 [], # clear
1583 [], # quit
d51b4107 1584 ]
7e4ccbf3 1585 ))
d51b4107 1586 init_interactive_shell(d)
f5677fb1 1587 read_history()
819569e8 1588 reset()
b2b933a9 1589 while True:
1dd312f5
O
1590 if g['prefix']:
1591 line = raw_input(g['decorated_name'])
1592 else:
1593 line = raw_input()
843647ad
O
1594 try:
1595 cmd = line.split()[0]
1596 except:
1597 cmd = ''
d0a726d6 1598 g['cmd'] = cmd
b8c1f42a 1599 try:
9683e61d
O
1600 # Lock the semaphore
1601 db.semaphore_update(True)
1602 # Save cmd to global variable and call process
b8c1f42a 1603 g['stuff'] = ' '.join(line.split()[1:])
9683e61d 1604 # Process the command
b8c1f42a 1605 process(cmd)()
9683e61d
O
1606 # Not re-display
1607 if cmd in ['switch', 't', 'rt', 'rep']:
1608 g['prefix'] = False
1609 else:
1610 g['prefix'] = True
1611 # Release the semaphore lock
1612 db.semaphore_update(False)
2d341029 1613 except Exception:
b8c1f42a 1614 printNicely(red('OMG something is wrong with Twitter right now.'))
54277114
O
1615
1616
42fde775 1617def stream(domain, args, name='Rainbow Stream'):
54277114 1618 """
f405a7d0 1619 Track the stream
54277114 1620 """
54277114 1621 # The Logo
42fde775 1622 art_dict = {
632c6fa5
O
1623 c['USER_DOMAIN']: name,
1624 c['PUBLIC_DOMAIN']: args.track_keywords,
1f2f6159 1625 c['SITE_DOMAIN']: name,
42fde775 1626 }
687567eb 1627 if c['ASCII_ART']:
c075e6dc 1628 ascii_art(art_dict[domain])
91476ec3
O
1629 # These arguments are optional:
1630 stream_args = dict(
1631 timeout=args.timeout,
1632 block=not args.no_block,
1633 heartbeat_timeout=args.heartbeat_timeout)
91476ec3
O
1634 # Track keyword
1635 query_args = dict()
1636 if args.track_keywords:
1637 query_args['track'] = args.track_keywords
91476ec3 1638 # Get stream
2a6238f5 1639 stream = TwitterStream(
22be990e 1640 auth=authen(),
42fde775 1641 domain=domain,
2a6238f5 1642 **stream_args)
2a0cabee
O
1643 try:
1644 if domain == c['USER_DOMAIN']:
1645 tweet_iter = stream.user(**query_args)
1646 elif domain == c['SITE_DOMAIN']:
1647 tweet_iter = stream.site(**query_args)
42fde775 1648 else:
2a0cabee
O
1649 if args.track_keywords:
1650 tweet_iter = stream.statuses.filter(**query_args)
1651 else:
1652 tweet_iter = stream.statuses.sample()
72c02928
VNM
1653 for tweet in tweet_iter:
1654 if tweet is None:
1655 printNicely("-- None --")
1656 elif tweet is Timeout:
1657 printNicely("-- Timeout --")
1658 elif tweet is HeartbeatTimeout:
1659 printNicely("-- Heartbeat Timeout --")
1660 elif tweet is Hangup:
1661 printNicely("-- Hangup --")
1662 elif tweet.get('text'):
1663 draw(
1664 t=tweet,
72c02928 1665 keyword=args.track_keywords,
9683e61d 1666 check_semaphore=True,
72c02928
VNM
1667 fil=args.filter,
1668 ig=args.ignore,
1669 )
14db58c7 1670 elif tweet.get('direct_message'):
1671 print_message(tweet['direct_message'])
2a0cabee
O
1672 except TwitterHTTPError:
1673 printNicely('')
c075e6dc 1674 printNicely(
2a0cabee 1675 magenta("We have maximum connection problem with twitter'stream API right now :("))
54277114
O
1676
1677
1678def fly():
1679 """
1680 Main function
1681 """
531f5682 1682 # Initial
42fde775 1683 args = parse_arguments()
2a0cabee 1684 try:
fe9bb33b 1685 init(args)
2a0cabee
O
1686 except TwitterHTTPError:
1687 printNicely('')
1688 printNicely(
2e1241c7 1689 magenta("Something wrong with Twitter Oauth right now :("))
1690 printNicely(
1691 magenta("Please delete ~/.rainbow_oauth and try again."))
2a0cabee
O
1692 save_history()
1693 os.system('rm -rf rainbow.db')
1694 sys.exit()
531f5682 1695 # Spawn stream process
c075e6dc
O
1696 p = Process(
1697 target=stream,
1698 args=(
422dd385 1699 c['USER_DOMAIN'],
c075e6dc
O
1700 args,
1701 g['original_name']))
42fde775 1702 p.start()
42fde775 1703 # Start listen process
819569e8 1704 time.sleep(0.5)
c91f75f2 1705 g['reset'] = True
1dd312f5 1706 g['prefix'] = True
f405a7d0 1707 g['stream_pid'] = p.pid
0f6e4daf 1708 listen()