add show profile
[rainbowstream.git] / rainbowstream / rainbow.py
CommitLineData
91476ec3
O
1"""
2Colorful user's timeline stream
3"""
78b81730
O
4from multiprocessing import Process
5from dateutil import parser
6
b2b933a9 7import os
8import os.path
9import sys
10import signal
11import argparse
12import time
13import datetime
991c30af 14import requests
91476ec3 15
91476ec3 16from twitter.stream import TwitterStream, Timeout, HeartbeatTimeout, Hangup
54277114 17from twitter.api import *
91476ec3 18from twitter.oauth import OAuth, read_token_file
8c840a83 19from twitter.oauth_dance import oauth_dance
91476ec3 20from twitter.util import printNicely
991c30af 21from StringIO import StringIO
91476ec3 22
2a6238f5
O
23from .colors import *
24from .config import *
777c52d4 25from .consumer import *
94a5f62e 26from .interactive import *
18cab06a 27from .db import *
991c30af 28from .c_image import *
2a6238f5 29
f405a7d0 30g = {}
18cab06a 31db = RainbowDB()
94a5f62e 32cmdset = [
42fde775 33 'switch',
94a5f62e 34 'home',
35 'view',
305ce127 36 'mentions',
94a5f62e 37 't',
38 'rt',
7e4ccbf3 39 'fav',
94a5f62e 40 'rep',
41 'del',
7e4ccbf3 42 'ufav',
94a5f62e 43 's',
305ce127 44 'mes',
f5677fb1 45 'show',
0f6e4daf 46 'ls',
305ce127 47 'inbox',
48 'sent',
49 'trash',
e2b81717 50 'whois',
94a5f62e 51 'fl',
f5677fb1 52 'ufl',
305ce127 53 'block',
54 'unblock',
55 'report',
94a5f62e 56 'h',
57 'c',
58 'q'
59]
22be990e 60
b2b933a9 61
c1fa7c94 62def draw(t, iot=False, keyword=None, fil=[], ig=[]):
91476ec3
O
63 """
64 Draw the rainbow
65 """
d51b4107 66
91476ec3 67 # Retrieve tweet
829cc2d8 68 tid = t['id']
91476ec3
O
69 text = t['text']
70 screen_name = t['user']['screen_name']
71 name = t['user']['name']
72 created_at = t['created_at']
7e4ccbf3 73 favorited = t['favorited']
91476ec3 74 date = parser.parse(created_at)
e20af1c3 75 date = date - datetime.timedelta(seconds=time.timezone)
76 clock = date.strftime('%Y/%m/%d %H:%M:%S')
91476ec3 77
991c30af
O
78 # Get expanded url
79 try:
80 expanded_url = []
81 url = []
82 urls = t['entities']['urls']
83 for u in urls:
84 expanded_url.append(u['expanded_url'])
85 url.append(u['url'])
86 except:
87 expanded_url = None
88 url = None
89
90 # Get media
91 try:
92 media_url = []
93 media = t['entities']['media']
94 for m in media:
f5677fb1 95 media_url.append(m['media_url'])
991c30af
O
96 except:
97 media_url = None
98
d51b4107
O
99 # Filter and ignore
100 screen_name = '@' + screen_name
101 if fil and screen_name not in fil:
102 return
103 if ig and screen_name in ig:
104 return
105
305ce127 106 # Get rainbow id
107 res = db.tweet_to_rainbow_query(tid)
18cab06a 108 if not res:
305ce127 109 db.tweet_store(tid)
110 res = db.tweet_to_rainbow_query(tid)
18cab06a
O
111 rid = res[0].rainbow_id
112
91476ec3 113 # Format info
d51b4107 114 user = cycle_color(name) + grey(' ' + screen_name + ' ')
7e4ccbf3 115 meta = grey('[' + clock + '] [id=' + str(rid) + '] ')
116 if favorited:
117 meta = meta + green(u'\u2605')
8c840a83 118 tweet = text.split()
991c30af
O
119 # Replace url
120 if expanded_url:
121 for index in range(len(expanded_url)):
122 tweet = map(
123 lambda x: expanded_url[index] if x == url[index] else x,
124 tweet)
b8dda704 125 # Highlight RT
2a6238f5 126 tweet = map(lambda x: grey(x) if x == 'RT' else x, tweet)
b8dda704 127 # Highlight screen_name
2a6238f5 128 tweet = map(lambda x: cycle_color(x) if x[0] == '@' else x, tweet)
b8dda704 129 # Highlight link
2a6238f5 130 tweet = map(lambda x: cyan(x) if x[0:7] == 'http://' else x, tweet)
b8dda704 131 # Highlight search keyword
7a431249 132 if keyword:
22be990e 133 tweet = map(
134 lambda x: on_yellow(x) if
135 ''.join(c for c in x if c.isalnum()).lower() == keyword.lower()
136 else x,
137 tweet
138 )
991c30af 139 # Recreate tweet
8c840a83 140 tweet = ' '.join(tweet)
91476ec3
O
141
142 # Draw rainbow
06773ffe 143 line1 = u"{u:>{uw}}:".format(
2a6238f5
O
144 u=user,
145 uw=len(user) + 2,
91476ec3 146 )
06773ffe 147 line2 = u"{c:>{cw}}".format(
829cc2d8
O
148 c=meta,
149 cw=len(meta) + 2,
06773ffe
O
150 )
151 line3 = ' ' + tweet
91476ec3 152
94a5f62e 153 printNicely('')
f405a7d0
O
154 printNicely(line1)
155 printNicely(line2)
156 printNicely(line3)
91476ec3 157
991c30af 158 # Display Image
c1fa7c94 159 if iot and media_url:
f5677fb1
O
160 for mu in media_url:
161 response = requests.get(mu)
162 image_to_display(StringIO(response.content))
991c30af 163
91476ec3 164
305ce127 165def print_message(m):
166 """
167 Print direct message
168 """
e2b81717
O
169 sender_screen_name = '@' + m['sender_screen_name']
170 sender_name = m['sender']['name']
305ce127 171 text = m['text']
e2b81717
O
172 recipient_screen_name = '@' + m['recipient_screen_name']
173 recipient_name = m['recipient']['name']
305ce127 174 mid = m['id']
175 date = parser.parse(m['created_at'])
176 date = date - datetime.timedelta(seconds=time.timezone)
177 clock = date.strftime('%Y/%m/%d %H:%M:%S')
178
179 # Get rainbow id
180 res = db.message_to_rainbow_query(mid)
181 if not res:
182 db.message_store(mid)
183 res = db.message_to_rainbow_query(mid)
184 rid = res[0].rainbow_id
185
e2b81717
O
186 sender = cycle_color(sender_name) + grey(' ' + sender_screen_name + ' ')
187 recipient = cycle_color(recipient_name) + grey(' ' + recipient_screen_name + ' ')
188 user = sender + magenta(' >>> ') + recipient
305ce127 189 meta = grey('[' + clock + '] [message_id=' + str(rid) + '] ')
190 text = ''.join(map(lambda x: x+' ' if x=='\n' else x,text))
191
192 line1 = u"{u:>{uw}}:".format(
193 u=user,
194 uw=len(user) + 2,
195 )
196 line2 = u"{c:>{cw}}".format(
197 c=meta,
198 cw=len(meta) + 2,
199 )
e2b81717 200
305ce127 201 line3 = ' ' + text
202
203 printNicely('')
204 printNicely(line1)
205 printNicely(line2)
206 printNicely(line3)
e2b81717
O
207
208
209def show_profile(u):
210 """
211 Show a profile
212 """
213 # Retrieve info
214 name = u['name']
215 screen_name = u['screen_name']
216 description = u['description']
217 profile_image_url = u['profile_image_url']
218 location = u['location']
219 url = u['url']
220 created_at = u['created_at']
221 statuses_count = u['statuses_count']
222 friends_count = u['friends_count']
223 followers_count = u['followers_count']
224 # Create content
225 statuses_count = green(str(statuses_count) + ' tweets')
226 friends_count = green(str(friends_count) + ' following')
227 followers_count = green(str(followers_count) + ' followers')
228 count = statuses_count + ' ' + friends_count + ' ' + followers_count
229 user = cycle_color(name) + grey(' ' + screen_name + ' : ') + count
230 profile_image_url = 'Profile photo: ' + cyan(profile_image_url)
231 description = ''.join(map(lambda x: x+' '*4 if x=='\n' else x,description))
232 description = yellow(description)
233 location = 'Location : ' + magenta(location)
234 url = 'URL : ' + (cyan(url) if url else '')
235 created_at = 'Join at ' + white(created_at)
236 # Format
237 line1 = u"{u:>{uw}}".format(
238 u=user,
239 uw=len(user) + 2,
240 )
241 line2 = u"{p:>{pw}}".format(
242 p=profile_image_url,
243 pw=len(profile_image_url) + 4,
244 )
245 line3 = u"{d:>{dw}}".format(
246 d=description,
247 dw=len(description) + 4,
248 )
249 line4 = u"{l:>{lw}}".format(
250 l=location,
251 lw=len(location) + 4,
252 )
253 line5 = u"{u:>{uw}}".format(
254 u=url,
255 uw=len(url) + 4,
256 )
257 line6 = u"{j:>{jw}}".format(
258 j=created_at,
259 jw=len(created_at) + 4,
260 )
261 # Display
262 printNicely('')
263 for line in [line1,line2,line3,line4,line5,line6]:
264 printNicely(line)
265 printNicely('')
266
305ce127 267
91476ec3
O
268def parse_arguments():
269 """
270 Parse the arguments
271 """
91476ec3 272 parser = argparse.ArgumentParser(description=__doc__ or "")
2a6238f5
O
273 parser.add_argument(
274 '-to',
275 '--timeout',
276 help='Timeout for the stream (seconds).')
277 parser.add_argument(
278 '-ht',
279 '--heartbeat-timeout',
280 help='Set heartbeat timeout.',
281 default=90)
282 parser.add_argument(
283 '-nb',
284 '--no-block',
285 action='store_true',
286 help='Set stream to non-blocking.')
287 parser.add_argument(
288 '-tt',
289 '--track-keywords',
290 help='Search the stream for specific text.')
d51b4107
O
291 parser.add_argument(
292 '-fil',
293 '--filter',
294 help='Filter specific screen_name.')
295 parser.add_argument(
296 '-ig',
297 '--ignore',
298 help='Ignore specific screen_name.')
88af38d8 299 parser.add_argument(
c1fa7c94
O
300 '-iot',
301 '--image-on-term',
302 action='store_true',
303 help='Display all image on terminal.')
91476ec3
O
304 return parser.parse_args()
305
306
54277114
O
307def authen():
308 """
7b674cef 309 Authenticate with Twitter OAuth
54277114 310 """
8c840a83 311 # When using rainbow stream you must authorize.
2a6238f5
O
312 twitter_credential = os.environ.get(
313 'HOME',
314 os.environ.get(
315 'USERPROFILE',
316 '')) + os.sep + '.rainbow_oauth'
8c840a83
O
317 if not os.path.exists(twitter_credential):
318 oauth_dance("Rainbow Stream",
319 CONSUMER_KEY,
320 CONSUMER_SECRET,
321 twitter_credential)
322 oauth_token, oauth_token_secret = read_token_file(twitter_credential)
54277114 323 return OAuth(
2a6238f5
O
324 oauth_token,
325 oauth_token_secret,
326 CONSUMER_KEY,
327 CONSUMER_SECRET)
91476ec3 328
54277114
O
329
330def get_decorated_name():
331 """
332 Beginning of every line
333 """
334 t = Twitter(auth=authen())
c5ff542b 335 name = '@' + t.account.verify_credentials()['screen_name']
42fde775 336 g['original_name'] = name[1:]
f405a7d0 337 g['decorated_name'] = grey('[') + grey(name) + grey(']: ')
54277114 338
f405a7d0 339
42fde775 340def switch():
341 """
342 Switch stream
343 """
344 try:
345 target = g['stuff'].split()[0]
346
d51b4107
O
347 # Filter and ignore
348 args = parse_arguments()
7e4ccbf3 349 try:
d51b4107
O
350 if g['stuff'].split()[-1] == '-f':
351 only = raw_input('Only nicks: ')
352 ignore = raw_input('Ignore nicks: ')
7e4ccbf3 353 args.filter = filter(None, only.split(','))
354 args.ignore = filter(None, ignore.split(','))
d51b4107
O
355 elif g['stuff'].split()[-1] == '-d':
356 args.filter = ONLY_LIST
357 args.ignore = IGNORE_LIST
358 except:
359 printNicely(red('Sorry, wrong format.'))
360 return
361
42fde775 362 # Public stream
363 if target == 'public':
364 keyword = g['stuff'].split()[1]
365 if keyword[0] == '#':
366 keyword = keyword[1:]
42fde775 367 # Kill old process
368 os.kill(g['stream_pid'], signal.SIGKILL)
42fde775 369 args.track_keywords = keyword
42fde775 370 # Start new process
371 p = Process(
d51b4107 372 target=stream,
42fde775 373 args=(
d51b4107 374 PUBLIC_DOMAIN,
42fde775 375 args))
376 p.start()
377 g['stream_pid'] = p.pid
378
379 # Personal stream
380 elif target == 'mine':
42fde775 381 # Kill old process
382 os.kill(g['stream_pid'], signal.SIGKILL)
42fde775 383 # Start new process
384 p = Process(
385 target=stream,
386 args=(
387 USER_DOMAIN,
388 args,
389 g['original_name']))
390 p.start()
391 g['stream_pid'] = p.pid
d51b4107 392 printNicely('')
1551a7d3 393 printNicely(green('Stream switched.'))
d51b4107
O
394 if args.filter:
395 printNicely(cyan('Only: ' + str(args.filter)))
396 if args.ignore:
397 printNicely(red('Ignore: ' + str(args.ignore)))
398 printNicely('')
42fde775 399 except:
400 printNicely(red('Sorry I can\'t understand.'))
42fde775 401
402
7b674cef 403def home():
404 """
405 Home
406 """
407 t = Twitter(auth=authen())
94a5f62e 408 num = HOME_TWEET_NUM
7b674cef 409 if g['stuff'].isdigit():
305ce127 410 num = int(g['stuff'])
94a5f62e 411 for tweet in reversed(t.statuses.home_timeline(count=num)):
c1fa7c94 412 draw(t=tweet, iot=g['iot'])
94a5f62e 413 printNicely('')
7b674cef 414
415
416def view():
417 """
418 Friend view
419 """
420 t = Twitter(auth=authen())
421 user = g['stuff'].split()[0]
b8fbcb70 422 if user[0] == '@':
423 try:
94a5f62e 424 num = int(g['stuff'].split()[1])
b8fbcb70 425 except:
94a5f62e 426 num = HOME_TWEET_NUM
427 for tweet in reversed(t.statuses.user_timeline(count=num, screen_name=user[1:])):
c1fa7c94 428 draw(t=tweet, iot=g['iot'])
94a5f62e 429 printNicely('')
b8fbcb70 430 else:
c91f75f2 431 printNicely(red('A name should begin with a \'@\''))
7b674cef 432
433
305ce127 434def mentions():
435 """
436 Mentions timeline
437 """
438 t = Twitter(auth=authen())
439 num = HOME_TWEET_NUM
440 if g['stuff'].isdigit():
441 num = int(g['stuff'])
442 for tweet in reversed(t.statuses.mentions_timeline(count=num)):
443 draw(t=tweet, iot=g['iot'])
444 printNicely('')
445
446
f405a7d0 447def tweet():
54277114 448 """
7b674cef 449 Tweet
54277114
O
450 """
451 t = Twitter(auth=authen())
f405a7d0 452 t.statuses.update(status=g['stuff'])
f405a7d0 453
b2b933a9 454
1ba4abfd
O
455def retweet():
456 """
457 ReTweet
458 """
459 t = Twitter(auth=authen())
460 try:
461 id = int(g['stuff'].split()[0])
305ce127 462 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
b2b933a9 463 t.statuses.retweet(id=tid, include_entities=False, trim_user=True)
1ba4abfd 464 except:
c91f75f2 465 printNicely(red('Sorry I can\'t retweet for you.'))
1ba4abfd
O
466
467
7e4ccbf3 468def favorite():
469 """
470 Favorite
471 """
472 t = Twitter(auth=authen())
473 try:
474 id = int(g['stuff'].split()[0])
305ce127 475 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
7e4ccbf3 476 t.favorites.create(_id=tid, include_entities=False)
477 printNicely(green('Favorited.'))
c1fa7c94 478 draw(t.statuses.show(id=tid), iot=g['iot'])
7e4ccbf3 479 except:
480 printNicely(red('Omg some syntax is wrong.'))
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])
305ce127 490 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
18cab06a 491 user = t.statuses.show(id=tid)['user']['screen_name']
7b674cef 492 status = ' '.join(g['stuff'].split()[1:])
493 status = '@' + user + ' ' + status.decode('utf-8')
18cab06a 494 t.statuses.update(status=status, in_reply_to_status_id=tid)
7b674cef 495 except:
c91f75f2 496 printNicely(red('Sorry I can\'t understand.'))
7b674cef 497
498
499def delete():
500 """
501 Delete
502 """
503 t = Twitter(auth=authen())
504 try:
305ce127 505 rid = int(g['stuff'].split()[0])
506 tid = db.rainbow_to_tweet_query(rid)[0].tweet_id
18cab06a 507 t.statuses.destroy(id=tid)
c91f75f2 508 printNicely(green('Okay it\'s gone.'))
7b674cef 509 except:
305ce127 510 printNicely(red('Sorry I can\'t understand.'))
829cc2d8
O
511
512
7e4ccbf3 513def unfavorite():
514 """
515 Unfavorite
516 """
517 t = Twitter(auth=authen())
518 try:
519 id = int(g['stuff'].split()[0])
305ce127 520 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
7e4ccbf3 521 t.favorites.destroy(_id=tid)
522 printNicely(green('Okay it\'s unfavorited.'))
c1fa7c94 523 draw(t.statuses.show(id=tid), iot=g['iot'])
7e4ccbf3 524 except:
525 printNicely(red('Sorry I can\'t unfavorite this tweet for you.'))
526
527
f405a7d0
O
528def search():
529 """
7b674cef 530 Search
f405a7d0
O
531 """
532 t = Twitter(auth=authen())
94a5f62e 533 try:
534 if g['stuff'][0] == '#':
535 rel = t.search.tweets(q=g['stuff'])['statuses']
c91f75f2 536 if len(rel):
537 printNicely('Newest tweets:')
538 for i in reversed(xrange(SEARCH_MAX_RECORD)):
88af38d8 539 draw(t=rel[i],
0f6e4daf 540 iot=g['iot'],
541 keyword=g['stuff'].strip()[1:])
c91f75f2 542 printNicely('')
543 else:
544 printNicely(magenta('I\'m afraid there is no result'))
94a5f62e 545 else:
c91f75f2 546 printNicely(red('A keyword should be a hashtag (like \'#AKB48\')'))
94a5f62e 547 except:
c91f75f2 548 printNicely(red('Sorry I can\'t understand.'))
b2b933a9 549
f405a7d0 550
305ce127 551def message():
552 """
553 Send a direct message
554 """
555 t = Twitter(auth=authen())
556 user = g['stuff'].split()[0]
557 if user[0] == '@':
558 try:
559 content = g['stuff'].split()[1]
560 t.direct_messages.new(
561 screen_name=user[1:],
562 text=content
563 )
564 printNicely(green('Message sent.'))
565 except:
566 printNicely(red('Sorry I can\'t understand.'))
567 else:
568 printNicely(red('A name should begin with a \'@\''))
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])
305ce127 581 tid = db.rainbow_to_tweet_query(id)[0].tweet_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'])
586 img = Image.open(StringIO(res.content))
587 img.show()
588 except:
589 printNicely(red('Sorry I can\'t show this image.'))
843647ad
O
590
591
0f6e4daf 592def list():
593 """
594 List friends for followers
595 """
596 t = Twitter(auth=authen())
e2b81717
O
597 # Get name
598 try:
599 name = g['stuff'].split()[1]
600 if name[0] == '@':
601 name = name[1:]
602 else:
603 printNicely(red('A name should begin with a \'@\''))
604 raise Exception('Invalid name')
605 except:
606 name = g['original_name']
607 # Get list followers or friends
0f6e4daf 608 try:
609 target = g['stuff'].split()[0]
610 d = {'fl': 'followers', 'fr': 'friends'}
611 next_cursor = -1
612 rel = {}
613 # Cursor loop
614 while next_cursor != 0:
305ce127 615 list = getattr(t, d[target]).list(
e2b81717 616 screen_name=name,
305ce127 617 cursor=next_cursor,
618 skip_status=True,
619 include_entities=False,
620 )
0f6e4daf 621 for u in list['users']:
622 rel[u['name']] = '@' + u['screen_name']
623 next_cursor = list['next_cursor']
624 # Print out result
625 printNicely('All: ' + str(len(rel)) + ' people.')
626 for name in rel:
627 user = ' ' + cycle_color(name) + grey(' ' + rel[name] + ' ')
628 printNicely(user)
629 except:
630 printNicely(red('Omg some syntax is wrong.'))
631
632
305ce127 633def inbox():
634 """
635 Inbox direct messages
636 """
637 t = Twitter(auth=authen())
638 num = MESSAGES_DISPLAY
639 rel = []
640 if g['stuff'].isdigit():
641 num = g['stuff']
642 cur_page = 1
643 # Max message per page is 20 so we have to loop
644 while num > 20:
645 rel = rel + t.direct_messages(
646 count=20,
647 page=cur_page,
648 include_entities=False,
649 skip_status=False
650 )
651 num -= 20
652 cur_page += 1
653 rel = rel + t.direct_messages(
654 count=num,
655 page=cur_page,
656 include_entities=False,
657 skip_status=False
658 )
e2b81717 659 # Display
305ce127 660 printNicely('Inbox: newest ' + str(len(rel)) + ' messages.')
661 for m in reversed(rel):
662 print_message(m)
663 printNicely('')
664
e2b81717 665
305ce127 666def sent():
667 """
668 Sent direct messages
669 """
670 t = Twitter(auth=authen())
671 num = MESSAGES_DISPLAY
672 rel = []
673 if g['stuff'].isdigit():
674 num = int(g['stuff'])
675 cur_page = 1
676 # Max message per page is 20 so we have to loop
677 while num > 20:
678 rel = rel + t.direct_messages.sent(
679 count=20,
680 page=cur_page,
681 include_entities=False,
682 skip_status=False
683 )
684 num -= 20
685 cur_page += 1
686 rel = rel + t.direct_messages.sent(
687 count=num,
688 page=cur_page,
689 include_entities=False,
690 skip_status=False
691 )
e2b81717 692 # Display
305ce127 693 printNicely('Sent: newest ' + str(len(rel)) + ' messages.')
694 for m in reversed(rel):
695 print_message(m)
696 printNicely('')
e2b81717 697
305ce127 698
699def trash():
700 """
701 Remove message
702 """
703 t = Twitter(auth=authen())
704 try:
705 rid = int(g['stuff'].split()[0])
706 mid = db.rainbow_to_message_query(rid)[0].message_id
707 t.direct_messages.destroy(id=mid)
708 printNicely(green('Message deleted.'))
709 except:
710 printNicely(red('Sorry I can\'t understand.'))
711
712
e2b81717
O
713def whois():
714 """
715 Show profile of a specific user
716 """
717 t = Twitter(auth=authen())
718 screen_name = g['stuff'].split()[0]
719 if screen_name[0] == '@':
720 try:
721 user = t.users.show(
722 screen_name=screen_name[1:],
723 include_entities=False)
724 show_profile(user)
725 except:
726 printNicely(red('Omg no user.'))
727 else:
728 printNicely(red('Sorry I can\'t understand.'))
729
730
f5677fb1 731def follow():
843647ad 732 """
f5677fb1 733 Follow a user
843647ad
O
734 """
735 t = Twitter(auth=authen())
f5677fb1
O
736 screen_name = g['stuff'].split()[0]
737 if screen_name[0] == '@':
0f6e4daf 738 try:
739 t.friendships.create(screen_name=screen_name[1:], follow=True)
f5677fb1
O
740 printNicely(green('You are following ' + screen_name + ' now!'))
741 except:
742 printNicely(red('Sorry can not follow at this time.'))
743 else:
744 printNicely(red('Sorry I can\'t understand.'))
745
746
747def unfollow():
748 """
749 Unfollow a user
750 """
751 t = Twitter(auth=authen())
752 screen_name = g['stuff'].split()[0]
753 if screen_name[0] == '@':
0f6e4daf 754 try:
755 t.friendships.destroy(
305ce127 756 screen_name=screen_name[1:],
0f6e4daf 757 include_entities=False)
f5677fb1
O
758 printNicely(green('Unfollow ' + screen_name + ' success!'))
759 except:
760 printNicely(red('Sorry can not unfollow at this time.'))
761 else:
762 printNicely(red('Sorry I can\'t understand.'))
843647ad
O
763
764
305ce127 765def block():
766 """
767 Block a user
768 """
769 t = Twitter(auth=authen())
770 screen_name = g['stuff'].split()[0]
771 if screen_name[0] == '@':
772 try:
773 t.blocks.create(
e2b81717 774 screen_name=screen_name[1:],
305ce127 775 include_entities=False,
776 skip_status=True)
777 printNicely(green('You blocked ' + screen_name + '.'))
778 except:
779 printNicely(red('Sorry something went wrong.'))
780 else:
781 printNicely(red('Sorry I can\'t understand.'))
782
783
784def unblock():
785 """
786 Unblock a user
787 """
788 t = Twitter(auth=authen())
789 screen_name = g['stuff'].split()[0]
790 if screen_name[0] == '@':
791 try:
792 t.blocks.destroy(
793 screen_name=screen_name[1:],
794 include_entities=False,
795 skip_status=True)
796 printNicely(green('Unblock ' + screen_name + ' success!'))
797 except:
798 printNicely(red('Sorry something went wrong.'))
799 else:
800 printNicely(red('Sorry I can\'t understand.'))
801
802
803def report():
804 """
805 Report a user as a spam account
806 """
807 t = Twitter(auth=authen())
808 screen_name = g['stuff'].split()[0]
809 if screen_name[0] == '@':
810 try:
811 t.users.report_spam(
e2b81717 812 screen_name=screen_name[1:])
305ce127 813 printNicely(green('You reported ' + screen_name + '.'))
814 except:
815 printNicely(red('Sorry something went wrong.'))
816 else:
817 printNicely(red('Sorry I can\'t understand.'))
818
819
f405a7d0
O
820def help():
821 """
7b674cef 822 Help
f405a7d0 823 """
7e4ccbf3 824 s = ' ' * 2
825 h, w = os.popen('stty size', 'r').read().split()
e3885f55
O
826
827 usage = '\n'
828 usage += s + 'Hi boss! I\'m ready to serve you right now!\n'
7e4ccbf3 829 usage += s + '-' * (int(w) - 4) + '\n'
830
831 usage += s + 'You are ' + yellow('already') + ' on your personal stream.\n'
832 usage += s * 2 + green('switch public #AKB') + \
833 ' will switch to public stream and follow "' + \
834 yellow('AKB') + '" keyword.\n'
835 usage += s * 2 + green('switch mine') + \
836 ' will switch to your personal stream.\n'
837 usage += s * 2 + green('switch mine -f ') + \
838 ' will prompt to enter the filter.\n'
839 usage += s * 3 + yellow('Only nicks') + \
840 ' filter will decide nicks will be INCLUDE ONLY.\n'
841 usage += s * 3 + yellow('Ignore nicks') + \
842 ' filter will decide nicks will be EXCLUDE.\n'
843 usage += s * 2 + green('switch mine -d') + \
844 ' will use the config\'s ONLY_LIST and IGNORE_LIST.\n'
845 usage += s * 3 + '(see ' + grey('rainbowstream/config.py') + ').\n'
e3885f55
O
846
847 usage += s + 'For more action: \n'
7e4ccbf3 848 usage += s * 2 + green('home') + ' will show your timeline. ' + \
305ce127 849 green('home 7') + ' will show 7 tweets.\n'
7e4ccbf3 850 usage += s * 2 + green('view @mdo') + \
305ce127 851 ' will show ' + magenta('@mdo') + '\'s home.\n'
852 usage += s * 2 + green('mentions') + ' will show mentions timeline. ' + \
e2b81717 853 green('mentions 7') + ' will show 7 mention tweets.\n'
7e4ccbf3 854 usage += s * 2 + green('t oops ') + \
855 'will tweet "' + yellow('oops') + '" immediately.\n'
856 usage += s * 2 + \
857 green('rt 12 ') + ' will retweet to tweet with ' + \
858 yellow('[id=12]') + '.\n'
859 usage += s * 2 + \
860 green('fav 12 ') + ' will favorite the tweet with ' + \
861 yellow('[id=12]') + '.\n'
862 usage += s * 2 + green('rep 12 oops') + ' will reply "' + \
863 yellow('oops') + '" to tweet with ' + yellow('[id=12]') + '.\n'
864 usage += s * 2 + \
865 green('del 12 ') + ' will delete tweet with ' + \
866 yellow('[id=12]') + '.\n'
867 usage += s * 2 + \
868 green('ufav 12 ') + ' will unfavorite tweet with ' + \
869 yellow('[id=12]') + '.\n'
870 usage += s * 2 + green('s #AKB48') + ' will search for "' + \
871 yellow('AKB48') + '" and return 5 newest tweet.\n'
305ce127 872 usage += s * 2 + green('mes @dtvd88 hi') + ' will send a "hi" messege to ' + \
873 magenta('@dtvd88') + '.\n'
a99b7b04
O
874 usage += s * 2 + green('show image 12') + ' will show image in tweet with ' + \
875 yellow('[id=12]') + ' in your OS\'s image viewer.\n'
0f6e4daf 876 usage += s * 2 + \
877 green('ls fl') + \
b5f92888 878 ' will list all followers (people who are following you).\n'
0f6e4daf 879 usage += s * 2 + \
880 green('ls fr') + \
881 ' will list all friends (people who you are following).\n'
305ce127 882 usage += s * 2 + green('inbox') + ' will show inbox messages. ' + \
883 green('inbox 7') + ' will show newest 7 messages.\n'
884 usage += s * 2 + green('sent') + ' will show sent messages. ' + \
885 green('sent 7') + ' will show newest 7 messages.\n'
886 usage += s * 2 + green('trash 5') + ' will remove message with ' + \
887 yellow('[message_id=5]') + '.\n'
e2b81717
O
888 usage += s * 2 + green('whois @dtvd88') + ' will show profile of ' + \
889 magenta('@dtvd88') + '.\n'
f5677fb1 890 usage += s * 2 + green('fl @dtvd88') + ' will follow ' + \
305ce127 891 magenta('@dtvd88') + '.\n'
f5677fb1 892 usage += s * 2 + green('ufl @dtvd88') + ' will unfollow ' + \
305ce127 893 magenta('@dtvd88') + '.\n'
894 usage += s * 2 + green('block @dtvd88') + ' will block ' + \
895 magenta('@dtvd88') + '.\n'
896 usage += s * 2 + green('unblock @dtvd88') + ' will unblock ' + \
897 magenta('@dtvd88') + '.\n'
898 usage += s * 2 + green('report @dtvd88') + ' will report ' + \
899 magenta('@dtvd88') + ' as a spam account.\n'
7e4ccbf3 900 usage += s * 2 + green('h') + ' will show this help again.\n'
901 usage += s * 2 + green('c') + ' will clear the screen.\n'
902 usage += s * 2 + green('q') + ' will quit.\n'
903
904 usage += s + '-' * (int(w) - 4) + '\n'
e3885f55 905 usage += s + 'Have fun and hang tight!\n'
f405a7d0 906 printNicely(usage)
f405a7d0
O
907
908
843647ad 909def clear():
f405a7d0 910 """
7b674cef 911 Clear screen
f405a7d0 912 """
843647ad 913 os.system('clear')
f405a7d0
O
914
915
843647ad 916def quit():
b8dda704
O
917 """
918 Exit all
919 """
f5677fb1 920 save_history()
8e633322 921 os.system('rm -rf rainbow.db')
843647ad
O
922 os.kill(g['stream_pid'], signal.SIGKILL)
923 sys.exit()
b8dda704
O
924
925
94a5f62e 926def reset():
f405a7d0 927 """
94a5f62e 928 Reset prefix of line
f405a7d0 929 """
c91f75f2 930 if g['reset']:
e3885f55 931 printNicely(magenta('Need tips ? Type "h" and hit Enter key!'))
c91f75f2 932 g['reset'] = False
54277114
O
933
934
94a5f62e 935def process(cmd):
54277114 936 """
94a5f62e 937 Process switch
54277114 938 """
94a5f62e 939 return dict(zip(
940 cmdset,
b2b933a9 941 [
42fde775 942 switch,
b2b933a9 943 home,
944 view,
305ce127 945 mentions,
b2b933a9 946 tweet,
947 retweet,
7e4ccbf3 948 favorite,
b2b933a9 949 reply,
950 delete,
7e4ccbf3 951 unfavorite,
b2b933a9 952 search,
305ce127 953 message,
f5677fb1 954 show,
0f6e4daf 955 list,
305ce127 956 inbox,
957 sent,
958 trash,
e2b81717 959 whois,
f5677fb1
O
960 follow,
961 unfollow,
305ce127 962 block,
963 unblock,
964 report,
b2b933a9 965 help,
966 clear,
967 quit
968 ]
94a5f62e 969 )).get(cmd, reset)
970
971
972def listen():
42fde775 973 """
974 Listen to user's input
975 """
d51b4107
O
976 d = dict(zip(
977 cmdset,
978 [
affcb149 979 ['public', 'mine'], # switch
7e4ccbf3 980 [], # home
981 ['@'], # view
305ce127 982 [], # mentions
7e4ccbf3 983 [], # tweet
984 [], # retweet
f5677fb1 985 [], # favorite
7e4ccbf3 986 [], # reply
987 [], # delete
f5677fb1 988 [], # unfavorite
7e4ccbf3 989 ['#'], # search
305ce127 990 ['@'], # message
f5677fb1 991 ['image'], # show image
305ce127 992 ['fl', 'fr'], # list
993 [], # inbox
994 [], # sent
995 [], # trash
e2b81717 996 ['@'], # whois
affcb149
O
997 ['@'], # follow
998 ['@'], # unfollow
305ce127 999 ['@'], # block
1000 ['@'], # unblock
1001 ['@'], # report
7e4ccbf3 1002 [], # help
1003 [], # clear
1004 [], # quit
d51b4107 1005 ]
7e4ccbf3 1006 ))
d51b4107 1007 init_interactive_shell(d)
f5677fb1 1008 read_history()
819569e8 1009 reset()
b2b933a9 1010 while True:
1dd312f5
O
1011 if g['prefix']:
1012 line = raw_input(g['decorated_name'])
1013 else:
1014 line = raw_input()
843647ad
O
1015 try:
1016 cmd = line.split()[0]
1017 except:
1018 cmd = ''
f405a7d0 1019 # Save cmd to global variable and call process
843647ad
O
1020 g['stuff'] = ' '.join(line.split()[1:])
1021 process(cmd)()
7e4ccbf3 1022 if cmd in ['switch', 't', 'rt', 'rep']:
1dd312f5
O
1023 g['prefix'] = False
1024 else:
1025 g['prefix'] = True
54277114
O
1026
1027
42fde775 1028def stream(domain, args, name='Rainbow Stream'):
54277114 1029 """
f405a7d0 1030 Track the stream
54277114 1031 """
d51b4107 1032
54277114 1033 # The Logo
42fde775 1034 art_dict = {
1035 USER_DOMAIN: name,
1036 PUBLIC_DOMAIN: args.track_keywords,
1037 SITE_DOMAIN: 'Site Stream',
1038 }
1039 ascii_art(art_dict[domain])
d51b4107 1040
91476ec3
O
1041 # These arguments are optional:
1042 stream_args = dict(
1043 timeout=args.timeout,
1044 block=not args.no_block,
1045 heartbeat_timeout=args.heartbeat_timeout)
1046
1047 # Track keyword
1048 query_args = dict()
1049 if args.track_keywords:
1050 query_args['track'] = args.track_keywords
1051
1052 # Get stream
2a6238f5 1053 stream = TwitterStream(
22be990e 1054 auth=authen(),
42fde775 1055 domain=domain,
2a6238f5 1056 **stream_args)
91476ec3 1057
42fde775 1058 if domain == USER_DOMAIN:
1059 tweet_iter = stream.user(**query_args)
1060 elif domain == SITE_DOMAIN:
1061 tweet_iter = stream.site(**query_args)
1062 else:
1063 if args.track_keywords:
1064 tweet_iter = stream.statuses.filter(**query_args)
1065 else:
1066 tweet_iter = stream.statuses.sample()
1067
1068 # Iterate over the stream.
91476ec3
O
1069 for tweet in tweet_iter:
1070 if tweet is None:
1071 printNicely("-- None --")
1072 elif tweet is Timeout:
1073 printNicely("-- Timeout --")
1074 elif tweet is HeartbeatTimeout:
1075 printNicely("-- Heartbeat Timeout --")
1076 elif tweet is Hangup:
1077 printNicely("-- Hangup --")
1078 elif tweet.get('text'):
7e4ccbf3 1079 draw(
1080 t=tweet,
c1fa7c94 1081 iot=args.image_on_term,
7e4ccbf3 1082 keyword=args.track_keywords,
1083 fil=args.filter,
88af38d8 1084 ig=args.ignore,
0f6e4daf 1085 )
54277114
O
1086
1087
1088def fly():
1089 """
1090 Main function
1091 """
42fde775 1092 # Spawn stream process
1093 args = parse_arguments()
54277114 1094 get_decorated_name()
42fde775 1095 p = Process(target=stream, args=(USER_DOMAIN, args, g['original_name']))
1096 p.start()
1097
1098 # Start listen process
819569e8 1099 time.sleep(0.5)
c91f75f2 1100 g['reset'] = True
1dd312f5 1101 g['prefix'] = True
f405a7d0 1102 g['stream_pid'] = p.pid
c1fa7c94 1103 g['iot'] = args.image_on_term
0f6e4daf 1104 listen()