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(',')[0]
192 args
.ignore
= ignore
.split(',')[0]
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.'))
245 t
= Twitter(auth
=authen())
247 if g
['stuff'].isdigit():
249 for tweet
in reversed(t
.statuses
.home_timeline(count
=num
)):
258 t
= Twitter(auth
=authen())
259 user
= g
['stuff'].split()[0]
262 num
= int(g
['stuff'].split()[1])
265 for tweet
in reversed(t
.statuses
.user_timeline(count
=num
, screen_name
=user
[1:])):
269 printNicely(red('A name should begin with a \'@\''))
276 t
= Twitter(auth
=authen())
277 t
.statuses
.update(status
=g
['stuff'])
284 t
= Twitter(auth
=authen())
286 id = int(g
['stuff'].split()[0])
287 tid
= db
.rainbow_query(id)[0].tweet_id
288 t
.statuses
.retweet(id=tid
, include_entities
=False, trim_user
=True)
290 printNicely(red('Sorry I can\'t retweet for you.'))
297 t
= Twitter(auth
=authen())
299 id = int(g
['stuff'].split()[0])
300 tid
= db
.rainbow_query(id)[0].tweet_id
301 user
= t
.statuses
.show(id=tid
)['user']['screen_name']
302 status
= ' '.join(g
['stuff'].split()[1:])
303 status
= '@' + user
+ ' ' + status
.decode('utf-8')
304 t
.statuses
.update(status
=status
, in_reply_to_status_id
=tid
)
306 printNicely(red('Sorry I can\'t understand.'))
313 t
= Twitter(auth
=authen())
315 id = int(g
['stuff'].split()[0])
316 tid
= db
.rainbow_query(id)[0].tweet_id
317 t
.statuses
.destroy(id=tid
)
318 printNicely(green('Okay it\'s gone.'))
320 printNicely(red('Sorry I can\'t delete this tweet for you.'))
327 t
= Twitter(auth
=authen())
329 if g
['stuff'][0] == '#':
330 rel
= t
.search
.tweets(q
=g
['stuff'])['statuses']
332 printNicely('Newest tweets:')
333 for i
in reversed(xrange(SEARCH_MAX_RECORD
)):
334 draw(t
=rel
[i
], keyword
=g
['stuff'].strip()[1:])
337 printNicely(magenta('I\'m afraid there is no result'))
339 printNicely(red('A keyword should be a hashtag (like \'#AKB48\')'))
341 printNicely(red('Sorry I can\'t understand.'))
346 List of friend (following)
348 t
= Twitter(auth
=authen())
349 g
['friends'] = t
.friends
.ids()['ids']
350 for i
in g
['friends']:
351 screen_name
= t
.users
.lookup(user_id
=i
)[0]['screen_name']
352 user
= cycle_color('@' + screen_name
)
361 t
= Twitter(auth
=authen())
362 g
['followers'] = t
.followers
.ids()['ids']
363 for i
in g
['followers']:
364 screen_name
= t
.users
.lookup(user_id
=i
)[0]['screen_name']
365 user
= cycle_color('@' + screen_name
)
375 Hi boss! I'm ready to serve you right now!
376 -------------------------------------------------------------
377 You are already on your personal stream:
378 "switch public #AKB" will switch to public stream and follow "AKB" keyword.
379 "switch mine" will switch back to your personal stream.
380 "switch mine -f" will prompt to enter the filter.
381 "Only nicks" filter will decide nicks will be INCLUDE ONLY.
382 "Ignore nicks" filter will decide nicks will be EXCLUDE.
383 "switch mine -d" will use the config's ONLY_LIST and IGNORE_LIST
384 (see rainbowstream/config.py).
386 "home" will show your timeline. "home 7" will show 7 tweet.
387 "view @bob" will show your friend @bob's home.
388 "t oops" will tweet "oops" immediately.
389 "rt 12345" will retweet to tweet with id "12345".
390 "rep 12345 oops" will reply "oops" to tweet with id "12345".
391 "del 12345" will delete tweet with id "12345".
392 "s #AKB48" will search for "AKB48" and return 5 newest tweet.
393 "fr" will list out your following people.
394 "fl" will list out your followers.
395 "h" will show this help again.
396 "c" will clear the terminal.
398 -------------------------------------------------------------
399 Have fun and hang tight!
415 os
.system('rm -rf rainbow.db')
416 os
.kill(g
['stream_pid'], signal
.SIGKILL
)
425 printNicely(green('Need tips ? Type "h" and hit Enter key!'))
455 Listen to user's input
460 ['public #','mine'], # switch
475 init_interactive_shell(d
)
479 line
= raw_input(g
['decorated_name'])
483 cmd
= line
.split()[0]
486 # Save cmd to global variable and call process
487 g
['stuff'] = ' '.join(line
.split()[1:])
489 if cmd
in ['switch','t','rt','rep']:
495 def stream(domain
, args
, name
='Rainbow Stream'):
503 PUBLIC_DOMAIN
: args
.track_keywords
,
504 SITE_DOMAIN
: 'Site Stream',
506 ascii_art(art_dict
[domain
])
508 # These arguments are optional:
510 timeout
=args
.timeout
,
511 block
=not args
.no_block
,
512 heartbeat_timeout
=args
.heartbeat_timeout
)
516 if args
.track_keywords
:
517 query_args
['track'] = args
.track_keywords
520 stream
= TwitterStream(
525 if domain
== USER_DOMAIN
:
526 tweet_iter
= stream
.user(**query_args
)
527 elif domain
== SITE_DOMAIN
:
528 tweet_iter
= stream
.site(**query_args
)
530 if args
.track_keywords
:
531 tweet_iter
= stream
.statuses
.filter(**query_args
)
533 tweet_iter
= stream
.statuses
.sample()
535 # Iterate over the stream.
536 for tweet
in tweet_iter
:
538 printNicely("-- None --")
539 elif tweet
is Timeout
:
540 printNicely("-- Timeout --")
541 elif tweet
is HeartbeatTimeout
:
542 printNicely("-- Heartbeat Timeout --")
543 elif tweet
is Hangup
:
544 printNicely("-- Hangup --")
545 elif tweet
.get('text'):
546 draw(t
=tweet
, keyword
=args
.track_keywords
, fil
=args
.filter, ig
=args
.ignore
)
553 # Spawn stream process
554 args
= parse_arguments()
556 p
= Process(target
=stream
, args
=(USER_DOMAIN
, args
, g
['original_name']))
559 # Start listen process
563 g
['stream_pid'] = p
.pid