highlight and clear
[rainbowstream.git] / rainbowstream / rainbow.py
CommitLineData
91476ec3
O
1"""
2Colorful user's timeline stream
3"""
4
5from __future__ import print_function
54277114 6from multiprocessing import Process
91476ec3 7
f405a7d0 8import os, os.path, argparse, sys, time, signal
91476ec3
O
9
10from twitter.stream import TwitterStream, Timeout, HeartbeatTimeout, Hangup
54277114 11from twitter.api import *
91476ec3 12from twitter.oauth import OAuth, read_token_file
8c840a83 13from twitter.oauth_dance import oauth_dance
91476ec3
O
14from twitter.util import printNicely
15from dateutil import parser
91476ec3 16
2a6238f5
O
17from .colors import *
18from .config import *
19
f405a7d0 20g = {}
91476ec3 21
b8dda704 22def draw(t,keyword=None):
91476ec3
O
23 """
24 Draw the rainbow
25 """
26 # Retrieve tweet
27 text = t['text']
28 screen_name = t['user']['screen_name']
29 name = t['user']['name']
30 created_at = t['created_at']
31 date = parser.parse(created_at)
32 time = date.strftime('%Y/%m/%d %H:%M:%S')
33
34 # Format info
54277114 35 user = cycle_color(name) + grey(' ' + '@' + screen_name + ' ')
2a6238f5 36 clock = grey('[' + time + ']')
8c840a83 37 tweet = text.split()
b8dda704 38 # Highlight RT
2a6238f5 39 tweet = map(lambda x: grey(x) if x == 'RT' else x, tweet)
b8dda704 40 # Highlight screen_name
2a6238f5 41 tweet = map(lambda x: cycle_color(x) if x[0] == '@' else x, tweet)
b8dda704 42 # Highlight link
2a6238f5 43 tweet = map(lambda x: cyan(x) if x[0:7] == 'http://' else x, tweet)
b8dda704
O
44 # Highlight search keyword
45 tweet = map(lambda x: on_yellow(x) if ''.join(c for c in x if c.isalnum()).lower() == keyword.lower() else x, tweet)
8c840a83 46 tweet = ' '.join(tweet)
91476ec3
O
47
48 # Draw rainbow
06773ffe 49 line1 = u"{u:>{uw}}:".format(
2a6238f5
O
50 u=user,
51 uw=len(user) + 2,
91476ec3 52 )
06773ffe 53 line2 = u"{c:>{cw}}".format(
2a6238f5
O
54 c=clock,
55 cw=len(clock) + 2,
06773ffe
O
56 )
57 line3 = ' ' + tweet
58 line4 = '\n'
91476ec3 59
f405a7d0
O
60 printNicely(line1)
61 printNicely(line2)
62 printNicely(line3)
63 printNicely(line4)
91476ec3
O
64
65
66def parse_arguments():
67 """
68 Parse the arguments
69 """
70
71 parser = argparse.ArgumentParser(description=__doc__ or "")
72
2a6238f5
O
73 parser.add_argument(
74 '-to',
75 '--timeout',
76 help='Timeout for the stream (seconds).')
77 parser.add_argument(
78 '-ht',
79 '--heartbeat-timeout',
80 help='Set heartbeat timeout.',
81 default=90)
82 parser.add_argument(
83 '-nb',
84 '--no-block',
85 action='store_true',
86 help='Set stream to non-blocking.')
87 parser.add_argument(
88 '-tt',
89 '--track-keywords',
90 help='Search the stream for specific text.')
91476ec3
O
91 return parser.parse_args()
92
93
54277114
O
94def authen():
95 """
96 authenticate with Twitter OAuth
97 """
8c840a83 98 # When using rainbow stream you must authorize.
2a6238f5
O
99 twitter_credential = os.environ.get(
100 'HOME',
101 os.environ.get(
102 'USERPROFILE',
103 '')) + os.sep + '.rainbow_oauth'
8c840a83
O
104 if not os.path.exists(twitter_credential):
105 oauth_dance("Rainbow Stream",
106 CONSUMER_KEY,
107 CONSUMER_SECRET,
108 twitter_credential)
109 oauth_token, oauth_token_secret = read_token_file(twitter_credential)
54277114 110 return OAuth(
2a6238f5
O
111 oauth_token,
112 oauth_token_secret,
113 CONSUMER_KEY,
114 CONSUMER_SECRET)
91476ec3 115
54277114
O
116
117def get_decorated_name():
118 """
119 Beginning of every line
120 """
121 t = Twitter(auth=authen())
122 name = '@' + t.statuses.user_timeline()[-1]['user']['screen_name']
f405a7d0 123 g['decorated_name'] = grey('[') + grey(name) + grey(']: ')
54277114 124
f405a7d0
O
125
126def tweet():
54277114
O
127 """
128 Authen and tweet
129 """
130 t = Twitter(auth=authen())
f405a7d0
O
131 t.statuses.update(status=g['stuff'])
132
133
134def search():
135 """
136 Authen and search
137 """
138 t = Twitter(auth=authen())
139 rel = t.search.tweets(q='#' + g['stuff'])['statuses']
140 printNicely(grey('**************************************************************************************\n'))
05105565 141 print('Newest',SEARCH_MAX_RECORD, 'tweet: \n')
f405a7d0 142 for i in xrange(5):
b8dda704 143 draw(t=rel[i],keyword=g['stuff'].strip())
f405a7d0
O
144 printNicely(grey('**************************************************************************************\n'))
145
146
147def help():
148 """
149 Print help
150 """
151 usage = '''
152 Hi boss! I'm ready to serve you right now!
153 ----------------------------------------------------
154 "!" at the beginning will start to tweet immediately
8c234c44 155 "/" at the beginning will search for 5 newest tweet
b8dda704
O
156 "?" or "h" will print this help once again
157 "c" will clear the terminal
f405a7d0
O
158 "q" will exit
159 ----------------------------------------------------
160 Hvae fun and hang tight!
161 '''
162 printNicely(usage)
163 sys.stdout.write(g['decorated_name'])
164
165
166def quit():
167 """
168 Exit all
169 """
170 os.kill(g['stream_pid'], signal.SIGKILL)
171 sys.exit()
172
173
b8dda704
O
174def clear():
175 """
176 Exit all
177 """
178 os.system('clear')
179
180
f405a7d0
O
181def process(line):
182 """
183 Process switch by start of line
184 """
185 return {
186 '!' : tweet,
187 '/' : search,
188 '?' : help,
b8dda704
O
189 'h' : help,
190 'c' : clear,
f405a7d0
O
191 'q' : quit,
192 }.get(line[0],lambda: sys.stdout.write(g['decorated_name']))
54277114
O
193
194
195def listen(stdin):
196 """
197 Listen to user's input
198 """
199 for line in iter(stdin.readline, ''):
f405a7d0
O
200 # Save cmd to global variable and call process
201 g['stuff'] = line[1:]
202 process(line)()
54277114
O
203 stdin.close()
204
205
206def stream():
207 """
f405a7d0 208 Track the stream
54277114
O
209 """
210 args = parse_arguments()
211
212 # The Logo
213 ascii_art()
91476ec3
O
214 # These arguments are optional:
215 stream_args = dict(
216 timeout=args.timeout,
217 block=not args.no_block,
218 heartbeat_timeout=args.heartbeat_timeout)
219
220 # Track keyword
221 query_args = dict()
222 if args.track_keywords:
223 query_args['track'] = args.track_keywords
224
225 # Get stream
2a6238f5 226 stream = TwitterStream(
54277114
O
227 auth = authen(),
228 domain = 'userstream.twitter.com',
2a6238f5 229 **stream_args)
91476ec3
O
230 tweet_iter = stream.user(**query_args)
231
232 # Iterate over the sample stream.
233 for tweet in tweet_iter:
234 if tweet is None:
235 printNicely("-- None --")
236 elif tweet is Timeout:
237 printNicely("-- Timeout --")
238 elif tweet is HeartbeatTimeout:
239 printNicely("-- Heartbeat Timeout --")
240 elif tweet is Hangup:
241 printNicely("-- Hangup --")
242 elif tweet.get('text'):
f405a7d0 243 draw(t=tweet)
54277114
O
244
245
246def fly():
247 """
248 Main function
249 """
250 get_decorated_name()
251 p = Process(target = stream)
252 p.start()
f405a7d0 253 g['stream_pid'] = p.pid
54277114
O
254 listen(sys.stdin)
255