2 Colorful user's timeline stream
4 from __future__
import print_function
5 from multiprocessing
import Process
6 from dateutil
import parser
16 from twitter
.stream
import TwitterStream
, Timeout
, HeartbeatTimeout
, Hangup
17 from twitter
.api
import *
18 from twitter
.oauth
import OAuth
, read_token_file
19 from twitter
.oauth_dance
import oauth_dance
20 from twitter
.util
import printNicely
24 from .interactive
import *
46 def draw(t
, keyword
=None, fil
=[], ig
=[]):
54 screen_name
= t
['user']['screen_name']
55 name
= t
['user']['name']
56 created_at
= t
['created_at']
57 date
= parser
.parse(created_at
)
58 date
= date
- datetime
.timedelta(seconds
=time
.timezone
)
59 clock
= date
.strftime('%Y/%m/%d %H:%M:%S')
62 screen_name
= '@' + screen_name
63 if fil
and screen_name
not in fil
:
65 if ig
and screen_name
in ig
:
68 res
= db
.tweet_query(tid
)
71 res
= db
.tweet_query(tid
)
72 rid
= res
[0].rainbow_id
75 user
= cycle_color(name
) + grey(' ' + screen_name
+ ' ')
76 meta
= grey('[' + clock
+ '] [id=' + str(rid
) + ']')
79 tweet
= map(lambda x
: grey(x
) if x
== 'RT' else x
, tweet
)
80 # Highlight screen_name
81 tweet
= map(lambda x
: cycle_color(x
) if x
[0] == '@' else x
, tweet
)
83 tweet
= map(lambda x
: cyan(x
) if x
[0:7] == 'http://' else x
, tweet
)
84 # Highlight search keyword
87 lambda x
: on_yellow(x
) if
88 ''.join(c
for c
in x
if c
.isalnum()).lower() == keyword
.lower()
92 tweet
= ' '.join(tweet
)
95 line1
= u
"{u:>{uw}}:".format(
99 line2
= u
"{c:>{cw}}".format(
111 def parse_arguments():
115 parser
= argparse
.ArgumentParser(description
=__doc__
or "")
119 help='Timeout for the stream (seconds).')
122 '--heartbeat-timeout',
123 help='Set heartbeat timeout.',
129 help='Set stream to non-blocking.')
133 help='Search the stream for specific text.')
137 help='Filter specific screen_name.')
141 help='Ignore specific screen_name.')
142 return parser
.parse_args()
147 Authenticate with Twitter OAuth
149 # When using rainbow stream you must authorize.
150 twitter_credential
= os
.environ
.get(
154 '')) + os
.sep
+ '.rainbow_oauth'
155 if not os
.path
.exists(twitter_credential
):
156 oauth_dance("Rainbow Stream",
160 oauth_token
, oauth_token_secret
= read_token_file(twitter_credential
)
168 def get_decorated_name():
170 Beginning of every line
172 t
= Twitter(auth
=authen())
173 name
= '@' + t
.account
.verify_credentials()['screen_name']
174 g
['original_name'] = name
[1:]
175 g
['decorated_name'] = grey('[') + grey(name
) + grey(']: ')
183 target
= g
['stuff'].split()[0]
186 args
= parse_arguments()
188 if g
['stuff'].split()[-1] == '-f':
189 only
= raw_input('Only nicks: ')
190 ignore
= raw_input('Ignore nicks: ')
191 args
.filter = only
.split(',')
192 args
.ignore
= ignore
.split(',')
193 elif g
['stuff'].split()[-1] == '-d':
194 args
.filter = ONLY_LIST
195 args
.ignore
= IGNORE_LIST
197 printNicely(red('Sorry, wrong format.'))
201 if target
== 'public':
202 keyword
= g
['stuff'].split()[1]
203 if keyword
[0] == '#':
204 keyword
= keyword
[1:]
206 os
.kill(g
['stream_pid'], signal
.SIGKILL
)
207 args
.track_keywords
= keyword
215 g
['stream_pid'] = p
.pid
218 elif target
== 'mine':
220 os
.kill(g
['stream_pid'], signal
.SIGKILL
)
229 g
['stream_pid'] = p
.pid
231 printNicely(green('Stream switched.'))
233 printNicely(cyan('Only: ' + str(args
.filter)))
235 printNicely(red('Ignore: ' + str(args
.ignore
)))
238 printNicely(red('Sorry I can\'t understand.'))
246 t
= Twitter(auth
=authen())
248 if g
['stuff'].isdigit():
250 for tweet
in reversed(t
.statuses
.home_timeline(count
=num
)):
259 t
= Twitter(auth
=authen())
260 user
= g
['stuff'].split()[0]
263 num
= int(g
['stuff'].split()[1])
266 for tweet
in reversed(t
.statuses
.user_timeline(count
=num
, screen_name
=user
[1:])):
270 printNicely(red('A name should begin with a \'@\''))
277 t
= Twitter(auth
=authen())
278 t
.statuses
.update(status
=g
['stuff'])
286 t
= Twitter(auth
=authen())
288 id = int(g
['stuff'].split()[0])
289 tid
= db
.rainbow_query(id)[0].tweet_id
290 t
.statuses
.retweet(id=tid
, include_entities
=False, trim_user
=True)
292 printNicely(red('Sorry I can\'t retweet for you.'))
300 t
= Twitter(auth
=authen())
302 id = int(g
['stuff'].split()[0])
303 tid
= db
.rainbow_query(id)[0].tweet_id
304 user
= t
.statuses
.show(id=tid
)['user']['screen_name']
305 status
= ' '.join(g
['stuff'].split()[1:])
306 status
= '@' + user
+ ' ' + status
.decode('utf-8')
307 t
.statuses
.update(status
=status
, in_reply_to_status_id
=tid
)
309 printNicely(red('Sorry I can\'t understand.'))
317 t
= Twitter(auth
=authen())
319 id = int(g
['stuff'].split()[0])
320 tid
= db
.rainbow_query(id)[0].tweet_id
321 t
.statuses
.destroy(id=tid
)
322 printNicely(green('Okay it\'s gone.'))
324 printNicely(red('Sorry I can\'t delete this tweet for you.'))
331 t
= Twitter(auth
=authen())
333 if g
['stuff'][0] == '#':
334 rel
= t
.search
.tweets(q
=g
['stuff'])['statuses']
336 printNicely('Newest tweets:')
337 for i
in reversed(xrange(SEARCH_MAX_RECORD
)):
338 draw(t
=rel
[i
], keyword
=g
['stuff'].strip()[1:])
341 printNicely(magenta('I\'m afraid there is no result'))
343 printNicely(red('A keyword should be a hashtag (like \'#AKB48\')'))
345 printNicely(red('Sorry I can\'t understand.'))
350 List of friend (following)
352 t
= Twitter(auth
=authen())
353 g
['friends'] = t
.friends
.ids()['ids']
354 for i
in g
['friends']:
355 screen_name
= t
.users
.lookup(user_id
=i
)[0]['screen_name']
356 user
= cycle_color('@' + screen_name
)
365 t
= Twitter(auth
=authen())
366 g
['followers'] = t
.followers
.ids()['ids']
367 for i
in g
['followers']:
368 screen_name
= t
.users
.lookup(user_id
=i
)[0]['screen_name']
369 user
= cycle_color('@' + screen_name
)
379 Hi boss! I'm ready to serve you right now!
380 -------------------------------------------------------------
381 You are already on your personal stream:
382 "switch public #AKB" will switch to public stream and follow "AKB" keyword.
383 "switch mine" will switch back to your personal stream.
384 "switch mine -f" will prompt to enter the filter.
385 "Only nicks" filter will decide nicks will be INCLUDE ONLY.
386 "Ignore nicks" filter will decide nicks will be EXCLUDE.
387 "switch mine -d" will use the config's ONLY_LIST and IGNORE_LIST(see config.py).
389 "home" will show your timeline. "home 7" will show 7 tweet.
390 "view @bob" will show your friend @bob's home.
391 "t oops" will tweet "oops" immediately.
392 "rt 12345" will retweet to tweet with id "12345".
393 "rep 12345 oops" will reply "oops" to tweet with id "12345".
394 "del 12345" will delete tweet with id "12345".
395 "s #AKB48" will search for "AKB48" and return 5 newest tweet.
396 "fr" will list out your following people.
397 "fl" will list out your followers.
398 "h" will show this help again.
399 "c" will clear the terminal.
401 -------------------------------------------------------------
402 Have fun and hang tight!
419 os
.system('rm -rf rainbow.db')
420 os
.kill(g
['stream_pid'], signal
.SIGKILL
)
429 printNicely(green('Need tips ? Type "h" and hit Enter key!'))
460 Listen to user's input
465 ['public #','mine'], # switch
480 init_interactive_shell(d
)
483 if g
['prefix'] and not first
:
484 line
= raw_input(g
['decorated_name'])
488 cmd
= line
.split()[0]
491 # Save cmd to global variable and call process
492 g
['stuff'] = ' '.join(line
.split()[1:])
497 def stream(domain
, args
, name
='Rainbow Stream'):
505 PUBLIC_DOMAIN
: args
.track_keywords
,
506 SITE_DOMAIN
: 'Site Stream',
508 ascii_art(art_dict
[domain
])
510 # These arguments are optional:
512 timeout
=args
.timeout
,
513 block
=not args
.no_block
,
514 heartbeat_timeout
=args
.heartbeat_timeout
)
518 if args
.track_keywords
:
519 query_args
['track'] = args
.track_keywords
522 stream
= TwitterStream(
527 if domain
== USER_DOMAIN
:
528 tweet_iter
= stream
.user(**query_args
)
529 elif domain
== SITE_DOMAIN
:
530 tweet_iter
= stream
.site(**query_args
)
532 if args
.track_keywords
:
533 tweet_iter
= stream
.statuses
.filter(**query_args
)
535 tweet_iter
= stream
.statuses
.sample()
537 # Iterate over the stream.
538 for tweet
in tweet_iter
:
540 printNicely("-- None --")
541 elif tweet
is Timeout
:
542 printNicely("-- Timeout --")
543 elif tweet
is HeartbeatTimeout
:
544 printNicely("-- Heartbeat Timeout --")
545 elif tweet
is Hangup
:
546 printNicely("-- Hangup --")
547 elif tweet
.get('text'):
548 draw(t
=tweet
, keyword
=args
.track_keywords
, fil
=args
.filter, ig
=args
.ignore
)
555 # Spawn stream process
556 args
= parse_arguments()
558 p
= Process(target
=stream
, args
=(USER_DOMAIN
, args
, g
['original_name']))
561 # Start listen process
564 g
['stream_pid'] = p
.pid