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