Commad to show current version
[rainbowstream.git] / rainbowstream / rainbow.py
CommitLineData
b2b933a9 1import os
2import os.path
3import sys
4import signal
5import argparse
6import time
92983945 7import threading
991c30af 8import requests
80b70d60 9import webbrowser
7a8a52fc 10import traceback
6e8fb961 11import pkg_resources
c426a344 12import socks
13import socket
91476ec3 14
a65129d4 15from io import BytesIO
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 *
991c30af 27from .c_image import *
c3bab4ef 28from .py3patch import *
841260fe 29from .emoji import *
c3bab4ef 30
531f5682 31# Global values
f405a7d0 32g = {}
531f5682 33
92983945 34# Lock for streams
92983945
BS
35StreamLock = threading.Lock()
36
c075e6dc 37
91476ec3
O
38def parse_arguments():
39 """
40 Parse the arguments
41 """
91476ec3 42 parser = argparse.ArgumentParser(description=__doc__ or "")
2a6238f5
O
43 parser.add_argument(
44 '-to',
45 '--timeout',
46 help='Timeout for the stream (seconds).')
2a6238f5
O
47 parser.add_argument(
48 '-tt',
49 '--track-keywords',
50 help='Search the stream for specific text.')
d51b4107
O
51 parser.add_argument(
52 '-fil',
53 '--filter',
54 help='Filter specific screen_name.')
55 parser.add_argument(
56 '-ig',
57 '--ignore',
58 help='Ignore specific screen_name.')
88af38d8 59 parser.add_argument(
c1fa7c94
O
60 '-iot',
61 '--image-on-term',
62 action='store_true',
63 help='Display all image on terminal.')
c426a344 64 parser.add_argument(
65 '-ph',
66 '--proxy-host',
67 help='Use HTTP/SOCKS proxy for network connections.')
68 parser.add_argument(
69 '-pp',
70 '--proxy-port',
71 default=8080,
72 help='HTTP/SOCKS proxy port (Default: 8080).')
73 parser.add_argument(
74 '-pt',
75 '--proxy-type',
89e6bf4b 76 default='SOCKS5',
c426a344 77 help='Proxy type (HTTP, SOCKS4, SOCKS5; Default: SOCKS5).')
91476ec3
O
78 return parser.parse_args()
79
80
a65129d4
O
81def proxy_connect(args):
82 """
83 Connect to specified proxy
84 """
85 if args.proxy_host:
86 # Setup proxy by monkeypatching the standard lib
87 if args.proxy_type.lower() == "socks5" or not args.proxy_type:
88 socks.set_default_proxy(
89 socks.SOCKS5, args.proxy_host,
90 int(args.proxy_port))
91 elif args.proxy_type.lower() == "http":
92 socks.set_default_proxy(
93 socks.HTTP, args.proxy_host,
94 int(args.proxy_port))
95 elif args.proxy_type.lower() == "socks4":
96 socks.set_default_proxy(
97 socks.SOCKS4, args.proxy_host,
98 int(args.proxy_port))
99 else:
100 printNicely(
101 magenta("Sorry, wrong proxy type specified! Aborting..."))
102 sys.exit()
103 socket.socket = socks.socksocket
104
105
54277114
O
106def authen():
107 """
7b674cef 108 Authenticate with Twitter OAuth
54277114 109 """
8c840a83 110 # When using rainbow stream you must authorize.
2a6238f5
O
111 twitter_credential = os.environ.get(
112 'HOME',
113 os.environ.get(
114 'USERPROFILE',
115 '')) + os.sep + '.rainbow_oauth'
8c840a83
O
116 if not os.path.exists(twitter_credential):
117 oauth_dance("Rainbow Stream",
118 CONSUMER_KEY,
119 CONSUMER_SECRET,
120 twitter_credential)
121 oauth_token, oauth_token_secret = read_token_file(twitter_credential)
54277114 122 return OAuth(
2a6238f5
O
123 oauth_token,
124 oauth_token_secret,
125 CONSUMER_KEY,
126 CONSUMER_SECRET)
91476ec3 127
54277114 128
e3927852
O
129def build_mute_dict(dict_data=False):
130 """
131 Build muting list
132 """
133 t = Twitter(auth=authen())
134 # Init cursor
135 next_cursor = -1
136 screen_name_list = []
137 name_list = []
138 # Cursor loop
139 while next_cursor != 0:
140 list = t.mutes.users.list(
141 screen_name=g['original_name'],
142 cursor=next_cursor,
143 skip_status=True,
144 include_entities=False,
145 )
146 screen_name_list += ['@' + u['screen_name'] for u in list['users']]
147 name_list += [u['name'] for u in list['users']]
148 next_cursor = list['next_cursor']
149 # Return dict or list
150 if dict_data:
151 return dict(zip(screen_name_list, name_list))
152 else:
153 return screen_name_list
154
155
7a8a52fc
O
156def debug_option():
157 """
158 Save traceback when run in debug mode
159 """
160 if g['debug']:
161 g['traceback'].append(traceback.format_exc())
162
163
6e8fb961 164def upgrade_center():
165 """
166 Check latest and notify to upgrade
167 """
168 try:
dfbc7288 169 current = pkg_resources.get_distribution("rainbowstream").version
6e8fb961 170 url = 'https://raw.githubusercontent.com/DTVD/rainbowstream/master/setup.py'
9ee4a3cc 171 readme = requests.get(url).text
6e8fb961 172 latest = readme.split("version = \'")[1].split("\'")[0]
173 if current != latest:
dfbc7288 174 notice = light_magenta('RainbowStream latest version is ')
6e8fb961 175 notice += light_green(latest)
176 notice += light_magenta(' while your current version is ')
177 notice += light_yellow(current) + '\n'
dfbc7288 178 notice += light_magenta('You should upgrade with ')
179 notice += light_green('pip install -U rainbowstream')
6e8fb961 180 printNicely(notice)
bf766c7b
LP
181 else:
182 printNicely(yellow('You are runnig latest ' + current + ' version.'))
6e8fb961 183 except:
184 pass
185
186
fe9bb33b 187def init(args):
54277114 188 """
9683e61d 189 Init function
54277114 190 """
64156ac4
O
191 # Handle Ctrl C
192 ctrl_c_handler = lambda signum, frame: quit()
193 signal.signal(signal.SIGINT, ctrl_c_handler)
6e8fb961 194 # Upgrade notify
195 upgrade_center()
9683e61d 196 # Get name
54277114 197 t = Twitter(auth=authen())
67c663f8
O
198 credential = t.account.verify_credentials()
199 screen_name = '@' + credential['screen_name']
200 name = credential['name']
ceec8593 201 if not get_config('PREFIX'):
67c663f8 202 set_config('PREFIX', screen_name)
841260fe 203 c['PREFIX'] = emojize(c['PREFIX'])
c285decf 204 g['PREFIX'] = u2str(c['PREFIX'])
37cf396a 205 c['original_name'] = g['original_name'] = screen_name[1:]
67c663f8 206 g['full_name'] = name
ceec8593 207 g['decorated_name'] = lambda x: color_func(
be4dba0e 208 c['DECORATED_NAME'])('[' + x + ']: ', rl=True)
9683e61d 209 # Theme init
422dd385 210 files = os.listdir(os.path.dirname(__file__) + '/colorset')
c075e6dc 211 themes = [f.split('.')[0] for f in files if f.split('.')[-1] == 'json']
632c6fa5 212 g['themes'] = themes
4dc385b5 213 g['pause'] = False
67c663f8 214 g['message_threads'] = {}
4824b181 215 # Startup cmd
f1c1dfea 216 g['cmd'] = ''
6e8fb961 217 # Debug option default = True
218 g['debug'] = True
7a8a52fc 219 g['traceback'] = []
d7d9c67c 220 # Events
38a6dc30 221 c['events'] = []
9683e61d 222 # Semaphore init
99b52f5f 223 c['lock'] = False
99b52f5f
O
224 # Init tweet dict and message dict
225 c['tweet_dict'] = []
226 c['message_dict'] = []
fe9bb33b 227 # Image on term
228 c['IMAGE_ON_TERM'] = args.image_on_term
62686013 229 set_config('IMAGE_ON_TERM', str(c['IMAGE_ON_TERM']))
d4b36355
O
230 # Check type of ONLY_LIST and IGNORE_LIST
231 if not isinstance(c['ONLY_LIST'], list):
232 printNicely(red('ONLY_LIST is not a valid list value.'))
233 c['ONLY_LIST'] = []
234 if not isinstance(c['IGNORE_LIST'], list):
235 printNicely(red('IGNORE_LIST is not a valid list value.'))
236 c['IGNORE_LIST'] = []
e3927852
O
237 # Mute dict
238 c['IGNORE_LIST'] += build_mute_dict()
f405a7d0 239
ceec8593 240
4592d231 241def trend():
242 """
243 Trend
244 """
245 t = Twitter(auth=authen())
48a25fe8 246 # Get country and town
4592d231 247 try:
248 country = g['stuff'].split()[0]
249 except:
250 country = ''
48a25fe8 251 try:
252 town = g['stuff'].split()[1]
253 except:
254 town = ''
48a25fe8 255 avail = t.trends.available()
256 # World wide
257 if not country:
258 trends = t.trends.place(_id=1)[0]['trends']
259 print_trends(trends)
260 else:
261 for location in avail:
262 # Search for country and Town
263 if town:
264 if location['countryCode'] == country \
265 and location['placeType']['name'] == 'Town' \
266 and location['name'] == town:
267 trends = t.trends.place(_id=location['woeid'])[0]['trends']
268 print_trends(trends)
269 # Search for country only
270 else:
271 if location['countryCode'] == country \
272 and location['placeType']['name'] == 'Country':
273 trends = t.trends.place(_id=location['woeid'])[0]['trends']
274 print_trends(trends)
4592d231 275
276
7b674cef 277def home():
278 """
279 Home
280 """
281 t = Twitter(auth=authen())
632c6fa5 282 num = c['HOME_TWEET_NUM']
7b674cef 283 if g['stuff'].isdigit():
305ce127 284 num = int(g['stuff'])
94a5f62e 285 for tweet in reversed(t.statuses.home_timeline(count=num)):
fe9bb33b 286 draw(t=tweet)
94a5f62e 287 printNicely('')
7b674cef 288
289
99cd1fba
O
290def notification():
291 """
292 Show notifications
293 """
d7d9c67c 294 if c['events']:
295 for e in c['events']:
99cd1fba
O
296 print_event(e)
297 printNicely('')
298 else:
299 printNicely(magenta('Nothing at this time.'))
300
301
fd87ddac
O
302def mentions():
303 """
304 Mentions timeline
305 """
306 t = Twitter(auth=authen())
307 num = c['HOME_TWEET_NUM']
308 if g['stuff'].isdigit():
309 num = int(g['stuff'])
310 for tweet in reversed(t.statuses.mentions_timeline(count=num)):
311 draw(t=tweet)
312 printNicely('')
313
314
315def whois():
316 """
317 Show profile of a specific user
318 """
319 t = Twitter(auth=authen())
320 screen_name = g['stuff'].split()[0]
321 if screen_name.startswith('@'):
322 try:
323 user = t.users.show(
324 screen_name=screen_name[1:],
325 include_entities=False)
326 show_profile(user)
327 except:
7a8a52fc
O
328 debug_option()
329 printNicely(red('No user.'))
fd87ddac
O
330 else:
331 printNicely(red('A name should begin with a \'@\''))
332
333
7b674cef 334def view():
335 """
336 Friend view
337 """
338 t = Twitter(auth=authen())
339 user = g['stuff'].split()[0]
b8fbcb70 340 if user[0] == '@':
341 try:
94a5f62e 342 num = int(g['stuff'].split()[1])
b8fbcb70 343 except:
632c6fa5 344 num = c['HOME_TWEET_NUM']
9ee4a3cc
O
345 for tweet in reversed(
346 t.statuses.user_timeline(count=num, screen_name=user[1:])):
fe9bb33b 347 draw(t=tweet)
94a5f62e 348 printNicely('')
b8fbcb70 349 else:
c91f75f2 350 printNicely(red('A name should begin with a \'@\''))
7b674cef 351
352
fd87ddac 353def search():
2d0ad040 354 """
fd87ddac 355 Search
2d0ad040
J
356 """
357 t = Twitter(auth=authen())
954b3101 358 # Setup query
359 query = g['stuff'].strip()
360 type = c['SEARCH_TYPE']
361 if type not in ['mixed', 'recent', 'popular']:
362 type = 'mixed'
363 max_record = c['SEARCH_MAX_RECORD']
364 count = min(max_record, 100)
365 # Perform search
366 rel = t.search.tweets(
367 q=query,
368 type=type,
369 count=count
370 )['statuses']
371 # Return results
fd87ddac
O
372 if rel:
373 printNicely('Newest tweets:')
954b3101 374 for i in reversed(xrange(count)):
375 draw(t=rel[i], keyword=query)
fd87ddac
O
376 printNicely('')
377 else:
378 printNicely(magenta('I\'m afraid there is no result'))
2d0ad040
J
379
380
f405a7d0 381def tweet():
54277114 382 """
7b674cef 383 Tweet
54277114
O
384 """
385 t = Twitter(auth=authen())
f405a7d0 386 t.statuses.update(status=g['stuff'])
f405a7d0 387
b2b933a9 388
1ba4abfd
O
389def retweet():
390 """
391 ReTweet
392 """
393 t = Twitter(auth=authen())
394 try:
395 id = int(g['stuff'].split()[0])
1ba4abfd 396 except:
b8c1f42a
O
397 printNicely(red('Sorry I can\'t understand.'))
398 return
99b52f5f 399 tid = c['tweet_dict'][id]
b8c1f42a 400 t.statuses.retweet(id=tid, include_entities=False, trim_user=True)
1ba4abfd
O
401
402
80b70d60
O
403def quote():
404 """
405 Quote a tweet
406 """
b7c9c570 407 # Get tweet
80b70d60
O
408 t = Twitter(auth=authen())
409 try:
410 id = int(g['stuff'].split()[0])
411 except:
412 printNicely(red('Sorry I can\'t understand.'))
413 return
99b52f5f 414 tid = c['tweet_dict'][id]
80b70d60 415 tweet = t.statuses.show(id=tid)
b7c9c570 416 # Get formater
417 formater = format_quote(tweet)
418 if not formater:
7c437a0f 419 return
7c437a0f 420 # Get comment
be4dba0e 421 prefix = light_magenta('Compose your ', rl=True) + \
422 light_green('#comment: ', rl=True)
7c437a0f
O
423 comment = raw_input(prefix)
424 if comment:
425 quote = comment.join(formater.split('#comment'))
b7c9c570 426 t.statuses.update(status=quote)
80b70d60
O
427 else:
428 printNicely(light_magenta('No text added.'))
429
430
1f24a05a 431def allretweet():
432 """
433 List all retweet
434 """
435 t = Twitter(auth=authen())
436 # Get rainbow id
437 try:
438 id = int(g['stuff'].split()[0])
439 except:
440 printNicely(red('Sorry I can\'t understand.'))
441 return
99b52f5f 442 tid = c['tweet_dict'][id]
1f24a05a 443 # Get display num if exist
444 try:
445 num = int(g['stuff'].split()[1])
446 except:
632c6fa5 447 num = c['RETWEETS_SHOW_NUM']
1f24a05a 448 # Get result and display
d8e901a4 449 rt_ary = t.statuses.retweets(id=tid, count=num)
1f24a05a 450 if not rt_ary:
451 printNicely(magenta('This tweet has no retweet.'))
452 return
453 for tweet in reversed(rt_ary):
fe9bb33b 454 draw(t=tweet)
1f24a05a 455 printNicely('')
456
457
fd87ddac 458def conversation():
7e4ccbf3 459 """
fd87ddac 460 Conversation view
7e4ccbf3 461 """
462 t = Twitter(auth=authen())
463 try:
464 id = int(g['stuff'].split()[0])
7e4ccbf3 465 except:
b8c1f42a
O
466 printNicely(red('Sorry I can\'t understand.'))
467 return
99b52f5f 468 tid = c['tweet_dict'][id]
fd87ddac
O
469 tweet = t.statuses.show(id=tid)
470 limit = c['CONVERSATION_MAX']
471 thread_ref = []
472 thread_ref.append(tweet)
473 prev_tid = tweet['in_reply_to_status_id']
474 while prev_tid and limit:
475 limit -= 1
476 tweet = t.statuses.show(id=prev_tid)
477 prev_tid = tweet['in_reply_to_status_id']
478 thread_ref.append(tweet)
479
480 for tweet in reversed(thread_ref):
481 draw(t=tweet)
b8c1f42a 482 printNicely('')
7e4ccbf3 483
484
7b674cef 485def reply():
829cc2d8 486 """
7b674cef 487 Reply
829cc2d8
O
488 """
489 t = Twitter(auth=authen())
7b674cef 490 try:
491 id = int(g['stuff'].split()[0])
7b674cef 492 except:
c91f75f2 493 printNicely(red('Sorry I can\'t understand.'))
b8c1f42a 494 return
99b52f5f 495 tid = c['tweet_dict'][id]
b8c1f42a
O
496 user = t.statuses.show(id=tid)['user']['screen_name']
497 status = ' '.join(g['stuff'].split()[1:])
7c437a0f 498 status = '@' + user + ' ' + str2u(status)
b8c1f42a 499 t.statuses.update(status=status, in_reply_to_status_id=tid)
7b674cef 500
501
fd87ddac 502def favorite():
7b674cef 503 """
fd87ddac 504 Favorite
7b674cef 505 """
506 t = Twitter(auth=authen())
507 try:
99b52f5f 508 id = int(g['stuff'].split()[0])
7b674cef 509 except:
305ce127 510 printNicely(red('Sorry I can\'t understand.'))
b8c1f42a 511 return
99b52f5f 512 tid = c['tweet_dict'][id]
fd87ddac
O
513 t.favorites.create(_id=tid, include_entities=False)
514 printNicely(green('Favorited.'))
515 draw(t.statuses.show(id=tid))
516 printNicely('')
829cc2d8
O
517
518
7e4ccbf3 519def unfavorite():
520 """
521 Unfavorite
522 """
523 t = Twitter(auth=authen())
524 try:
525 id = int(g['stuff'].split()[0])
7e4ccbf3 526 except:
b8c1f42a
O
527 printNicely(red('Sorry I can\'t understand.'))
528 return
99b52f5f 529 tid = c['tweet_dict'][id]
b8c1f42a
O
530 t.favorites.destroy(_id=tid)
531 printNicely(green('Okay it\'s unfavorited.'))
fe9bb33b 532 draw(t.statuses.show(id=tid))
b8c1f42a 533 printNicely('')
7e4ccbf3 534
535
413857b5
O
536def share():
537 """
538 Copy url of a tweet to clipboard
539 """
540 t = Twitter(auth=authen())
541 try:
542 id = int(g['stuff'].split()[0])
66fe9f75 543 tid = c['tweet_dict'][id]
413857b5 544 except:
66fe9f75 545 printNicely(red('Tweet id is not valid.'))
413857b5 546 return
413857b5
O
547 tweet = t.statuses.show(id=tid)
548 url = 'https://twitter.com/' + \
549 tweet['user']['screen_name'] + '/status/' + str(tid)
eb9b6273 550 import platform
551 if platform.system().lower() == 'darwin':
552 os.system("echo '%s' | pbcopy" % url)
553 printNicely(green('Copied tweet\'s url to clipboard.'))
554 else:
555 printNicely('Direct link: ' + yellow(url))
413857b5
O
556
557
fd87ddac 558def delete():
305ce127 559 """
fd87ddac 560 Delete
305ce127 561 """
562 t = Twitter(auth=authen())
fd87ddac
O
563 try:
564 id = int(g['stuff'].split()[0])
565 except:
566 printNicely(red('Sorry I can\'t understand.'))
567 return
568 tid = c['tweet_dict'][id]
569 t.statuses.destroy(id=tid)
570 printNicely(green('Okay it\'s gone.'))
305ce127 571
572
f5677fb1 573def show():
843647ad 574 """
f5677fb1 575 Show image
843647ad
O
576 """
577 t = Twitter(auth=authen())
f5677fb1
O
578 try:
579 target = g['stuff'].split()[0]
580 if target != 'image':
581 return
582 id = int(g['stuff'].split()[1])
99b52f5f 583 tid = c['tweet_dict'][id]
f5677fb1
O
584 tweet = t.statuses.show(id=tid)
585 media = tweet['entities']['media']
586 for m in media:
587 res = requests.get(m['media_url'])
b3164e62 588 img = Image.open(BytesIO(res.content))
f5677fb1
O
589 img.show()
590 except:
7a8a52fc 591 debug_option()
f5677fb1 592 printNicely(red('Sorry I can\'t show this image.'))
843647ad
O
593
594
80bb2040 595def urlopen():
80b70d60
O
596 """
597 Open url
598 """
599 t = Twitter(auth=authen())
600 try:
601 if not g['stuff'].isdigit():
602 return
8101275e 603 tid = c['tweet_dict'][int(g['stuff'])]
80b70d60 604 tweet = t.statuses.show(id=tid)
571ea706
O
605 link_prefix = ('http://', 'https://')
606 link_ary = [u for u in tweet['text'].split()
607 if u.startswith(link_prefix)]
80b70d60
O
608 if not link_ary:
609 printNicely(light_magenta('No url here @.@!'))
610 return
611 for link in link_ary:
612 webbrowser.open(link)
613 except:
7a8a52fc 614 debug_option()
80b70d60
O
615 printNicely(red('Sorry I can\'t open url in this tweet.'))
616
617
305ce127 618def inbox():
619 """
67c663f8 620 Inbox threads
305ce127 621 """
622 t = Twitter(auth=authen())
632c6fa5 623 num = c['MESSAGES_DISPLAY']
305ce127 624 if g['stuff'].isdigit():
625 num = g['stuff']
67c663f8 626 # Get inbox messages
305ce127 627 cur_page = 1
67c663f8 628 inbox = []
305ce127 629 while num > 20:
67c663f8 630 inbox = inbox + t.direct_messages(
305ce127 631 count=20,
632 page=cur_page,
633 include_entities=False,
634 skip_status=False
48a25fe8 635 )
305ce127 636 num -= 20
637 cur_page += 1
67c663f8 638 inbox = inbox + t.direct_messages(
305ce127 639 count=num,
640 page=cur_page,
641 include_entities=False,
642 skip_status=False
48a25fe8 643 )
67c663f8 644 # Get sent messages
632c6fa5 645 num = c['MESSAGES_DISPLAY']
305ce127 646 if g['stuff'].isdigit():
67c663f8 647 num = g['stuff']
305ce127 648 cur_page = 1
67c663f8 649 sent = []
305ce127 650 while num > 20:
67c663f8 651 sent = sent + t.direct_messages.sent(
305ce127 652 count=20,
653 page=cur_page,
654 include_entities=False,
655 skip_status=False
48a25fe8 656 )
305ce127 657 num -= 20
658 cur_page += 1
67c663f8 659 sent = sent + t.direct_messages.sent(
305ce127 660 count=num,
661 page=cur_page,
662 include_entities=False,
663 skip_status=False
48a25fe8 664 )
67c663f8
O
665
666 d = {}
667 uniq_inbox = list(set(
03c0d30b 668 [(m['sender_screen_name'], m['sender']['name']) for m in inbox]
67c663f8 669 ))
03c0d30b 670 uniq_sent = list(set(
671 [(m['recipient_screen_name'], m['recipient']['name']) for m in sent]
67c663f8
O
672 ))
673 for partner in uniq_inbox:
674 inbox_ary = [m for m in inbox if m['sender_screen_name'] == partner[0]]
03c0d30b 675 sent_ary = [
676 m for m in sent if m['recipient_screen_name'] == partner[0]]
67c663f8
O
677 d[partner] = inbox_ary + sent_ary
678 for partner in uniq_sent:
679 if partner not in d:
03c0d30b 680 d[partner] = [
681 m for m in sent if m['recipient_screen_name'] == partner[0]]
67c663f8
O
682 g['message_threads'] = print_threads(d)
683
684
685def thread():
686 """
687 View a thread of message
688 """
689 try:
690 thread_id = int(g['stuff'])
03c0d30b 691 print_thread(
692 g['message_threads'][thread_id],
693 g['original_name'],
694 g['full_name'])
695 except Exception:
7a8a52fc 696 debug_option()
67c663f8 697 printNicely(red('No such thread.'))
e2b81717 698
305ce127 699
fd87ddac
O
700def message():
701 """
702 Send a direct message
703 """
704 t = Twitter(auth=authen())
03c0d30b 705 try:
706 user = g['stuff'].split()[0]
707 if user[0].startswith('@'):
708 content = ' '.join(g['stuff'].split()[1:])
709 t.direct_messages.new(
710 screen_name=user[1:],
711 text=content
712 )
713 printNicely(green('Message sent.'))
714 else:
715 printNicely(red('A name should begin with a \'@\''))
716 except:
7a8a52fc 717 debug_option()
03c0d30b 718 printNicely(red('Sorry I can\'t understand.'))
fd87ddac
O
719
720
305ce127 721def trash():
722 """
723 Remove message
724 """
725 t = Twitter(auth=authen())
726 try:
99b52f5f 727 id = int(g['stuff'].split()[0])
305ce127 728 except:
729 printNicely(red('Sorry I can\'t understand.'))
99b52f5f 730 mid = c['message_dict'][id]
b8c1f42a
O
731 t.direct_messages.destroy(id=mid)
732 printNicely(green('Message deleted.'))
305ce127 733
734
fd87ddac 735def ls():
e2b81717 736 """
fd87ddac 737 List friends for followers
e2b81717
O
738 """
739 t = Twitter(auth=authen())
fd87ddac
O
740 # Get name
741 try:
742 name = g['stuff'].split()[1]
743 if name.startswith('@'):
744 name = name[1:]
745 else:
746 printNicely(red('A name should begin with a \'@\''))
747 raise Exception('Invalid name')
748 except:
749 name = g['original_name']
750 # Get list followers or friends
751 try:
752 target = g['stuff'].split()[0]
753 except:
754 printNicely(red('Omg some syntax is wrong.'))
755 # Init cursor
756 d = {'fl': 'followers', 'fr': 'friends'}
757 next_cursor = -1
758 rel = {}
759 # Cursor loop
760 while next_cursor != 0:
761 list = getattr(t, d[target]).list(
762 screen_name=name,
763 cursor=next_cursor,
764 skip_status=True,
765 include_entities=False,
766 )
767 for u in list['users']:
768 rel[u['name']] = '@' + u['screen_name']
769 next_cursor = list['next_cursor']
770 # Print out result
771 printNicely('All: ' + str(len(rel)) + ' ' + d[target] + '.')
772 for name in rel:
773 user = ' ' + cycle_color(name)
774 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
775 printNicely(user)
e2b81717
O
776
777
f5677fb1 778def follow():
843647ad 779 """
f5677fb1 780 Follow a user
843647ad
O
781 """
782 t = Twitter(auth=authen())
f5677fb1 783 screen_name = g['stuff'].split()[0]
b8c1f42a
O
784 if screen_name.startswith('@'):
785 t.friendships.create(screen_name=screen_name[1:], follow=True)
786 printNicely(green('You are following ' + screen_name + ' now!'))
f5677fb1 787 else:
b8c1f42a 788 printNicely(red('A name should begin with a \'@\''))
f5677fb1
O
789
790
791def unfollow():
792 """
793 Unfollow a user
794 """
795 t = Twitter(auth=authen())
796 screen_name = g['stuff'].split()[0]
b8c1f42a
O
797 if screen_name.startswith('@'):
798 t.friendships.destroy(
799 screen_name=screen_name[1:],
800 include_entities=False)
801 printNicely(green('Unfollow ' + screen_name + ' success!'))
f5677fb1 802 else:
b8c1f42a 803 printNicely(red('A name should begin with a \'@\''))
843647ad
O
804
805
5b2c4faf 806def mute():
807 """
808 Mute a user
809 """
810 t = Twitter(auth=authen())
811 try:
812 screen_name = g['stuff'].split()[0]
813 except:
814 printNicely(red('A name should be specified. '))
815 return
816 if screen_name.startswith('@'):
e3927852
O
817 try:
818 rel = t.mutes.users.create(screen_name=screen_name[1:])
819 if isinstance(rel, dict):
820 printNicely(green(screen_name + ' is muted.'))
612d6863 821 c['IGNORE_LIST'] += [unc(screen_name)]
e3927852
O
822 c['IGNORE_LIST'] = list(set(c['IGNORE_LIST']))
823 else:
824 printNicely(red(rel))
825 except:
7a8a52fc 826 debug_option()
e3927852 827 printNicely(red('Something is wrong, can not mute now :('))
5b2c4faf 828 else:
829 printNicely(red('A name should begin with a \'@\''))
830
831
832def unmute():
833 """
834 Unmute a user
835 """
836 t = Twitter(auth=authen())
837 try:
838 screen_name = g['stuff'].split()[0]
839 except:
840 printNicely(red('A name should be specified. '))
841 return
842 if screen_name.startswith('@'):
e3927852
O
843 try:
844 rel = t.mutes.users.destroy(screen_name=screen_name[1:])
845 if isinstance(rel, dict):
846 printNicely(green(screen_name + ' is unmuted.'))
847 c['IGNORE_LIST'].remove(screen_name)
848 else:
849 printNicely(red(rel))
850 except:
851 printNicely(red('Maybe you are not muting this person ?'))
5b2c4faf 852 else:
853 printNicely(red('A name should begin with a \'@\''))
854
855
856def muting():
857 """
858 List muting user
859 """
e3927852
O
860 # Get dict of muting users
861 md = build_mute_dict(dict_data=True)
862 printNicely('All: ' + str(len(md)) + ' people.')
863 for name in md:
864 user = ' ' + cycle_color(md[name])
865 user += color_func(c['TWEET']['nick'])(' ' + name + ' ')
5b2c4faf 866 printNicely(user)
e3927852
O
867 # Update from Twitter
868 c['IGNORE_LIST'] = [n for n in md]
5b2c4faf 869
870
305ce127 871def block():
872 """
873 Block a user
874 """
875 t = Twitter(auth=authen())
876 screen_name = g['stuff'].split()[0]
b8c1f42a
O
877 if screen_name.startswith('@'):
878 t.blocks.create(
5b2c4faf 879 screen_name=screen_name[1:],
880 include_entities=False,
881 skip_status=True)
b8c1f42a 882 printNicely(green('You blocked ' + screen_name + '.'))
305ce127 883 else:
b8c1f42a 884 printNicely(red('A name should begin with a \'@\''))
305ce127 885
886
887def unblock():
888 """
889 Unblock a user
890 """
891 t = Twitter(auth=authen())
892 screen_name = g['stuff'].split()[0]
b8c1f42a
O
893 if screen_name.startswith('@'):
894 t.blocks.destroy(
895 screen_name=screen_name[1:],
896 include_entities=False,
897 skip_status=True)
898 printNicely(green('Unblock ' + screen_name + ' success!'))
305ce127 899 else:
b8c1f42a 900 printNicely(red('A name should begin with a \'@\''))
305ce127 901
902
903def report():
904 """
905 Report a user as a spam account
906 """
907 t = Twitter(auth=authen())
908 screen_name = g['stuff'].split()[0]
b8c1f42a
O
909 if screen_name.startswith('@'):
910 t.users.report_spam(
911 screen_name=screen_name[1:])
912 printNicely(green('You reported ' + screen_name + '.'))
305ce127 913 else:
914 printNicely(red('Sorry I can\'t understand.'))
915
916
8b8566d1
O
917def get_slug():
918 """
ee4c94b1 919 Get slug
8b8566d1 920 """
a8c5fce4 921 # Get list name
be4dba0e 922 list_name = raw_input(
923 light_magenta('Give me the list\'s name ("@owner/list_name"): ', rl=True))
8b8566d1
O
924 # Get list name and owner
925 try:
926 owner, slug = list_name.split('/')
927 if slug.startswith('@'):
928 slug = slug[1:]
929 return owner, slug
930 except:
a8c5fce4
O
931 printNicely(
932 light_magenta('List name should follow "@owner/list_name" format.'))
8b8566d1
O
933 raise Exception('Wrong list name')
934
935
2d341029
O
936def show_lists(t):
937 """
422dd385 938 List list
2d341029
O
939 """
940 rel = t.lists.list(screen_name=g['original_name'])
941 if rel:
942 print_list(rel)
943 else:
944 printNicely(light_magenta('You belong to no lists :)'))
945
946
947def list_home(t):
948 """
949 List home
950 """
8b8566d1 951 owner, slug = get_slug()
2d341029 952 res = t.lists.statuses(
422dd385
O
953 slug=slug,
954 owner_screen_name=owner,
955 count=c['LIST_MAX'],
2d341029 956 include_entities=False)
7304256c 957 for tweet in reversed(res):
2d341029
O
958 draw(t=tweet)
959 printNicely('')
960
961
962def list_members(t):
963 """
964 List members
965 """
8b8566d1 966 owner, slug = get_slug()
422dd385 967 # Get members
2d341029
O
968 rel = {}
969 next_cursor = -1
422dd385 970 while next_cursor != 0:
2d341029 971 m = t.lists.members(
422dd385
O
972 slug=slug,
973 owner_screen_name=owner,
974 cursor=next_cursor,
2d341029
O
975 include_entities=False)
976 for u in m['users']:
977 rel[u['name']] = '@' + u['screen_name']
978 next_cursor = m['next_cursor']
979 printNicely('All: ' + str(len(rel)) + ' members.')
980 for name in rel:
981 user = ' ' + cycle_color(name)
422dd385 982 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
2d341029
O
983 printNicely(user)
984
985
986def list_subscribers(t):
987 """
988 List subscribers
989 """
8b8566d1 990 owner, slug = get_slug()
422dd385 991 # Get subscribers
2d341029
O
992 rel = {}
993 next_cursor = -1
422dd385 994 while next_cursor != 0:
2d341029 995 m = t.lists.subscribers(
422dd385
O
996 slug=slug,
997 owner_screen_name=owner,
998 cursor=next_cursor,
2d341029
O
999 include_entities=False)
1000 for u in m['users']:
1001 rel[u['name']] = '@' + u['screen_name']
1002 next_cursor = m['next_cursor']
1003 printNicely('All: ' + str(len(rel)) + ' subscribers.')
1004 for name in rel:
1005 user = ' ' + cycle_color(name)
422dd385 1006 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
2d341029
O
1007 printNicely(user)
1008
1009
422dd385
O
1010def list_add(t):
1011 """
1012 Add specific user to a list
1013 """
8b8566d1 1014 owner, slug = get_slug()
422dd385 1015 # Add
be4dba0e 1016 user_name = raw_input(
1017 light_magenta(
1018 'Give me name of the newbie: ',
1019 rl=True))
422dd385
O
1020 if user_name.startswith('@'):
1021 user_name = user_name[1:]
1022 try:
1023 t.lists.members.create(
1024 slug=slug,
1025 owner_screen_name=owner,
1026 screen_name=user_name)
d6cc4c67 1027 printNicely(green('Added.'))
422dd385 1028 except:
7a8a52fc 1029 debug_option()
422dd385
O
1030 printNicely(light_magenta('I\'m sorry we can not add him/her.'))
1031
1032
2d341029
O
1033def list_remove(t):
1034 """
1035 Remove specific user from a list
1036 """
8b8566d1 1037 owner, slug = get_slug()
2d341029 1038 # Remove
be4dba0e 1039 user_name = raw_input(
1040 light_magenta(
1041 'Give me name of the unlucky one: ',
1042 rl=True))
422dd385
O
1043 if user_name.startswith('@'):
1044 user_name = user_name[1:]
2d341029
O
1045 try:
1046 t.lists.members.destroy(
422dd385
O
1047 slug=slug,
1048 owner_screen_name=owner,
1049 screen_name=user_name)
d6cc4c67 1050 printNicely(green('Gone.'))
422dd385 1051 except:
7a8a52fc 1052 debug_option()
422dd385
O
1053 printNicely(light_magenta('I\'m sorry we can not remove him/her.'))
1054
1055
1056def list_subscribe(t):
1057 """
1058 Subscribe to a list
1059 """
8b8566d1 1060 owner, slug = get_slug()
422dd385
O
1061 # Subscribe
1062 try:
1063 t.lists.subscribers.create(
1064 slug=slug,
1065 owner_screen_name=owner)
d6cc4c67 1066 printNicely(green('Done.'))
422dd385 1067 except:
7a8a52fc 1068 debug_option()
422dd385
O
1069 printNicely(
1070 light_magenta('I\'m sorry you can not subscribe to this list.'))
1071
1072
1073def list_unsubscribe(t):
1074 """
1075 Unsubscribe a list
1076 """
8b8566d1 1077 owner, slug = get_slug()
422dd385
O
1078 # Subscribe
1079 try:
1080 t.lists.subscribers.destroy(
1081 slug=slug,
1082 owner_screen_name=owner)
d6cc4c67 1083 printNicely(green('Done.'))
422dd385 1084 except:
7a8a52fc 1085 debug_option()
422dd385
O
1086 printNicely(
1087 light_magenta('I\'m sorry you can not unsubscribe to this list.'))
1088
1089
1090def list_own(t):
1091 """
1092 List own
1093 """
1094 rel = []
1095 next_cursor = -1
1096 while next_cursor != 0:
1097 res = t.lists.ownerships(
1098 screen_name=g['original_name'],
1099 cursor=next_cursor)
1100 rel += res['lists']
1101 next_cursor = res['next_cursor']
1102 if rel:
1103 print_list(rel)
1104 else:
1105 printNicely(light_magenta('You own no lists :)'))
1106
1107
1108def list_new(t):
1109 """
1110 Create a new list
1111 """
be4dba0e 1112 name = raw_input(light_magenta('New list\'s name: ', rl=True))
1113 mode = raw_input(
1114 light_magenta(
1115 'New list\'s mode (public/private): ',
1116 rl=True))
1117 description = raw_input(
1118 light_magenta(
1119 'New list\'s description: ',
1120 rl=True))
422dd385
O
1121 try:
1122 t.lists.create(
1123 name=name,
1124 mode=mode,
1125 description=description)
d6cc4c67 1126 printNicely(green(name + ' list is created.'))
422dd385 1127 except:
7a8a52fc 1128 debug_option()
422dd385
O
1129 printNicely(red('Oops something is wrong with Twitter :('))
1130
1131
1132def list_update(t):
1133 """
1134 Update a list
1135 """
be4dba0e 1136 slug = raw_input(
1137 light_magenta(
1138 'Your list that you want to update: ',
1139 rl=True))
1140 name = raw_input(
1141 light_magenta(
1142 'Update name (leave blank to unchange): ',
1143 rl=True))
1144 mode = raw_input(light_magenta('Update mode (public/private): ', rl=True))
1145 description = raw_input(light_magenta('Update description: ', rl=True))
422dd385
O
1146 try:
1147 if name:
1148 t.lists.update(
1149 slug='-'.join(slug.split()),
1150 owner_screen_name=g['original_name'],
1151 name=name,
1152 mode=mode,
1153 description=description)
1154 else:
1155 t.lists.update(
1156 slug=slug,
1157 owner_screen_name=g['original_name'],
1158 mode=mode,
1159 description=description)
d6cc4c67 1160 printNicely(green(slug + ' list is updated.'))
3c85d8fc 1161 except:
7a8a52fc 1162 debug_option()
422dd385
O
1163 printNicely(red('Oops something is wrong with Twitter :('))
1164
1165
1166def list_delete(t):
1167 """
1168 Delete a list
1169 """
be4dba0e 1170 slug = raw_input(
1171 light_magenta(
1172 'Your list that you want to delete: ',
1173 rl=True))
422dd385
O
1174 try:
1175 t.lists.destroy(
1176 slug='-'.join(slug.split()),
1177 owner_screen_name=g['original_name'])
d6cc4c67 1178 printNicely(green(slug + ' list is deleted.'))
2d341029 1179 except:
7a8a52fc 1180 debug_option()
422dd385 1181 printNicely(red('Oops something is wrong with Twitter :('))
2d341029
O
1182
1183
e3927852 1184def twitterlist():
2d341029
O
1185 """
1186 Twitter's list
1187 """
1188 t = Twitter(auth=authen())
1189 # List all lists or base on action
1190 try:
1191 g['list_action'] = g['stuff'].split()[0]
1192 except:
1193 show_lists(t)
1194 return
422dd385 1195 # Sub-function
2d341029
O
1196 action_ary = {
1197 'home': list_home,
1198 'all_mem': list_members,
1199 'all_sub': list_subscribers,
422dd385 1200 'add': list_add,
2d341029 1201 'rm': list_remove,
422dd385
O
1202 'sub': list_subscribe,
1203 'unsub': list_unsubscribe,
1204 'own': list_own,
1205 'new': list_new,
1206 'update': list_update,
1207 'del': list_delete,
2d341029
O
1208 }
1209 try:
1210 return action_ary[g['list_action']](t)
3c85d8fc 1211 except:
8b8566d1 1212 printNicely(red('Please try again.'))
2d341029
O
1213
1214
fd87ddac
O
1215def switch():
1216 """
1217 Switch stream
1218 """
1219 try:
1220 target = g['stuff'].split()[0]
1221 # Filter and ignore
1222 args = parse_arguments()
1223 try:
1224 if g['stuff'].split()[-1] == '-f':
1225 guide = 'To ignore an option, just hit Enter key.'
1226 printNicely(light_magenta(guide))
1227 only = raw_input('Only nicks [Ex: @xxx,@yy]: ')
1228 ignore = raw_input('Ignore nicks [Ex: @xxx,@yy]: ')
1229 args.filter = filter(None, only.split(','))
1230 args.ignore = filter(None, ignore.split(','))
fd87ddac
O
1231 except:
1232 printNicely(red('Sorry, wrong format.'))
1233 return
1234 # Public stream
1235 if target == 'public':
1236 keyword = g['stuff'].split()[1]
1237 if keyword[0] == '#':
1238 keyword = keyword[1:]
1239 # Kill old thread
1240 g['stream_stop'] = True
1241 args.track_keywords = keyword
72f58edb
O
1242 # Reset prefix
1243 g['PREFIX'] = u2str(emojize(c['PREFIX']))
fd87ddac
O
1244 # Start new thread
1245 th = threading.Thread(
1246 target=stream,
1247 args=(
1248 c['PUBLIC_DOMAIN'],
1249 args))
1250 th.daemon = True
1251 th.start()
1252 # Personal stream
1253 elif target == 'mine':
1254 # Kill old thread
1255 g['stream_stop'] = True
72f58edb
O
1256 # Reset prefix
1257 g['PREFIX'] = u2str(emojize(c['PREFIX']))
fd87ddac
O
1258 # Start new thread
1259 th = threading.Thread(
1260 target=stream,
1261 args=(
1262 c['USER_DOMAIN'],
1263 args,
1264 g['original_name']))
1265 th.daemon = True
1266 th.start()
ee4c94b1
O
1267 # Stream base on list
1268 elif target == 'list':
1269 owner, slug = get_slug()
1270 # Force python 2 not redraw readline buffer
6df5cc3a 1271 g['PREFIX'] = g['cmd'] = '/'.join([owner, slug])
ee4c94b1
O
1272 printNicely(light_yellow('getting list members ...'))
1273 # Get members
1274 t = Twitter(auth=authen())
1275 members = []
1276 next_cursor = -1
1277 while next_cursor != 0:
1278 m = t.lists.members(
1279 slug=slug,
1280 owner_screen_name=owner,
1281 cursor=next_cursor,
1282 include_entities=False)
1283 for u in m['users']:
1284 members.append('@' + u['screen_name'])
1285 next_cursor = m['next_cursor']
1286 printNicely(light_yellow('... done.'))
1287 # Build thread filter array
1288 args.filter = members
1289 # Kill old thread
1290 g['stream_stop'] = True
1291 # Start new thread
1292 th = threading.Thread(
1293 target=stream,
1294 args=(
1295 c['USER_DOMAIN'],
1296 args,
1297 slug))
1298 th.daemon = True
1299 th.start()
fd87ddac
O
1300 printNicely('')
1301 if args.filter:
ac03309c 1302 printNicely(cyan('Include: ' + str(len(args.filter)) + ' people.'))
fd87ddac 1303 if args.ignore:
ac03309c 1304 printNicely(red('Ignore: ' + str(len(args.ignore)) + ' people.'))
fd87ddac 1305 printNicely('')
050a294e 1306 except:
ee4c94b1 1307 debug_option()
fd87ddac
O
1308 printNicely(red('Sorry I can\'t understand.'))
1309
1310
813a5d80 1311def cal():
1312 """
1313 Unix's command `cal`
1314 """
1315 # Format
1316 rel = os.popen('cal').read().split('\n')
1317 month = rel.pop(0)
813a5d80 1318 date = rel.pop(0)
2a0cabee 1319 show_calendar(month, date, rel)
813a5d80 1320
1321
fd87ddac
O
1322def theme():
1323 """
1324 List and change theme
1325 """
1326 if not g['stuff']:
1327 # List themes
1328 for theme in g['themes']:
1329 line = light_magenta(theme)
1330 if c['THEME'] == theme:
1331 line = ' ' * 2 + light_yellow('* ') + line
1332 else:
1333 line = ' ' * 4 + line
1334 printNicely(line)
1335 else:
1336 # Change theme
1337 try:
1338 # Load new theme
1339 c['THEME'] = reload_theme(g['stuff'], c['THEME'])
1340 # Redefine decorated_name
1341 g['decorated_name'] = lambda x: color_func(
1342 c['DECORATED_NAME'])(
1343 '[' + x + ']: ')
1344 printNicely(green('Theme changed.'))
1345 except:
1346 printNicely(red('No such theme exists.'))
1347
1348
29fd0be6
O
1349def config():
1350 """
1351 Browse and change config
1352 """
1353 all_config = get_all_config()
1354 g['stuff'] = g['stuff'].strip()
1355 # List all config
1356 if not g['stuff']:
1357 for k in all_config:
a8c5fce4 1358 line = ' ' * 2 + \
d6cc4c67 1359 green(k) + ': ' + light_yellow(str(all_config[k]))
29fd0be6
O
1360 printNicely(line)
1361 guide = 'Detailed explanation can be found at ' + \
a8c5fce4
O
1362 color_func(c['TWEET']['link'])(
1363 'http://rainbowstream.readthedocs.org/en/latest/#config-explanation')
29fd0be6
O
1364 printNicely(guide)
1365 # Print specific config
1366 elif len(g['stuff'].split()) == 1:
1367 if g['stuff'] in all_config:
1368 k = g['stuff']
a8c5fce4 1369 line = ' ' * 2 + \
d6cc4c67 1370 green(k) + ': ' + light_yellow(str(all_config[k]))
29fd0be6
O
1371 printNicely(line)
1372 else:
fe9bb33b 1373 printNicely(red('No such config key.'))
29fd0be6
O
1374 # Print specific config's default value
1375 elif len(g['stuff'].split()) == 2 and g['stuff'].split()[-1] == 'default':
1376 key = g['stuff'].split()[0]
fe9bb33b 1377 try:
1378 value = get_default_config(key)
d6cc4c67 1379 line = ' ' * 2 + green(key) + ': ' + light_magenta(value)
fe9bb33b 1380 printNicely(line)
050a294e
O
1381 except:
1382 debug_option()
1383 printNicely(red('Just can not get the default.'))
fe9bb33b 1384 # Delete specific config key in config file
1385 elif len(g['stuff'].split()) == 2 and g['stuff'].split()[-1] == 'drop':
1386 key = g['stuff'].split()[0]
1387 try:
1388 delete_config(key)
d6cc4c67 1389 printNicely(green('Config key is dropped.'))
050a294e
O
1390 except:
1391 debug_option()
1392 printNicely(red('Just can not drop the key.'))
29fd0be6 1393 # Set specific config
a8c5fce4 1394 elif len(g['stuff'].split()) == 3 and g['stuff'].split()[1] == '=':
29fd0be6
O
1395 key = g['stuff'].split()[0]
1396 value = g['stuff'].split()[-1]
ceec8593 1397 if key == 'THEME' and not validate_theme(value):
1398 printNicely(red('Invalid theme\'s value.'))
1399 return
3c01ba57 1400 try:
a8c5fce4 1401 set_config(key, value)
050a294e 1402 # Keys that needs to be apply immediately
ceec8593 1403 if key == 'THEME':
baec5f50 1404 c['THEME'] = reload_theme(value, c['THEME'])
ceec8593 1405 g['decorated_name'] = lambda x: color_func(
a8e71259 1406 c['DECORATED_NAME'])('[' + x + ']: ')
050a294e
O
1407 elif key == 'PREFIX':
1408 g['PREFIX'] = u2str(emojize(c['PREFIX']))
a8e71259 1409 reload_config()
d6cc4c67 1410 printNicely(green('Updated successfully.'))
050a294e
O
1411 except:
1412 debug_option()
1413 printNicely(red('Just can not set the key.'))
29fd0be6
O
1414 else:
1415 printNicely(light_magenta('Sorry I can\'s understand.'))
1416
1417
2d341029 1418def help_discover():
f405a7d0 1419 """
2d341029 1420 Discover the world
f405a7d0 1421 """
7e4ccbf3 1422 s = ' ' * 2
1f24a05a 1423 # Discover the world
2d341029 1424 usage = '\n'
8bc30efd 1425 usage += s + grey(u'\u266A' + ' Discover the world \n')
c075e6dc
O
1426 usage += s * 2 + light_green('trend') + ' will show global trending topics. ' + \
1427 'You can try ' + light_green('trend US') + ' or ' + \
1428 light_green('trend JP Tokyo') + '.\n'
1429 usage += s * 2 + light_green('home') + ' will show your timeline. ' + \
1430 light_green('home 7') + ' will show 7 tweets.\n'
99cd1fba
O
1431 usage += s * 2 + \
1432 light_green('notification') + ' will show your recent notification.\n'
c075e6dc
O
1433 usage += s * 2 + light_green('mentions') + ' will show mentions timeline. ' + \
1434 light_green('mentions 7') + ' will show 7 mention tweets.\n'
1435 usage += s * 2 + light_green('whois @mdo') + ' will show profile of ' + \
8bc30efd 1436 magenta('@mdo') + '.\n'
c075e6dc 1437 usage += s * 2 + light_green('view @mdo') + \
8bc30efd 1438 ' will show ' + magenta('@mdo') + '\'s home.\n'
03e08f86
O
1439 usage += s * 2 + light_green('s AKB48') + ' will search for "' + \
1440 light_yellow('AKB48') + '" and return 5 newest tweet. ' + \
1441 'Search can be performed with or without hashtag.\n'
2d341029
O
1442 printNicely(usage)
1443
8bc30efd 1444
2d341029
O
1445def help_tweets():
1446 """
1447 Tweets
1448 """
1449 s = ' ' * 2
1f24a05a 1450 # Tweet
2d341029 1451 usage = '\n'
8bc30efd 1452 usage += s + grey(u'\u266A' + ' Tweets \n')
c075e6dc
O
1453 usage += s * 2 + light_green('t oops ') + \
1454 'will tweet "' + light_yellow('oops') + '" immediately.\n'
7e4ccbf3 1455 usage += s * 2 + \
c075e6dc
O
1456 light_green('rt 12 ') + ' will retweet to tweet with ' + \
1457 light_yellow('[id=12]') + '.\n'
80b70d60
O
1458 usage += s * 2 + \
1459 light_green('quote 12 ') + ' will quote the tweet with ' + \
1460 light_yellow('[id=12]') + '. If no extra text is added, ' + \
1461 'the quote will be canceled.\n'
1f24a05a 1462 usage += s * 2 + \
c075e6dc
O
1463 light_green('allrt 12 20 ') + ' will list 20 newest retweet of the tweet with ' + \
1464 light_yellow('[id=12]') + '.\n'
fd87ddac
O
1465 usage += s * 2 + light_green('conversation 12') + ' will show the chain of ' + \
1466 'replies prior to the tweet with ' + light_yellow('[id=12]') + '.\n'
c075e6dc
O
1467 usage += s * 2 + light_green('rep 12 oops') + ' will reply "' + \
1468 light_yellow('oops') + '" to tweet with ' + \
1469 light_yellow('[id=12]') + '.\n'
7e4ccbf3 1470 usage += s * 2 + \
c075e6dc
O
1471 light_green('fav 12 ') + ' will favorite the tweet with ' + \
1472 light_yellow('[id=12]') + '.\n'
7e4ccbf3 1473 usage += s * 2 + \
c075e6dc
O
1474 light_green('ufav 12 ') + ' will unfavorite tweet with ' + \
1475 light_yellow('[id=12]') + '.\n'
413857b5 1476 usage += s * 2 + \
66fe9f75 1477 light_green('share 12 ') + ' will get the direct link of the tweet with ' + \
1478 light_yellow('[id=12]') + '.\n'
8bc30efd 1479 usage += s * 2 + \
c075e6dc
O
1480 light_green('del 12 ') + ' will delete tweet with ' + \
1481 light_yellow('[id=12]') + '.\n'
1482 usage += s * 2 + light_green('show image 12') + ' will show image in tweet with ' + \
1483 light_yellow('[id=12]') + ' in your OS\'s image viewer.\n'
80b70d60
O
1484 usage += s * 2 + light_green('open 12') + ' will open url in tweet with ' + \
1485 light_yellow('[id=12]') + ' in your OS\'s default browser.\n'
2d341029 1486 printNicely(usage)
8bc30efd 1487
2d341029
O
1488
1489def help_messages():
1490 """
1491 Messages
1492 """
1493 s = ' ' * 2
5b2c4faf 1494 # Direct message
2d341029 1495 usage = '\n'
8bc30efd 1496 usage += s + grey(u'\u266A' + ' Direct messages \n')
c075e6dc
O
1497 usage += s * 2 + light_green('inbox') + ' will show inbox messages. ' + \
1498 light_green('inbox 7') + ' will show newest 7 messages.\n'
03c0d30b 1499 usage += s * 2 + light_green('thread 2') + ' will show full thread with ' + \
1500 light_yellow('[thread_id=2]') + '.\n'
c075e6dc 1501 usage += s * 2 + light_green('mes @dtvd88 hi') + ' will send a "hi" messege to ' + \
8bc30efd 1502 magenta('@dtvd88') + '.\n'
c075e6dc
O
1503 usage += s * 2 + light_green('trash 5') + ' will remove message with ' + \
1504 light_yellow('[message_id=5]') + '.\n'
2d341029 1505 printNicely(usage)
8bc30efd 1506
2d341029
O
1507
1508def help_friends_and_followers():
1509 """
1510 Friends and Followers
1511 """
1512 s = ' ' * 2
8bc30efd 1513 # Follower and following
2d341029 1514 usage = '\n'
cdccb0d6 1515 usage += s + grey(u'\u266A' + ' Friends and followers \n')
8bc30efd 1516 usage += s * 2 + \
c075e6dc 1517 light_green('ls fl') + \
8bc30efd 1518 ' will list all followers (people who are following you).\n'
1519 usage += s * 2 + \
c075e6dc 1520 light_green('ls fr') + \
8bc30efd 1521 ' will list all friends (people who you are following).\n'
c075e6dc 1522 usage += s * 2 + light_green('fl @dtvd88') + ' will follow ' + \
305ce127 1523 magenta('@dtvd88') + '.\n'
c075e6dc 1524 usage += s * 2 + light_green('ufl @dtvd88') + ' will unfollow ' + \
305ce127 1525 magenta('@dtvd88') + '.\n'
c075e6dc 1526 usage += s * 2 + light_green('mute @dtvd88') + ' will mute ' + \
5b2c4faf 1527 magenta('@dtvd88') + '.\n'
c075e6dc 1528 usage += s * 2 + light_green('unmute @dtvd88') + ' will unmute ' + \
5b2c4faf 1529 magenta('@dtvd88') + '.\n'
c075e6dc
O
1530 usage += s * 2 + light_green('muting') + ' will list muting users.\n'
1531 usage += s * 2 + light_green('block @dtvd88') + ' will block ' + \
305ce127 1532 magenta('@dtvd88') + '.\n'
c075e6dc 1533 usage += s * 2 + light_green('unblock @dtvd88') + ' will unblock ' + \
305ce127 1534 magenta('@dtvd88') + '.\n'
c075e6dc 1535 usage += s * 2 + light_green('report @dtvd88') + ' will report ' + \
305ce127 1536 magenta('@dtvd88') + ' as a spam account.\n'
2d341029
O
1537 printNicely(usage)
1538
1539
1540def help_list():
1541 """
1542 Lists
1543 """
1544 s = ' ' * 2
1545 # Twitter list
1546 usage = '\n'
1547 usage += s + grey(u'\u266A' + ' Twitter list\n')
1548 usage += s * 2 + light_green('list') + \
1549 ' will show all lists you are belong to.\n'
1550 usage += s * 2 + light_green('list home') + \
bef33491 1551 ' will show timeline of list. You will be asked for list\'s name.\n'
a65bd34c 1552 usage += s * 2 + light_green('list all_mem') + \
2d341029 1553 ' will show list\'s all members.\n'
a65bd34c 1554 usage += s * 2 + light_green('list all_sub') + \
2d341029 1555 ' will show list\'s all subscribers.\n'
422dd385
O
1556 usage += s * 2 + light_green('list add') + \
1557 ' will add specific person to a list owned by you.' + \
1558 ' You will be asked for list\'s name and person\'s name.\n'
2d341029
O
1559 usage += s * 2 + light_green('list rm') + \
1560 ' will remove specific person from a list owned by you.' + \
1561 ' You will be asked for list\'s name and person\'s name.\n'
422dd385
O
1562 usage += s * 2 + light_green('list sub') + \
1563 ' will subscribe you to a specific list.\n'
1564 usage += s * 2 + light_green('list unsub') + \
1565 ' will unsubscribe you from a specific list.\n'
1566 usage += s * 2 + light_green('list own') + \
1567 ' will show all list owned by you.\n'
1568 usage += s * 2 + light_green('list new') + \
1569 ' will create a new list.\n'
1570 usage += s * 2 + light_green('list update') + \
1571 ' will update a list owned by you.\n'
1572 usage += s * 2 + light_green('list del') + \
1573 ' will delete a list owned by you.\n'
2d341029 1574 printNicely(usage)
8bc30efd 1575
2d341029
O
1576
1577def help_stream():
1578 """
1579 Stream switch
1580 """
1581 s = ' ' * 2
8bc30efd 1582 # Switch
2d341029 1583 usage = '\n'
8bc30efd 1584 usage += s + grey(u'\u266A' + ' Switching streams \n')
c075e6dc 1585 usage += s * 2 + light_green('switch public #AKB') + \
48a25fe8 1586 ' will switch to public stream and follow "' + \
c075e6dc
O
1587 light_yellow('AKB') + '" keyword.\n'
1588 usage += s * 2 + light_green('switch mine') + \
48a25fe8 1589 ' will switch to your personal stream.\n'
c075e6dc 1590 usage += s * 2 + light_green('switch mine -f ') + \
48a25fe8 1591 ' will prompt to enter the filter.\n'
c075e6dc 1592 usage += s * 3 + light_yellow('Only nicks') + \
48a25fe8 1593 ' filter will decide nicks will be INCLUDE ONLY.\n'
c075e6dc 1594 usage += s * 3 + light_yellow('Ignore nicks') + \
48a25fe8 1595 ' filter will decide nicks will be EXCLUDE.\n'
ee4c94b1
O
1596 usage += s * 2 + light_green('switch list') + \
1597 ' will switch to a Twitter list\'s stream. You will be asked for list name\n'
2d341029
O
1598 printNicely(usage)
1599
1600
1601def help():
1602 """
1603 Help
1604 """
1605 s = ' ' * 2
1606 h, w = os.popen('stty size', 'r').read().split()
2d341029
O
1607 # Start
1608 usage = '\n'
1609 usage += s + 'Hi boss! I\'m ready to serve you right now!\n'
1610 usage += s + '-' * (int(w) - 4) + '\n'
1611 usage += s + 'You are ' + \
1612 light_yellow('already') + ' on your personal stream.\n'
1613 usage += s + 'Any update from Twitter will show up ' + \
1614 light_yellow('immediately') + '.\n'
37d1047f 1615 usage += s + 'In addition, following commands are available right now:\n'
2d341029
O
1616 # Twitter help section
1617 usage += '\n'
1618 usage += s + grey(u'\u266A' + ' Twitter help\n')
1619 usage += s * 2 + light_green('h discover') + \
1620 ' will show help for discover commands.\n'
1621 usage += s * 2 + light_green('h tweets') + \
1622 ' will show help for tweets commands.\n'
1623 usage += s * 2 + light_green('h messages') + \
1624 ' will show help for messages commands.\n'
1625 usage += s * 2 + light_green('h friends_and_followers') + \
1626 ' will show help for friends and followers commands.\n'
1627 usage += s * 2 + light_green('h list') + \
1628 ' will show help for list commands.\n'
1629 usage += s * 2 + light_green('h stream') + \
1630 ' will show help for stream commands.\n'
1f24a05a 1631 # Smart shell
1632 usage += '\n'
1633 usage += s + grey(u'\u266A' + ' Smart shell\n')
c075e6dc 1634 usage += s * 2 + light_green('111111 * 9 / 7') + ' or any math expression ' + \
1f24a05a 1635 'will be evaluate by Python interpreter.\n'
c075e6dc 1636 usage += s * 2 + 'Even ' + light_green('cal') + ' will show the calendar' + \
1f24a05a 1637 ' for current month.\n'
29fd0be6 1638 # Config
1f24a05a 1639 usage += '\n'
29fd0be6
O
1640 usage += s + grey(u'\u266A' + ' Config \n')
1641 usage += s * 2 + light_green('theme') + ' will list available theme. ' + \
c075e6dc 1642 light_green('theme monokai') + ' will apply ' + light_yellow('monokai') + \
632c6fa5 1643 ' theme immediately.\n'
29fd0be6
O
1644 usage += s * 2 + light_green('config') + ' will list all config.\n'
1645 usage += s * 3 + \
1646 light_green('config ASCII_ART') + ' will output current value of ' +\
a8c5fce4 1647 light_yellow('ASCII_ART') + ' config key.\n'
29fd0be6 1648 usage += s * 3 + \
fe9bb33b 1649 light_green('config TREND_MAX default') + ' will output default value of ' + \
1650 light_yellow('TREND_MAX') + ' config key.\n'
1651 usage += s * 3 + \
1652 light_green('config CUSTOM_CONFIG drop') + ' will drop ' + \
1653 light_yellow('CUSTOM_CONFIG') + ' config key.\n'
29fd0be6 1654 usage += s * 3 + \
fe9bb33b 1655 light_green('config IMAGE_ON_TERM = true') + ' will set value of ' + \
1656 light_yellow('IMAGE_ON_TERM') + ' config key to ' + \
1657 light_yellow('True') + '.\n'
29fd0be6
O
1658 # Screening
1659 usage += '\n'
1660 usage += s + grey(u'\u266A' + ' Screening \n')
c075e6dc 1661 usage += s * 2 + light_green('h') + ' will show this help again.\n'
d6cc4c67
O
1662 usage += s * 2 + light_green('p') + ' will pause the stream.\n'
1663 usage += s * 2 + light_green('r') + ' will unpause the stream.\n'
c075e6dc
O
1664 usage += s * 2 + light_green('c') + ' will clear the screen.\n'
1665 usage += s * 2 + light_green('q') + ' will quit.\n'
8bc30efd 1666 # End
1667 usage += '\n'
7e4ccbf3 1668 usage += s + '-' * (int(w) - 4) + '\n'
8bc30efd 1669 usage += s + 'Have fun and hang tight! \n'
2d341029
O
1670 # Show help
1671 d = {
422dd385
O
1672 'discover': help_discover,
1673 'tweets': help_tweets,
1674 'messages': help_messages,
1675 'friends_and_followers': help_friends_and_followers,
1676 'list': help_list,
1677 'stream': help_stream,
2d341029
O
1678 }
1679 if g['stuff']:
baec5f50 1680 d.get(
1681 g['stuff'].strip(),
1682 lambda: printNicely(red('No such command.'))
3d48702f 1683 )()
2d341029
O
1684 else:
1685 printNicely(usage)
f405a7d0
O
1686
1687
d6cc4c67
O
1688def pause():
1689 """
1690 Pause stream display
1691 """
4dc385b5 1692 g['pause'] = True
d6cc4c67
O
1693 printNicely(green('Stream is paused'))
1694
1695
1696def replay():
1697 """
1698 Replay stream
1699 """
4dc385b5 1700 g['pause'] = False
d6cc4c67
O
1701 printNicely(green('Stream is running back now'))
1702
1703
843647ad 1704def clear():
f405a7d0 1705 """
7b674cef 1706 Clear screen
f405a7d0 1707 """
843647ad 1708 os.system('clear')
f405a7d0
O
1709
1710
843647ad 1711def quit():
b8dda704
O
1712 """
1713 Exit all
1714 """
4c025026 1715 try:
1716 save_history()
4c025026 1717 printNicely(green('See you next time :)'))
1718 except:
1719 pass
843647ad 1720 sys.exit()
b8dda704
O
1721
1722
94a5f62e 1723def reset():
f405a7d0 1724 """
94a5f62e 1725 Reset prefix of line
f405a7d0 1726 """
c91f75f2 1727 if g['reset']:
a8e71259 1728 if c.get('USER_JSON_ERROR'):
1729 printNicely(red('Your ~/.rainbow_config.json is messed up:'))
1730 printNicely(red('>>> ' + c['USER_JSON_ERROR']))
1731 printNicely('')
e3885f55 1732 printNicely(magenta('Need tips ? Type "h" and hit Enter key!'))
c91f75f2 1733 g['reset'] = False
d0a726d6 1734 try:
779b0640 1735 printNicely(str(eval(g['cmd'])))
2a0cabee 1736 except Exception:
d0a726d6 1737 pass
54277114
O
1738
1739
f1c1dfea
O
1740# Command set
1741cmdset = [
1742 'switch',
1743 'trend',
1744 'home',
99cd1fba 1745 'notification',
f1c1dfea
O
1746 'view',
1747 'mentions',
1748 't',
1749 'rt',
1750 'quote',
1751 'allrt',
fd87ddac 1752 'conversation',
f1c1dfea
O
1753 'fav',
1754 'rep',
1755 'del',
1756 'ufav',
413857b5 1757 'share',
f1c1dfea
O
1758 's',
1759 'mes',
1760 'show',
1761 'open',
1762 'ls',
1763 'inbox',
67c663f8 1764 'thread',
f1c1dfea
O
1765 'trash',
1766 'whois',
1767 'fl',
1768 'ufl',
1769 'mute',
1770 'unmute',
1771 'muting',
1772 'block',
1773 'unblock',
1774 'report',
1775 'list',
1776 'cal',
1777 'config',
1778 'theme',
1779 'h',
1780 'p',
1781 'r',
1782 'c',
bf766c7b
LP
1783 'q',
1784 'version',
f1c1dfea
O
1785]
1786
1787# Handle function set
1788funcset = [
1789 switch,
1790 trend,
1791 home,
99cd1fba 1792 notification,
f1c1dfea
O
1793 view,
1794 mentions,
1795 tweet,
1796 retweet,
1797 quote,
1798 allretweet,
fd87ddac 1799 conversation,
f1c1dfea
O
1800 favorite,
1801 reply,
1802 delete,
1803 unfavorite,
413857b5 1804 share,
f1c1dfea
O
1805 search,
1806 message,
1807 show,
1808 urlopen,
1809 ls,
1810 inbox,
67c663f8 1811 thread,
f1c1dfea
O
1812 trash,
1813 whois,
1814 follow,
1815 unfollow,
1816 mute,
1817 unmute,
1818 muting,
1819 block,
1820 unblock,
1821 report,
1822 twitterlist,
1823 cal,
1824 config,
1825 theme,
1826 help,
1827 pause,
1828 replay,
1829 clear,
bf766c7b
LP
1830 quit,
1831 upgrade_center,
f1c1dfea
O
1832]
1833
1834
94a5f62e 1835def process(cmd):
54277114 1836 """
94a5f62e 1837 Process switch
54277114 1838 """
f1c1dfea 1839 return dict(zip(cmdset, funcset)).get(cmd, reset)
94a5f62e 1840
1841
1842def listen():
42fde775 1843 """
1844 Listen to user's input
1845 """
d51b4107
O
1846 d = dict(zip(
1847 cmdset,
1848 [
ee4c94b1 1849 ['public', 'mine', 'list'], # switch
4592d231 1850 [], # trend
7e4ccbf3 1851 [], # home
99cd1fba 1852 [], # notification
7e4ccbf3 1853 ['@'], # view
305ce127 1854 [], # mentions
7e4ccbf3 1855 [], # tweet
1856 [], # retweet
80b70d60 1857 [], # quote
1f24a05a 1858 [], # allretweet
fd87ddac 1859 [], # conversation
f5677fb1 1860 [], # favorite
7e4ccbf3 1861 [], # reply
1862 [], # delete
f5677fb1 1863 [], # unfavorite
413857b5 1864 [], # url
7e4ccbf3 1865 ['#'], # search
305ce127 1866 ['@'], # message
f5677fb1 1867 ['image'], # show image
80b70d60 1868 [''], # open url
305ce127 1869 ['fl', 'fr'], # list
1870 [], # inbox
03c0d30b 1871 [i for i in g['message_threads']], # sent
305ce127 1872 [], # trash
e2b81717 1873 ['@'], # whois
affcb149
O
1874 ['@'], # follow
1875 ['@'], # unfollow
5b2c4faf 1876 ['@'], # mute
1877 ['@'], # unmute
1878 ['@'], # muting
305ce127 1879 ['@'], # block
1880 ['@'], # unblock
1881 ['@'], # report
422dd385
O
1882 [
1883 'home',
1884 'all_mem',
1885 'all_sub',
1886 'add',
1887 'rm',
1888 'sub',
1889 'unsub',
1890 'own',
1891 'new',
1892 'update',
1893 'del'
1894 ], # list
813a5d80 1895 [], # cal
a8c5fce4 1896 [key for key in dict(get_all_config())], # config
ceec8593 1897 g['themes'], # theme
422dd385
O
1898 [
1899 'discover',
1900 'tweets',
1901 'messages',
1902 'friends_and_followers',
1903 'list',
1904 'stream'
1905 ], # help
d6cc4c67
O
1906 [], # pause
1907 [], # reconnect
7e4ccbf3 1908 [], # clear
1909 [], # quit
d51b4107 1910 ]
7e4ccbf3 1911 ))
d51b4107 1912 init_interactive_shell(d)
f5677fb1 1913 read_history()
819569e8 1914 reset()
b2b933a9 1915 while True:
b8c1f42a 1916 try:
39b8e6b3
O
1917 # raw_input
1918 if g['prefix']:
aa452ee9 1919 # Only use PREFIX as a string with raw_input
c285decf 1920 line = raw_input(g['decorated_name'](g['PREFIX']))
39b8e6b3
O
1921 else:
1922 line = raw_input()
1923 # Save cmd to compare with readline buffer
1924 g['cmd'] = line.strip()
1925 # Get short cmd to pass to handle function
1926 try:
1927 cmd = line.split()[0]
1928 except:
1929 cmd = ''
9683e61d 1930 # Lock the semaphore
99b52f5f 1931 c['lock'] = True
9683e61d 1932 # Save cmd to global variable and call process
b8c1f42a 1933 g['stuff'] = ' '.join(line.split()[1:])
9683e61d 1934 # Process the command
b8c1f42a 1935 process(cmd)()
9683e61d 1936 # Not re-display
99b52f5f 1937 if cmd in ['switch', 't', 'rt', 'rep']:
9683e61d
O
1938 g['prefix'] = False
1939 else:
1940 g['prefix'] = True
1941 # Release the semaphore lock
99b52f5f 1942 c['lock'] = False
39b8e6b3
O
1943 except EOFError:
1944 printNicely('')
eadd85a8 1945 except Exception:
7a8a52fc 1946 debug_option()
b8c1f42a 1947 printNicely(red('OMG something is wrong with Twitter right now.'))
ee444288 1948
54277114 1949
47cee703
O
1950def reconn_notice():
1951 """
1952 Notice when Hangup or Timeout
1953 """
1954 guide = light_magenta("You can use ") + \
1955 light_green("switch") + \
1956 light_magenta(" command to return to your stream.\n")
1957 guide += light_magenta("Type ") + \
1958 light_green("h stream") + \
1959 light_magenta(" for more details.")
1960 printNicely(guide)
1961 sys.stdout.write(g['decorated_name'](c['PREFIX']))
1962 sys.stdout.flush()
1963
1964
42fde775 1965def stream(domain, args, name='Rainbow Stream'):
54277114 1966 """
f405a7d0 1967 Track the stream
54277114 1968 """
54277114 1969 # The Logo
42fde775 1970 art_dict = {
632c6fa5
O
1971 c['USER_DOMAIN']: name,
1972 c['PUBLIC_DOMAIN']: args.track_keywords,
1f2f6159 1973 c['SITE_DOMAIN']: name,
42fde775 1974 }
687567eb 1975 if c['ASCII_ART']:
c075e6dc 1976 ascii_art(art_dict[domain])
91476ec3
O
1977 # These arguments are optional:
1978 stream_args = dict(
e3927852 1979 timeout=0.5, # To check g['stream_stop'] after each 0.5 s
cb45dc23 1980 block=True,
1981 heartbeat_timeout=c['HEARTBEAT_TIMEOUT'] * 60)
91476ec3
O
1982 # Track keyword
1983 query_args = dict()
1984 if args.track_keywords:
1985 query_args['track'] = args.track_keywords
91476ec3 1986 # Get stream
2a6238f5 1987 stream = TwitterStream(
22be990e 1988 auth=authen(),
42fde775 1989 domain=domain,
2a6238f5 1990 **stream_args)
2a0cabee
O
1991 try:
1992 if domain == c['USER_DOMAIN']:
1993 tweet_iter = stream.user(**query_args)
1994 elif domain == c['SITE_DOMAIN']:
1995 tweet_iter = stream.site(**query_args)
42fde775 1996 else:
2a0cabee
O
1997 if args.track_keywords:
1998 tweet_iter = stream.statuses.filter(**query_args)
1999 else:
2000 tweet_iter = stream.statuses.sample()
92983945
BS
2001 # Block new stream until other one exits
2002 StreamLock.acquire()
2003 g['stream_stop'] = False
e53e2c70 2004 last_tweet_time = time.time()
72c02928
VNM
2005 for tweet in tweet_iter:
2006 if tweet is None:
a1222228 2007 printNicely("-- None --")
72c02928 2008 elif tweet is Timeout:
47cee703
O
2009 # Because the stream check for each 0.3s
2010 # so we shouldn't output anything here
335e7803
O
2011 if(g['stream_stop']):
2012 StreamLock.release()
2013 break
72c02928
VNM
2014 elif tweet is HeartbeatTimeout:
2015 printNicely("-- Heartbeat Timeout --")
47cee703 2016 reconn_notice()
8715dda0
O
2017 StreamLock.release()
2018 break
72c02928
VNM
2019 elif tweet is Hangup:
2020 printNicely("-- Hangup --")
47cee703
O
2021 reconn_notice()
2022 StreamLock.release()
2023 break
72c02928 2024 elif tweet.get('text'):
84b41f58
O
2025 # Slow down the stream by STREAM_DELAY config key
2026 if time.time() - last_tweet_time < c['STREAM_DELAY']:
2027 continue
2028 last_tweet_time = time.time()
2029 # Check the semaphore pause and lock (stream process only)
2030 if g['pause']:
2031 continue
2032 while c['lock']:
2033 time.sleep(0.5)
2034 # Draw the tweet
2035 draw(
2036 t=tweet,
2037 keyword=args.track_keywords,
2038 humanize=False,
2039 fil=args.filter,
2040 ig=args.ignore,
2041 )
2042 # Current readline buffer
2043 current_buffer = readline.get_line_buffer().strip()
2044 # There is an unexpected behaviour in MacOSX readline + Python 2:
2045 # after completely delete a word after typing it,
2046 # somehow readline buffer still contains
2047 # the 1st character of that word
2048 if current_buffer and g['cmd'] != current_buffer:
2049 sys.stdout.write(
2050 g['decorated_name'](c['PREFIX']) + str2u(current_buffer))
2051 sys.stdout.flush()
2052 elif not c['HIDE_PROMPT']:
2053 sys.stdout.write(g['decorated_name'](c['PREFIX']))
2054 sys.stdout.flush()
14db58c7 2055 elif tweet.get('direct_message'):
4dc385b5
O
2056 # Check the semaphore pause and lock (stream process only)
2057 if g['pause']:
2058 continue
2059 while c['lock']:
2060 time.sleep(0.5)
2061 print_message(tweet['direct_message'])
99cd1fba 2062 elif tweet.get('event'):
d7d9c67c 2063 c['events'].append(tweet)
99cd1fba 2064 print_event(tweet)
2a0cabee
O
2065 except TwitterHTTPError:
2066 printNicely('')
c075e6dc 2067 printNicely(
2a0cabee 2068 magenta("We have maximum connection problem with twitter'stream API right now :("))
54277114
O
2069
2070
2071def fly():
2072 """
2073 Main function
2074 """
531f5682 2075 # Initial
42fde775 2076 args = parse_arguments()
2a0cabee 2077 try:
a65129d4 2078 proxy_connect(args)
fe9bb33b 2079 init(args)
a65129d4 2080 # Twitter API connection problem
2a0cabee
O
2081 except TwitterHTTPError:
2082 printNicely('')
2083 printNicely(
e3927852 2084 magenta("We have connection problem with twitter'stream API right now :("))
4c025026 2085 printNicely(magenta("Let's try again later."))
2a0cabee 2086 save_history()
2a0cabee 2087 sys.exit()
a65129d4
O
2088 # Proxy connection problem
2089 except (socks.ProxyConnectionError, URLError):
c426a344 2090 printNicely(
2091 magenta("There seems to be a connection problem."))
2092 printNicely(
2093 magenta("You might want to check your proxy settings (host, port and type)!"))
2094 save_history()
2095 sys.exit()
2096
92983945 2097 # Spawn stream thread
baec5f50 2098 th = threading.Thread(
2099 target=stream,
2100 args=(
2101 c['USER_DOMAIN'],
2102 args,
2103 g['original_name']))
92983945
BS
2104 th.daemon = True
2105 th.start()
42fde775 2106 # Start listen process
819569e8 2107 time.sleep(0.5)
c91f75f2 2108 g['reset'] = True
1dd312f5 2109 g['prefix'] = True
0f6e4daf 2110 listen()