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):
53 screen_name
= t
['user']['screen_name']
54 name
= t
['user']['name']
55 created_at
= t
['created_at']
56 date
= parser
.parse(created_at
)
57 date
= date
- datetime
.timedelta(seconds
=time
.timezone
)
58 clock
= date
.strftime('%Y/%m/%d %H:%M:%S')
60 res
= db
.tweet_query(tid
)
63 res
= db
.tweet_query(tid
)
64 rid
= res
[0].rainbow_id
67 user
= cycle_color(name
) + grey(' ' + '@' + screen_name
+ ' ')
68 meta
= grey('[' + clock
+ '] [id=' + str(rid
) + ']')
71 tweet
= map(lambda x
: grey(x
) if x
== 'RT' else x
, tweet
)
72 # Highlight screen_name
73 tweet
= map(lambda x
: cycle_color(x
) if x
[0] == '@' else x
, tweet
)
75 tweet
= map(lambda x
: cyan(x
) if x
[0:7] == 'http://' else x
, tweet
)
76 # Highlight search keyword
79 lambda x
: on_yellow(x
) if
80 ''.join(c
for c
in x
if c
.isalnum()).lower() == keyword
.lower()
84 tweet
= ' '.join(tweet
)
87 line1
= u
"{u:>{uw}}:".format(
91 line2
= u
"{c:>{cw}}".format(
103 def parse_arguments():
107 parser
= argparse
.ArgumentParser(description
=__doc__
or "")
111 help='Timeout for the stream (seconds).')
114 '--heartbeat-timeout',
115 help='Set heartbeat timeout.',
121 help='Set stream to non-blocking.')
125 help='Search the stream for specific text.')
126 return parser
.parse_args()
131 Authenticate with Twitter OAuth
133 # When using rainbow stream you must authorize.
134 twitter_credential
= os
.environ
.get(
138 '')) + os
.sep
+ '.rainbow_oauth'
139 if not os
.path
.exists(twitter_credential
):
140 oauth_dance("Rainbow Stream",
144 oauth_token
, oauth_token_secret
= read_token_file(twitter_credential
)
152 def get_decorated_name():
154 Beginning of every line
156 t
= Twitter(auth
=authen())
157 name
= '@' + t
.account
.verify_credentials()['screen_name']
158 g
['original_name'] = name
[1:]
159 g
['decorated_name'] = grey('[') + grey(name
) + grey(']: ')
167 target
= g
['stuff'].split()[0]
170 if target
== 'public':
171 keyword
= g
['stuff'].split()[1]
172 if keyword
[0] == '#':
173 keyword
= keyword
[1:]
175 os
.kill(g
['stream_pid'], signal
.SIGKILL
)
176 args
= parse_arguments()
177 args
.track_keywords
= keyword
185 g
['stream_pid'] = p
.pid
188 elif target
== 'mine':
190 os
.kill(g
['stream_pid'], signal
.SIGKILL
)
191 args
= parse_arguments()
200 g
['stream_pid'] = p
.pid
201 printNicely(green('stream switched.'))
203 printNicely(red('Sorry I can\'t understand.'))
211 t
= Twitter(auth
=authen())
213 if g
['stuff'].isdigit():
215 for tweet
in reversed(t
.statuses
.home_timeline(count
=num
)):
224 t
= Twitter(auth
=authen())
225 user
= g
['stuff'].split()[0]
228 num
= int(g
['stuff'].split()[1])
231 for tweet
in reversed(t
.statuses
.user_timeline(count
=num
, screen_name
=user
[1:])):
235 printNicely(red('A name should begin with a \'@\''))
242 t
= Twitter(auth
=authen())
243 t
.statuses
.update(status
=g
['stuff'])
251 t
= Twitter(auth
=authen())
253 id = int(g
['stuff'].split()[0])
254 tid
= db
.rainbow_query(id)[0].tweet_id
255 t
.statuses
.retweet(id=tid
, include_entities
=False, trim_user
=True)
257 printNicely(red('Sorry I can\'t retweet for you.'))
265 t
= Twitter(auth
=authen())
267 id = int(g
['stuff'].split()[0])
268 tid
= db
.rainbow_query(id)[0].tweet_id
269 user
= t
.statuses
.show(id=tid
)['user']['screen_name']
270 status
= ' '.join(g
['stuff'].split()[1:])
271 status
= '@' + user
+ ' ' + status
.decode('utf-8')
272 t
.statuses
.update(status
=status
, in_reply_to_status_id
=tid
)
274 printNicely(red('Sorry I can\'t understand.'))
282 t
= Twitter(auth
=authen())
284 id = int(g
['stuff'].split()[0])
285 tid
= db
.rainbow_query(id)[0].tweet_id
286 t
.statuses
.destroy(id=tid
)
287 printNicely(green('Okay it\'s gone.'))
289 printNicely(red('Sorry I can\'t delete this tweet for you.'))
296 t
= Twitter(auth
=authen())
298 if g
['stuff'][0] == '#':
299 rel
= t
.search
.tweets(q
=g
['stuff'])['statuses']
301 printNicely('Newest tweets:')
302 for i
in reversed(xrange(SEARCH_MAX_RECORD
)):
303 draw(t
=rel
[i
], keyword
=g
['stuff'].strip()[1:])
306 printNicely(magenta('I\'m afraid there is no result'))
308 printNicely(red('A keyword should be a hashtag (like \'#AKB48\')'))
310 printNicely(red('Sorry I can\'t understand.'))
315 List of friend (following)
317 t
= Twitter(auth
=authen())
318 g
['friends'] = t
.friends
.ids()['ids']
319 for i
in g
['friends']:
320 screen_name
= t
.users
.lookup(user_id
=i
)[0]['screen_name']
321 user
= cycle_color('@' + screen_name
)
330 t
= Twitter(auth
=authen())
331 g
['followers'] = t
.followers
.ids()['ids']
332 for i
in g
['followers']:
333 screen_name
= t
.users
.lookup(user_id
=i
)[0]['screen_name']
334 user
= cycle_color('@' + screen_name
)
344 Hi boss! I'm ready to serve you right now!
345 -------------------------------------------------------------
346 You are already on your personal stream:
347 "switch public #AKB" will switch to public stream and follow "AKB" keyword.
348 "switch mine" will switch back to your personal stream.
350 "home" will show your timeline. "home 7" will show 7 tweet.
351 "view @bob" will show your friend @bob's home.
352 "t oops" will tweet "oops" immediately.
353 "rt 12345" will retweet to tweet with id "12345".
354 "rep 12345 oops" will reply "oops" to tweet with id "12345".
355 "del 12345" will delete tweet with id "12345".
356 "s #AKB48" will search for "AKB48" and return 5 newest tweet.
357 "fr" will list out your following people.
358 "fl" will list out your followers.
359 "h" will show this help again.
360 "c" will clear the terminal.
362 -------------------------------------------------------------
363 Have fun and hang tight!
380 os
.system('rm -rf rainbow.db')
381 os
.kill(g
['stream_pid'], signal
.SIGKILL
)
390 printNicely(green('Need tips ? Type "h" and hit Enter key!'))
421 Listen to user's input
423 init_interactive_shell(cmdset
)
426 if g
['prefix'] and not first
:
427 line
= raw_input(g
['decorated_name'])
431 cmd
= line
.split()[0]
434 # Save cmd to global variable and call process
435 g
['stuff'] = ' '.join(line
.split()[1:])
440 def stream(domain
, args
, name
='Rainbow Stream'):
447 PUBLIC_DOMAIN
: args
.track_keywords
,
448 SITE_DOMAIN
: 'Site Stream',
450 ascii_art(art_dict
[domain
])
451 # These arguments are optional:
453 timeout
=args
.timeout
,
454 block
=not args
.no_block
,
455 heartbeat_timeout
=args
.heartbeat_timeout
)
459 if args
.track_keywords
:
460 query_args
['track'] = args
.track_keywords
463 stream
= TwitterStream(
468 if domain
== USER_DOMAIN
:
469 tweet_iter
= stream
.user(**query_args
)
470 elif domain
== SITE_DOMAIN
:
471 tweet_iter
= stream
.site(**query_args
)
473 if args
.track_keywords
:
474 tweet_iter
= stream
.statuses
.filter(**query_args
)
476 tweet_iter
= stream
.statuses
.sample()
478 # Iterate over the stream.
479 for tweet
in tweet_iter
:
481 printNicely("-- None --")
482 elif tweet
is Timeout
:
483 printNicely("-- Timeout --")
484 elif tweet
is HeartbeatTimeout
:
485 printNicely("-- Heartbeat Timeout --")
486 elif tweet
is Hangup
:
487 printNicely("-- Hangup --")
488 elif tweet
.get('text'):
496 # Spawn stream process
497 args
= parse_arguments()
499 p
= Process(target
=stream
, args
=(USER_DOMAIN
, args
, g
['original_name']))
502 # Start listen process
505 g
['stream_pid'] = p
.pid
513 os
.system('screen -S rainbow fly')