add list support and seperate help
[rainbowstream.git] / rainbowstream / draw.py
CommitLineData
e9f5200b
VNM
1import random
2import itertools
7500d90b
VNM
3import requests
4import datetime
5import time
6
2da50cc4 7from twitter.util import printNicely
e9f5200b
VNM
8from functools import wraps
9from pyfiglet import figlet_format
10from functools import reduce
7500d90b
VNM
11from StringIO import StringIO
12from dateutil import parser
2da50cc4 13from .c_image import *
7500d90b
VNM
14from .colors import *
15from .config import *
16from .db import *
17
18db = RainbowDB()
1fdd6a5c
VNM
19g = {}
20
e9f5200b
VNM
21def init_cycle():
22 """
23 Init the cycle
24 """
25 colors_shuffle = [globals()[i.encode('utf8')]
37ae740e 26 if not i.startswith('term_')
8124f3a8 27 else term_color(int(i[5:]))
e9f5200b 28 for i in c['CYCLE_COLOR']]
5f22104f 29 return itertools.cycle(colors_shuffle)
30g['cyc'] = init_cycle()
e43ebfa6 31g['cache'] = {}
1fdd6a5c 32
e9f5200b 33
e43ebfa6 34def reset_cycle():
2359c276
VNM
35 """
36 Notify from rainbow
37 """
5f22104f 38 g['cyc'] = init_cycle()
e43ebfa6 39 g['cache'] = {}
2359c276
VNM
40
41
e9f5200b
VNM
42def order_rainbow(s):
43 """
44 Print a string with ordered color with each character
45 """
5f22104f 46 colors_shuffle = [globals()[i.encode('utf8')]
47 if not i.startswith('term_')
48 else term_color(int(i[5:]))
49 for i in c['CYCLE_COLOR']]
50 colored = [colors_shuffle[i % 7](s[i]) for i in xrange(len(s))]
51 return reduce(lambda x, y: x + y, colored)
e9f5200b
VNM
52
53
54def random_rainbow(s):
55 """
56 Print a string with random color with each character
57 """
5f22104f 58 colors_shuffle = [globals()[i.encode('utf8')]
59 if not i.startswith('term_')
60 else term_color(int(i[5:]))
61 for i in c['CYCLE_COLOR']]
62 colored = [random.choice(colors_shuffle)(i) for i in s]
63 return reduce(lambda x, y: x + y, colored)
e9f5200b
VNM
64
65
66def Memoize(func):
67 """
68 Memoize decorator
69 """
e9f5200b
VNM
70 @wraps(func)
71 def wrapper(*args):
e43ebfa6 72 if args not in g['cache']:
73 g['cache'][args] = func(*args)
74 return g['cache'][args]
e9f5200b
VNM
75 return wrapper
76
77
78@Memoize
79def cycle_color(s):
80 """
81 Cycle the colors_shuffle
82 """
1fdd6a5c 83 return next(g['cyc'])(s)
e9f5200b
VNM
84
85
86def ascii_art(text):
87 """
88 Draw the Ascii Art
89 """
90 fi = figlet_format(text, font='doom')
91 print('\n'.join(
1fdd6a5c 92 [next(g['cyc'])(i) for i in fi.split('\n')]
e9f5200b
VNM
93 ))
94
95
2a0cabee
O
96def show_calendar(month, date, rel):
97 """
98 Show the calendar in rainbow mode
99 """
100 month = random_rainbow(month)
101 date = ' '.join([cycle_color(i) for i in date.split(' ')])
102 today = str(int(os.popen('date +\'%d\'').read().strip()))
103 # Display
104 printNicely(month)
105 printNicely(date)
106 for line in rel:
107 ary = line.split(' ')
108 ary = map(lambda x: color_func(c['CAL']['today'])(x)
109 if x == today
110 else color_func(c['CAL']['days'])(x)
111 , ary)
112 printNicely(' '.join(ary))
113
114
4cf86720
VNM
115def check_theme():
116 """
117 Check current theme and update if necessary
118 """
119 exists = db.theme_query()
120 themes = [t.theme_name for t in exists]
ddb1e615
VNM
121 if c['theme'] != themes[0]:
122 c['theme'] = themes[0]
4cf86720 123 # Determine path
ddb1e615 124 if c['theme'] == 'custom':
4cf86720
VNM
125 config = os.environ.get(
126 'HOME',
9c7342ca 127 os.environ.get('USERPROFILE',
4cf86720
VNM
128 '')) + os.sep + '.rainbow_config.json'
129 else:
15f3e155 130 config = os.path.dirname(__file__) + '/colorset/'+c['theme']+'.json'
4cf86720
VNM
131 # Load new config
132 data = load_config(config)
a5301bc0
VNM
133 if data:
134 for d in data:
135 c[d] = data[d]
9c7342ca 136 # Re-init color cycle
1fdd6a5c 137 g['cyc'] = init_cycle()
7500d90b 138
fe08f905
VNM
139
140def color_func(func_name):
141 """
142 Call color function base on name
143 """
144 pure = func_name.encode('utf8')
8124f3a8
VNM
145 if pure.startswith('term_') and pure[5:].isdigit():
146 return term_color(int(pure[5:]))
1face019 147 return globals()[pure]
fe08f905
VNM
148
149
7500d90b
VNM
150def draw(t, iot=False, keyword=None, fil=[], ig=[]):
151 """
152 Draw the rainbow
153 """
154
4cf86720 155 check_theme()
7500d90b
VNM
156 # Retrieve tweet
157 tid = t['id']
158 text = t['text']
159 screen_name = t['user']['screen_name']
160 name = t['user']['name']
161 created_at = t['created_at']
162 favorited = t['favorited']
163 date = parser.parse(created_at)
164 date = date - datetime.timedelta(seconds=time.timezone)
165 clock = date.strftime('%Y/%m/%d %H:%M:%S')
166
167 # Get expanded url
168 try:
169 expanded_url = []
170 url = []
171 urls = t['entities']['urls']
172 for u in urls:
173 expanded_url.append(u['expanded_url'])
174 url.append(u['url'])
175 except:
176 expanded_url = None
177 url = None
178
179 # Get media
180 try:
181 media_url = []
182 media = t['entities']['media']
183 for m in media:
184 media_url.append(m['media_url'])
185 except:
186 media_url = None
187
188 # Filter and ignore
189 screen_name = '@' + screen_name
190 if fil and screen_name not in fil:
191 return
192 if ig and screen_name in ig:
193 return
194
195 # Get rainbow id
196 res = db.tweet_to_rainbow_query(tid)
197 if not res:
198 db.tweet_store(tid)
199 res = db.tweet_to_rainbow_query(tid)
200 rid = res[0].rainbow_id
201
202 # Format info
c075e6dc
O
203 user = cycle_color(
204 name) + color_func(c['TWEET']['nick'])(' ' + screen_name + ' ')
205 meta = color_func(c['TWEET']['clock'])(
206 '[' + clock + '] ') + color_func(c['TWEET']['id'])('[id=' + str(rid) + '] ')
7500d90b 207 if favorited:
1a0ac1b8 208 meta = meta + color_func(c['TWEET']['favorited'])(u'\u2605')
7500d90b
VNM
209 tweet = text.split()
210 # Replace url
211 if expanded_url:
212 for index in range(len(expanded_url)):
213 tweet = map(
214 lambda x: expanded_url[index] if x == url[index] else x,
215 tweet)
216 # Highlight RT
c075e6dc
O
217 tweet = map(
218 lambda x: color_func(
219 c['TWEET']['rt'])(x) if x == 'RT' else x,
220 tweet)
7500d90b
VNM
221 # Highlight screen_name
222 tweet = map(lambda x: cycle_color(x) if x[0] == '@' else x, tweet)
223 # Highlight link
c075e6dc
O
224 tweet = map(
225 lambda x: color_func(
226 c['TWEET']['link'])(x) if x[
227 0:4] == 'http' else x,
228 tweet)
7500d90b
VNM
229 # Highlight search keyword
230 if keyword:
231 tweet = map(
632c6fa5 232 lambda x: color_func(c['TWEET']['keyword'])(x) if
7500d90b
VNM
233 ''.join(c for c in x if c.isalnum()).lower() == keyword.lower()
234 else x,
235 tweet
236 )
237 # Recreate tweet
238 tweet = ' '.join(tweet)
239
240 # Draw rainbow
241 line1 = u"{u:>{uw}}:".format(
242 u=user,
243 uw=len(user) + 2,
244 )
245 line2 = u"{c:>{cw}}".format(
246 c=meta,
247 cw=len(meta) + 2,
248 )
249 line3 = ' ' + tweet
250
251 printNicely('')
252 printNicely(line1)
253 printNicely(line2)
254 printNicely(line3)
255
256 # Display Image
257 if iot and media_url:
258 for mu in media_url:
17bc529d 259 try:
260 response = requests.get(mu)
261 image_to_display(StringIO(response.content))
262 except:
263 printNicely(red('Sorry, image link is broken'))
7500d90b
VNM
264
265
266def print_message(m):
267 """
268 Print direct message
269 """
270 sender_screen_name = '@' + m['sender_screen_name']
271 sender_name = m['sender']['name']
272 text = m['text']
273 recipient_screen_name = '@' + m['recipient_screen_name']
274 recipient_name = m['recipient']['name']
275 mid = m['id']
276 date = parser.parse(m['created_at'])
277 date = date - datetime.timedelta(seconds=time.timezone)
278 clock = date.strftime('%Y/%m/%d %H:%M:%S')
279
280 # Get rainbow id
281 res = db.message_to_rainbow_query(mid)
282 if not res:
283 db.message_store(mid)
284 res = db.message_to_rainbow_query(mid)
285 rid = res[0].rainbow_id
286
6fa09c14 287 # Draw
c075e6dc
O
288 sender = cycle_color(
289 sender_name) + color_func(c['MESSAGE']['sender'])(' ' + sender_screen_name + ' ')
290 recipient = cycle_color(recipient_name) + color_func(
291 c['MESSAGE']['recipient'])(
292 ' ' + recipient_screen_name + ' ')
632c6fa5 293 user = sender + color_func(c['MESSAGE']['to'])(' >>> ') + recipient
c075e6dc
O
294 meta = color_func(
295 c['MESSAGE']['clock'])(
296 '[' + clock + ']') + color_func(
297 c['MESSAGE']['id'])(
298 ' [message_id=' + str(rid) + '] ')
7500d90b
VNM
299 text = ''.join(map(lambda x: x + ' ' if x == '\n' else x, text))
300
301 line1 = u"{u:>{uw}}:".format(
302 u=user,
303 uw=len(user) + 2,
304 )
305 line2 = u"{c:>{cw}}".format(
306 c=meta,
307 cw=len(meta) + 2,
308 )
309
310 line3 = ' ' + text
311
312 printNicely('')
313 printNicely(line1)
314 printNicely(line2)
315 printNicely(line3)
316
317
318def show_profile(u, iot=False):
319 """
320 Show a profile
321 """
322 # Retrieve info
323 name = u['name']
324 screen_name = u['screen_name']
325 description = u['description']
326 profile_image_url = u['profile_image_url']
327 location = u['location']
328 url = u['url']
329 created_at = u['created_at']
330 statuses_count = u['statuses_count']
331 friends_count = u['friends_count']
332 followers_count = u['followers_count']
6fa09c14 333
7500d90b 334 # Create content
c075e6dc
O
335 statuses_count = color_func(
336 c['PROFILE']['statuses_count'])(
337 str(statuses_count) +
338 ' tweets')
339 friends_count = color_func(
340 c['PROFILE']['friends_count'])(
341 str(friends_count) +
342 ' following')
343 followers_count = color_func(
344 c['PROFILE']['followers_count'])(
345 str(followers_count) +
346 ' followers')
7500d90b 347 count = statuses_count + ' ' + friends_count + ' ' + followers_count
c075e6dc
O
348 user = cycle_color(
349 name) + color_func(c['PROFILE']['nick'])(' @' + screen_name + ' : ') + count
350 profile_image_raw_url = 'Profile photo: ' + \
351 color_func(c['PROFILE']['profile_image_url'])(profile_image_url)
7500d90b
VNM
352 description = ''.join(
353 map(lambda x: x + ' ' * 4 if x == '\n' else x, description))
632c6fa5
O
354 description = color_func(c['PROFILE']['description'])(description)
355 location = 'Location : ' + color_func(c['PROFILE']['location'])(location)
356 url = 'URL : ' + (color_func(c['PROFILE']['url'])(url) if url else '')
7500d90b
VNM
357 date = parser.parse(created_at)
358 date = date - datetime.timedelta(seconds=time.timezone)
359 clock = date.strftime('%Y/%m/%d %H:%M:%S')
632c6fa5 360 clock = 'Join at ' + color_func(c['PROFILE']['clock'])(clock)
6fa09c14 361
7500d90b
VNM
362 # Format
363 line1 = u"{u:>{uw}}".format(
364 u=user,
365 uw=len(user) + 2,
366 )
367 line2 = u"{p:>{pw}}".format(
368 p=profile_image_raw_url,
369 pw=len(profile_image_raw_url) + 4,
370 )
371 line3 = u"{d:>{dw}}".format(
372 d=description,
373 dw=len(description) + 4,
374 )
375 line4 = u"{l:>{lw}}".format(
376 l=location,
377 lw=len(location) + 4,
378 )
379 line5 = u"{u:>{uw}}".format(
380 u=url,
381 uw=len(url) + 4,
382 )
383 line6 = u"{c:>{cw}}".format(
384 c=clock,
385 cw=len(clock) + 4,
386 )
6fa09c14 387
7500d90b
VNM
388 # Display
389 printNicely('')
390 printNicely(line1)
391 if iot:
17bc529d 392 try:
393 response = requests.get(profile_image_url)
394 image_to_display(StringIO(response.content), 2, 20)
395 except:
396 pass
7500d90b
VNM
397 else:
398 printNicely(line2)
399 for line in [line3, line4, line5, line6]:
400 printNicely(line)
401 printNicely('')
402
403
404def print_trends(trends):
405 """
406 Display topics
407 """
632c6fa5 408 for topic in trends[:c['TREND_MAX']]:
7500d90b
VNM
409 name = topic['name']
410 url = topic['url']
8394e34b 411 line = cycle_color(name) + ': ' + color_func(c['TREND']['url'])(url)
7500d90b
VNM
412 printNicely(line)
413 printNicely('')
2d341029
O
414
415
416def print_list(group):
417 """
418 Display a list
419 """
420 for g in group:
421 # Format
422 name = g['name']
423 name = color_func(c['GROUP']['name'])(name + ' : ')
424 member = str(g['member_count'])
425 member = color_func(c['GROUP']['member'])(member+' member')
426 subscriber = str(g['subscriber_count'])
427 subscriber = color_func(c['GROUP']['subscriber'])(subscriber+' subscriber')
428 description = g['description'].strip()
429 description = color_func(c['GROUP']['description'])(description)
430 mode = g['mode']
431 mode = color_func(c['GROUP']['mode'])('Type: '+mode)
432 created_at = g['created_at']
433 date = parser.parse(created_at)
434 date = date - datetime.timedelta(seconds=time.timezone)
435 clock = date.strftime('%Y/%m/%d %H:%M:%S')
436 clock = 'Created at ' + color_func(c['GROUP']['clock'])(clock)
437
438 # Save to db
439 db.list_store(g['id'],g['name'])
440
441 # Create lines
442 line1 = ' '*2 + name + member + ' ' + subscriber
443 line2 = ' '*4 + description
444 line3 = ' '*4 + mode
445 line4 = ' '*4 + clock
446
447 # Display
448 printNicely('')
449 printNicely(line1)
450 printNicely(line2)
451 printNicely(line3)
452 printNicely(line4)
453
454 printNicely('')
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491