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