add debug option
[rainbowstream.git] / rainbowstream / draw.py
CommitLineData
e9f5200b 1import random
bcb5518e 2import textwrap
e9f5200b 3import itertools
7500d90b 4import requests
8b3456f9 5import locale
6import arrow
59262e95 7import re
67c663f8 8import os
7500d90b 9
2da50cc4 10from twitter.util import printNicely
e9f5200b
VNM
11from functools import wraps
12from pyfiglet import figlet_format
7500d90b 13from dateutil import parser
2da50cc4 14from .c_image import *
7500d90b
VNM
15from .colors import *
16from .config import *
c3bab4ef 17from .py3patch import *
18
99b52f5f
O
19# Draw global variables
20dg = {}
1fdd6a5c 21
422dd385 22
e9f5200b
VNM
23def init_cycle():
24 """
25 Init the cycle
26 """
27 colors_shuffle = [globals()[i.encode('utf8')]
fa6e062d
O
28 if not str(i).isdigit()
29 else term_color(int(i))
422dd385 30 for i in c['CYCLE_COLOR']]
5f22104f 31 return itertools.cycle(colors_shuffle)
1fdd6a5c 32
e9f5200b 33
59262e95 34def start_cycle():
2359c276
VNM
35 """
36 Notify from rainbow
37 """
99b52f5f
O
38 dg['cyc'] = init_cycle()
39 dg['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')]
fa6e062d
O
47 if not str(i).isdigit()
48 else term_color(int(i))
422dd385 49 for i in c['CYCLE_COLOR']]
5f22104f 50 colored = [colors_shuffle[i % 7](s[i]) for i in xrange(len(s))]
c3bab4ef 51 return ''.join(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')]
fa6e062d
O
59 if not str(i).isdigit()
60 else term_color(int(i))
422dd385 61 for i in c['CYCLE_COLOR']]
5f22104f 62 colored = [random.choice(colors_shuffle)(i) for i in s]
c3bab4ef 63 return ''.join(colored)
e9f5200b
VNM
64
65
66def Memoize(func):
67 """
68 Memoize decorator
69 """
e9f5200b
VNM
70 @wraps(func)
71 def wrapper(*args):
99b52f5f
O
72 if args not in dg['cache']:
73 dg['cache'][args] = func(*args)
74 return dg['cache'][args]
e9f5200b
VNM
75 return wrapper
76
77
78@Memoize
79def cycle_color(s):
80 """
81 Cycle the colors_shuffle
82 """
99b52f5f 83 return next(dg['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(
99b52f5f 92 [next(dg['cyc'])(i) for i in fi.split('\n')]
e9f5200b
VNM
93 ))
94
95
92685d21 96def check_config():
ceec8593 97 """
98 Check if config is changed
99 """
100 changed = False
101 data = get_all_config()
102 for key in c:
103 if key in data:
104 if data[key] != c[key]:
105 changed = True
106 if changed:
107 reload_config()
108
109
110def validate_theme(theme):
111 """
112 Validate a theme exists or not
113 """
114 # Theme changed check
115 files = os.listdir(os.path.dirname(__file__) + '/colorset')
116 themes = [f.split('.')[0] for f in files if f.split('.')[-1] == 'json']
117 return theme in themes
92685d21 118
119
99b52f5f 120def reload_theme(value, prev):
4cf86720
VNM
121 """
122 Check current theme and update if necessary
123 """
99b52f5f 124 if value != prev:
1f2f6159 125 config = os.path.dirname(
99b52f5f 126 __file__) + '/colorset/' + value + '.json'
4cf86720
VNM
127 # Load new config
128 data = load_config(config)
a5301bc0
VNM
129 if data:
130 for d in data:
131 c[d] = data[d]
99b52f5f 132 # Restart color cycle and update config
ceec8593 133 start_cycle()
99b52f5f
O
134 set_config('THEME', value)
135 return value
136 return prev
7500d90b 137
fe08f905
VNM
138
139def color_func(func_name):
140 """
141 Call color function base on name
142 """
fa6e062d
O
143 if str(func_name).isdigit():
144 return term_color(int(func_name))
c3bab4ef 145 return globals()[func_name]
fe08f905
VNM
146
147
99cd1fba 148def draw(t, keyword=None, humanize=True, noti=False, fil=[], ig=[]):
7500d90b
VNM
149 """
150 Draw the rainbow
151 """
99b52f5f 152 # Check config
92685d21 153 check_config()
c37c04a9 154
7500d90b
VNM
155 # Retrieve tweet
156 tid = t['id']
606def7e 157 text = t['text']
7500d90b
VNM
158 screen_name = t['user']['screen_name']
159 name = t['user']['name']
160 created_at = t['created_at']
161 favorited = t['favorited']
318cdd67
O
162 retweet_count = t['retweet_count']
163 favorite_count = t['favorite_count']
7500d90b 164 date = parser.parse(created_at)
8b3456f9 165 date = arrow.get(date).to('local')
166 if humanize:
167 lang, encode = locale.getdefaultlocale()
168 clock = arrow.get(date).to('local').humanize(locale=lang)
169 else:
170 try:
171 clock_format = c['FORMAT']['TWEET']['CLOCK_FORMAT']
172 except:
173 clock_format = '%Y/%m/%d %H:%M:%S'
174 clock = date.datetime.strftime(clock_format)
7500d90b 175
606def7e
BR
176 # Pull extended retweet text
177 try:
18df6e7f
O
178 text = 'RT @' + t['retweeted_status']['user']['screen_name'] + ': ' +\
179 t['retweeted_status']['text']
38a6dc30
O
180 # Display as a notification
181 target = t['retweeted_status']['user']['screen_name']
182 if all([target == c['original_name'], not noti]):
183 # Add to evens for 'notification' command
184 t['event'] = 'retweet'
185 c['events'].append(t)
186 notify_retweet(t)
187 return
606def7e
BR
188 except:
189 pass
190
18df6e7f 191 # Unescape HTML character
606def7e
BR
192 text = unescape(text)
193
7500d90b
VNM
194 # Get expanded url
195 try:
196 expanded_url = []
197 url = []
198 urls = t['entities']['urls']
199 for u in urls:
200 expanded_url.append(u['expanded_url'])
201 url.append(u['url'])
202 except:
203 expanded_url = None
204 url = None
205
206 # Get media
207 try:
208 media_url = []
209 media = t['entities']['media']
210 for m in media:
211 media_url.append(m['media_url'])
212 except:
213 media_url = None
214
215 # Filter and ignore
37cf396a 216 mytweet = screen_name == c['original_name']
7500d90b 217 screen_name = '@' + screen_name
e3927852
O
218 fil = list(set((fil or []) + c['ONLY_LIST']))
219 ig = list(set((ig or []) + c['IGNORE_LIST']))
7500d90b
VNM
220 if fil and screen_name not in fil:
221 return
222 if ig and screen_name in ig:
223 return
224
225 # Get rainbow id
99b52f5f
O
226 if tid not in c['tweet_dict']:
227 c['tweet_dict'].append(tid)
228 rid = len(c['tweet_dict']) - 1
229 else:
230 rid = c['tweet_dict'].index(tid)
7500d90b
VNM
231
232 # Format info
8c7ae594 233 name = cycle_color(name)
571ea706
O
234 if mytweet:
235 nick = color_func(c['TWEET']['mynick'])(screen_name)
236 else:
237 nick = color_func(c['TWEET']['nick'])(screen_name)
0d9977c7
O
238 clock = clock
239 id = str(rid)
8c7ae594 240 fav = ''
7500d90b 241 if favorited:
8c7ae594
O
242 fav = color_func(c['TWEET']['favorited'])(u'\u2605')
243
7500d90b
VNM
244 tweet = text.split()
245 # Replace url
246 if expanded_url:
13e6b275 247 for index in xrange(len(expanded_url)):
c3bab4ef 248 tweet = lmap(
8141aca6 249 lambda x: expanded_url[index]
250 if x == url[index]
251 else x,
7500d90b
VNM
252 tweet)
253 # Highlight RT
c3bab4ef 254 tweet = lmap(
8141aca6 255 lambda x: color_func(c['TWEET']['rt'])(x)
256 if x == 'RT'
257 else x,
c075e6dc 258 tweet)
7500d90b 259 # Highlight screen_name
c3bab4ef 260 tweet = lmap(lambda x: cycle_color(x) if x[0] == '@' else x, tweet)
7500d90b 261 # Highlight link
c3bab4ef 262 tweet = lmap(
8141aca6 263 lambda x: color_func(c['TWEET']['link'])(x)
37cf396a 264 if x.startswith('http')
8141aca6 265 else x,
c075e6dc 266 tweet)
4c025026 267 # Highlight hashtag
268 tweet = lmap(
8141aca6 269 lambda x: color_func(c['TWEET']['hashtag'])(x)
270 if x.startswith('#')
271 else x,
4c025026 272 tweet)
37cf396a
O
273 # Highlight my tweet
274 if mytweet:
275 tweet = [color_func(c['TWEET']['mytweet'])(x)
276 for x in tweet
277 if not any([
278 x == 'RT',
279 x.startswith('http'),
280 x.startswith('#')])
281 ]
59262e95 282 # Highlight keyword
7500d90b 283 tweet = ' '.join(tweet)
59262e95 284 if keyword:
a8c5fce4 285 roj = re.search(keyword, tweet, re.IGNORECASE)
59262e95
O
286 if roj:
287 occur = roj.group()
288 ary = tweet.split(occur)
b13c6a0d 289 delimiter = color_func(c['TWEET']['keyword'])(occur)
290 tweet = delimiter.join(ary)
7500d90b 291
8c7ae594 292 # Load config formater
318cdd67 293 formater = ''
8c7ae594
O
294 try:
295 formater = c['FORMAT']['TWEET']['DISPLAY']
7c437a0f
O
296 formater = name.join(formater.split('#name'))
297 formater = nick.join(formater.split('#nick'))
298 formater = fav.join(formater.split('#fav'))
299 formater = tweet.join(formater.split('#tweet'))
0d9977c7 300 # Change clock word
03c0d30b 301 word = [wo for wo in formater.split() if '#clock' in wo][0]
8141aca6 302 delimiter = color_func(c['TWEET']['clock'])(
303 clock.join(word.split('#clock')))
0d9977c7
O
304 formater = delimiter.join(formater.split(word))
305 # Change id word
03c0d30b 306 word = [wo for wo in formater.split() if '#id' in wo][0]
0d9977c7
O
307 delimiter = color_func(c['TWEET']['id'])(id.join(word.split('#id')))
308 formater = delimiter.join(formater.split(word))
318cdd67 309 # Change retweet count word
03c0d30b 310 word = [wo for wo in formater.split() if '#rt_count' in wo][0]
318cdd67
O
311 delimiter = color_func(c['TWEET']['retweet_count'])(
312 str(retweet_count).join(word.split('#rt_count')))
313 formater = delimiter.join(formater.split(word))
314 # Change favorites count word
03c0d30b 315 word = [wo for wo in formater.split() if '#fa_count' in wo][0]
318cdd67
O
316 delimiter = color_func(c['TWEET']['favorite_count'])(
317 str(favorite_count).join(word.split('#fa_count')))
318 formater = delimiter.join(formater.split(word))
8c7ae594 319 except:
318cdd67 320 pass
7500d90b 321
99cd1fba
O
322 # Add spaces in begining of line if this is inside a notification
323 if noti:
324 formater = '\n '.join(formater.split('\n'))
38a6dc30
O
325 # Reformat
326 if formater.startswith('\n'):
327 formater = formater[1:]
99cd1fba 328
8c7ae594
O
329 # Draw
330 printNicely(formater)
7500d90b
VNM
331
332 # Display Image
fe9bb33b 333 if c['IMAGE_ON_TERM'] and media_url:
7500d90b 334 for mu in media_url:
17bc529d 335 try:
336 response = requests.get(mu)
77f1d210 337 image_to_display(BytesIO(response.content))
338 except Exception:
17bc529d 339 printNicely(red('Sorry, image link is broken'))
7500d90b
VNM
340
341
67c663f8
O
342def print_threads(d):
343 """
344 Print threads of messages
345 """
346 id = 1
347 rel = {}
348 for partner in d:
349 messages = d[partner]
350 count = len(messages)
351 screen_name = '@' + partner[0]
352 name = partner[1]
353 screen_name = color_func(c['MESSAGE']['partner'])(screen_name)
354 name = cycle_color(name)
03c0d30b 355 thread_id = color_func(c['MESSAGE']['id'])('thread_id:' + str(id))
356 line = ' ' * 2 + name + ' ' + screen_name + \
67c663f8
O
357 ' (' + str(count) + ' message) ' + thread_id
358 printNicely(line)
359 rel[id] = partner
360 id += 1
361 dg['thread'] = d
362 return rel
363
364
365def print_thread(partner, me_nick, me_name):
366 """
367 Print a thread of messages
368 """
369 # Sort messages by time
370 messages = dg['thread'][partner]
03c0d30b 371 messages.sort(key=lambda x: parser.parse(x['created_at']))
372 # Use legacy display on non-ascii text message
bcb5518e 373 ms = [m['text'] for m in messages]
374 ums = [m for m in ms if not all(ord(c) < 128 for c in m)]
375 if ums:
03c0d30b 376 for m in messages:
377 print_message(m)
378 printNicely('')
379 return
380 # Print the first line
381 dg['frame_margin'] = margin = 2
382 partner_nick = partner[0]
383 partner_name = partner[1]
384 left_size = len(partner_nick) + len(partner_name) + 2
385 right_size = len(me_nick) + len(me_name) + 2
386 partner_nick = color_func(c['MESSAGE']['partner'])('@' + partner_nick)
387 partner_name = cycle_color(partner_name)
67c663f8
O
388 me_screen_name = color_func(c['MESSAGE']['me'])('@' + me_nick)
389 me_name = cycle_color(me_name)
03c0d30b 390 left = ' ' * margin + partner_name + ' ' + partner_nick
67c663f8
O
391 right = me_name + ' ' + me_screen_name + ' ' * margin
392 h, w = os.popen('stty size', 'r').read().split()
393 w = int(w)
03c0d30b 394 line = '{}{}{}'.format(
395 left, ' ' * (w - left_size - right_size - 2 * margin), right)
67c663f8
O
396 printNicely('')
397 printNicely(line)
398 printNicely('')
67c663f8
O
399 # Print messages
400 for m in messages:
401 if m['sender_screen_name'] == me_nick:
402 print_right_message(m)
403 elif m['recipient_screen_name'] == me_nick:
404 print_left_message(m)
405
406
407def print_right_message(m):
408 """
409 Print a message on the right of screen
410 """
411 h, w = os.popen('stty size', 'r').read().split()
412 w = int(w)
03c0d30b 413 frame_width = w // 3 - dg['frame_margin']
37cf396a 414 frame_width = max(c['THREAD_MIN_WIDTH'], frame_width)
03c0d30b 415 step = frame_width - 2 * dg['frame_margin']
bcb5518e 416 slicing = textwrap.wrap(m['text'], step)
03c0d30b 417 spaces = w - frame_width - dg['frame_margin']
67c663f8 418 dotline = ' ' * spaces + '-' * frame_width
03c0d30b 419 dotline = color_func(c['MESSAGE']['me_frame'])(dotline)
223d2e05 420 # Draw the frame
67c663f8
O
421 printNicely(dotline)
422 for line in slicing:
423 fill = step - len(line)
424 screen_line = ' ' * spaces + '| ' + line + ' ' * fill + ' '
425 if slicing[-1] == line:
426 screen_line = screen_line + ' >'
427 else:
428 screen_line = screen_line + '|'
03c0d30b 429 screen_line = color_func(c['MESSAGE']['me_frame'])(screen_line)
67c663f8
O
430 printNicely(screen_line)
431 printNicely(dotline)
03c0d30b 432 # Format clock
223d2e05
O
433 date = parser.parse(m['created_at'])
434 date = arrow.get(date).to('local').datetime
435 clock_format = '%Y/%m/%d %H:%M:%S'
436 try:
437 clock_format = c['FORMAT']['MESSAGE']['CLOCK_FORMAT']
438 except:
439 pass
440 clock = date.strftime(clock_format)
03c0d30b 441 # Format id
223d2e05
O
442 if m['id'] not in c['message_dict']:
443 c['message_dict'].append(m['id'])
444 rid = len(c['message_dict']) - 1
445 else:
446 rid = c['message_dict'].index(m['id'])
03c0d30b 447 id = str(rid)
448 # Print meta
449 formater = ''
450 try:
451 virtual_meta = formater = c['THREAD_META_RIGHT']
452 virtual_meta = clock.join(virtual_meta.split('#clock'))
453 virtual_meta = id.join(virtual_meta.split('#id'))
454 # Change clock word
455 word = [wo for wo in formater.split() if '#clock' in wo][0]
456 delimiter = color_func(c['MESSAGE']['clock'])(
457 clock.join(word.split('#clock')))
458 formater = delimiter.join(formater.split(word))
459 # Change id word
460 word = [wo for wo in formater.split() if '#id' in wo][0]
461 delimiter = color_func(c['MESSAGE']['id'])(id.join(word.split('#id')))
462 formater = delimiter.join(formater.split(word))
463 except Exception:
464 printNicely(red('Wrong format in config.'))
465 return
466 meta = formater
467 line = ' ' * (w - len(virtual_meta) - dg['frame_margin']) + meta
223d2e05 468 printNicely(line)
67c663f8
O
469
470
471def print_left_message(m):
472 """
473 Print a message on the left of screen
474 """
475 h, w = os.popen('stty size', 'r').read().split()
476 w = int(w)
03c0d30b 477 frame_width = w // 3 - dg['frame_margin']
37cf396a 478 frame_width = max(c['THREAD_MIN_WIDTH'], frame_width)
03c0d30b 479 step = frame_width - 2 * dg['frame_margin']
bcb5518e 480 slicing = textwrap.wrap(m['text'], step)
03c0d30b 481 spaces = dg['frame_margin']
67c663f8 482 dotline = ' ' * spaces + '-' * frame_width
03c0d30b 483 dotline = color_func(c['MESSAGE']['partner_frame'])(dotline)
223d2e05 484 # Draw the frame
67c663f8
O
485 printNicely(dotline)
486 for line in slicing:
487 fill = step - len(line)
488 screen_line = ' ' + line + ' ' * fill + ' |'
489 if slicing[-1] == line:
03c0d30b 490 screen_line = ' ' * (spaces - 1) + '< ' + screen_line
67c663f8
O
491 else:
492 screen_line = ' ' * spaces + '|' + screen_line
03c0d30b 493 screen_line = color_func(c['MESSAGE']['partner_frame'])(screen_line)
67c663f8
O
494 printNicely(screen_line)
495 printNicely(dotline)
03c0d30b 496 # Format clock
223d2e05
O
497 date = parser.parse(m['created_at'])
498 date = arrow.get(date).to('local').datetime
499 clock_format = '%Y/%m/%d %H:%M:%S'
500 try:
501 clock_format = c['FORMAT']['MESSAGE']['CLOCK_FORMAT']
502 except:
503 pass
504 clock = date.strftime(clock_format)
03c0d30b 505 # Format id
223d2e05
O
506 if m['id'] not in c['message_dict']:
507 c['message_dict'].append(m['id'])
508 rid = len(c['message_dict']) - 1
509 else:
510 rid = c['message_dict'].index(m['id'])
03c0d30b 511 id = str(rid)
512 # Print meta
513 formater = ''
514 try:
515 virtual_meta = formater = c['THREAD_META_LEFT']
516 virtual_meta = clock.join(virtual_meta.split('#clock'))
517 virtual_meta = id.join(virtual_meta.split('#id'))
518 # Change clock word
519 word = [wo for wo in formater.split() if '#clock' in wo][0]
520 delimiter = color_func(c['MESSAGE']['clock'])(
521 clock.join(word.split('#clock')))
522 formater = delimiter.join(formater.split(word))
523 # Change id word
524 word = [wo for wo in formater.split() if '#id' in wo][0]
525 delimiter = color_func(c['MESSAGE']['id'])(id.join(word.split('#id')))
526 formater = delimiter.join(formater.split(word))
527 except Exception:
528 printNicely(red('Wrong format in config.'))
529 return
530 meta = formater
531 line = ' ' * dg['frame_margin'] + meta
223d2e05 532 printNicely(line)
67c663f8
O
533
534
4dc385b5 535def print_message(m):
7500d90b
VNM
536 """
537 Print direct message
538 """
c37c04a9 539 # Retrieve message
7500d90b
VNM
540 sender_screen_name = '@' + m['sender_screen_name']
541 sender_name = m['sender']['name']
b2cde062 542 text = unescape(m['text'])
7500d90b
VNM
543 recipient_screen_name = '@' + m['recipient_screen_name']
544 recipient_name = m['recipient']['name']
545 mid = m['id']
546 date = parser.parse(m['created_at'])
8b3456f9 547 date = arrow.get(date).to('local').datetime
8c7ae594
O
548 clock_format = '%Y/%m/%d %H:%M:%S'
549 try:
550 clock_format = c['FORMAT']['MESSAGE']['CLOCK_FORMAT']
551 except:
552 pass
553 clock = date.strftime(clock_format)
7500d90b
VNM
554
555 # Get rainbow id
99b52f5f
O
556 if mid not in c['message_dict']:
557 c['message_dict'].append(mid)
558 rid = len(c['message_dict']) - 1
559 else:
560 rid = c['message_dict'].index(mid)
7500d90b 561
6fa09c14 562 # Draw
8c7ae594
O
563 sender_name = cycle_color(sender_name)
564 sender_nick = color_func(c['MESSAGE']['sender'])(sender_screen_name)
565 recipient_name = cycle_color(recipient_name)
0d9977c7
O
566 recipient_nick = color_func(
567 c['MESSAGE']['recipient'])(recipient_screen_name)
8c7ae594 568 to = color_func(c['MESSAGE']['to'])('>>>')
0d9977c7
O
569 clock = clock
570 id = str(rid)
8c7ae594 571
c3bab4ef 572 text = ''.join(lmap(lambda x: x + ' ' if x == '\n' else x, text))
7500d90b 573
8c7ae594
O
574 # Load config formater
575 try:
576 formater = c['FORMAT']['MESSAGE']['DISPLAY']
0d9977c7
O
577 formater = sender_name.join(formater.split("#sender_name"))
578 formater = sender_nick.join(formater.split("#sender_nick"))
579 formater = to.join(formater.split("#to"))
580 formater = recipient_name.join(formater.split("#recipient_name"))
581 formater = recipient_nick.join(formater.split("#recipient_nick"))
582 formater = text.join(formater.split("#message"))
583 # Change clock word
03c0d30b 584 word = [wo for wo in formater.split() if '#clock' in wo][0]
8141aca6 585 delimiter = color_func(c['MESSAGE']['clock'])(
586 clock.join(word.split('#clock')))
0d9977c7
O
587 formater = delimiter.join(formater.split(word))
588 # Change id word
03c0d30b 589 word = [wo for wo in formater.split() if '#id' in wo][0]
0d9977c7
O
590 delimiter = color_func(c['MESSAGE']['id'])(id.join(word.split('#id')))
591 formater = delimiter.join(formater.split(word))
8c7ae594
O
592 except:
593 printNicely(red('Wrong format in config.'))
594 return
595
596 # Draw
597 printNicely(formater)
7500d90b
VNM
598
599
38a6dc30
O
600def notify_retweet(t):
601 """
602 Notify a retweet
603 """
604 source = t['user']
605 created_at = t['created_at']
606 # Format
607 source_user = cycle_color(source['name']) + \
608 color_func(c['NOTIFICATION']['source_nick'])(
609 ' @' + source['screen_name'])
610 notify = color_func(c['NOTIFICATION']['notify'])(
611 'retweeted your tweet')
612 date = parser.parse(created_at)
613 date = arrow.get(date).to('local')
614 lang, encode = locale.getdefaultlocale()
615 clock = arrow.get(date).to('local').humanize(locale=lang)
616 clock = color_func(c['NOTIFICATION']['clock'])(clock)
617 meta = c['NOTIFY_FORMAT']
618 meta = source_user.join(meta.split('#source_user'))
619 meta = notify.join(meta.split('#notify'))
620 meta = clock.join(meta.split('#clock'))
621 # Output
622 printNicely('')
623 printNicely(meta)
624 draw(t=t['retweeted_status'], noti=True)
625
626
99cd1fba
O
627def notify_favorite(e):
628 """
629 Notify a favorite event
630 """
631 # Retrieve info
632 target = e['target']
633 if target['screen_name'] != c['original_name']:
634 return
635 source = e['source']
636 target_object = e['target_object']
637 created_at = e['created_at']
638 # Format
639 source_user = cycle_color(source['name']) + \
640 color_func(c['NOTIFICATION']['source_nick'])(
641 ' @' + source['screen_name'])
38a6dc30
O
642 notify = color_func(c['NOTIFICATION']['notify'])(
643 'favorited your tweet')
99cd1fba
O
644 date = parser.parse(created_at)
645 date = arrow.get(date).to('local')
646 lang, encode = locale.getdefaultlocale()
647 clock = arrow.get(date).to('local').humanize(locale=lang)
648 clock = color_func(c['NOTIFICATION']['clock'])(clock)
38a6dc30
O
649 meta = c['NOTIFY_FORMAT']
650 meta = source_user.join(meta.split('#source_user'))
651 meta = notify.join(meta.split('#notify'))
652 meta = clock.join(meta.split('#clock'))
99cd1fba
O
653 # Output
654 printNicely('')
655 printNicely(meta)
656 draw(t=target_object, noti=True)
657
658
659def notify_unfavorite(e):
660 """
661 Notify a unfavorite event
662 """
663 # Retrieve info
664 target = e['target']
665 if target['screen_name'] != c['original_name']:
666 return
667 source = e['source']
668 target_object = e['target_object']
669 created_at = e['created_at']
670 # Format
671 source_user = cycle_color(source['name']) + \
672 color_func(c['NOTIFICATION']['source_nick'])(
673 ' @' + source['screen_name'])
674 notify = color_func(c['NOTIFICATION']['notify'])(
38a6dc30 675 'unfavorited your tweet')
99cd1fba
O
676 date = parser.parse(created_at)
677 date = arrow.get(date).to('local')
678 lang, encode = locale.getdefaultlocale()
679 clock = arrow.get(date).to('local').humanize(locale=lang)
680 clock = color_func(c['NOTIFICATION']['clock'])(clock)
38a6dc30
O
681 meta = c['NOTIFY_FORMAT']
682 meta = source_user.join(meta.split('#source_user'))
683 meta = notify.join(meta.split('#notify'))
684 meta = clock.join(meta.split('#clock'))
99cd1fba
O
685 # Output
686 printNicely('')
687 printNicely(meta)
688 draw(t=target_object, noti=True)
689
690
691def notify_follow(e):
692 """
693 Notify a follow event
694 """
695 # Retrieve info
696 target = e['target']
697 if target['screen_name'] != c['original_name']:
698 return
699 source = e['source']
700 created_at = e['created_at']
701 # Format
702 source_user = cycle_color(source['name']) + \
703 color_func(c['NOTIFICATION']['source_nick'])(
704 ' @' + source['screen_name'])
38a6dc30
O
705 notify = color_func(c['NOTIFICATION']['notify'])(
706 'followed you')
99cd1fba
O
707 date = parser.parse(created_at)
708 date = arrow.get(date).to('local')
709 lang, encode = locale.getdefaultlocale()
710 clock = arrow.get(date).to('local').humanize(locale=lang)
711 clock = color_func(c['NOTIFICATION']['clock'])(clock)
38a6dc30
O
712 meta = c['NOTIFY_FORMAT']
713 meta = source_user.join(meta.split('#source_user'))
714 meta = notify.join(meta.split('#notify'))
715 meta = clock.join(meta.split('#clock'))
99cd1fba
O
716 # Output
717 printNicely('')
718 printNicely(meta)
719
720
721def notify_list_member_added(e):
722 """
723 Notify a list_member_added event
724 """
725 # Retrieve info
726 target = e['target']
727 if target['screen_name'] != c['original_name']:
728 return
729 source = e['source']
730 target_object = [e['target_object']] # list of Twitter list
731 created_at = e['created_at']
732 # Format
733 source_user = cycle_color(source['name']) + \
734 color_func(c['NOTIFICATION']['source_nick'])(
735 ' @' + source['screen_name'])
38a6dc30
O
736 notify = color_func(c['NOTIFICATION']['notify'])(
737 'added you to a list')
99cd1fba
O
738 date = parser.parse(created_at)
739 date = arrow.get(date).to('local')
740 lang, encode = locale.getdefaultlocale()
741 clock = arrow.get(date).to('local').humanize(locale=lang)
742 clock = color_func(c['NOTIFICATION']['clock'])(clock)
38a6dc30
O
743 meta = c['NOTIFY_FORMAT']
744 meta = source_user.join(meta.split('#source_user'))
745 meta = notify.join(meta.split('#notify'))
746 meta = clock.join(meta.split('#clock'))
99cd1fba
O
747 # Output
748 printNicely('')
749 printNicely(meta)
750 print_list(target_object, noti=True)
751
752
753def notify_list_member_removed(e):
754 """
755 Notify a list_member_removed event
756 """
757 # Retrieve info
758 target = e['target']
759 if target['screen_name'] != c['original_name']:
760 return
761 source = e['source']
762 target_object = [e['target_object']] # list of Twitter list
763 created_at = e['created_at']
764 # Format
765 source_user = cycle_color(source['name']) + \
766 color_func(c['NOTIFICATION']['source_nick'])(
767 ' @' + source['screen_name'])
768 notify = color_func(c['NOTIFICATION']['notify'])(
38a6dc30 769 'removed you from a list')
99cd1fba
O
770 date = parser.parse(created_at)
771 date = arrow.get(date).to('local')
772 lang, encode = locale.getdefaultlocale()
773 clock = arrow.get(date).to('local').humanize(locale=lang)
774 clock = color_func(c['NOTIFICATION']['clock'])(clock)
38a6dc30
O
775 meta = c['NOTIFY_FORMAT']
776 meta = source_user.join(meta.split('#source_user'))
777 meta = notify.join(meta.split('#notify'))
778 meta = clock.join(meta.split('#clock'))
99cd1fba
O
779 # Output
780 printNicely('')
781 printNicely(meta)
782 print_list(target_object, noti=True)
783
784
785def notify_list_user_subscribed(e):
786 """
787 Notify a list_user_subscribed event
788 """
789 # Retrieve info
790 target = e['target']
791 if target['screen_name'] != c['original_name']:
792 return
793 source = e['source']
794 target_object = [e['target_object']] # list of Twitter list
795 created_at = e['created_at']
796 # Format
797 source_user = cycle_color(source['name']) + \
798 color_func(c['NOTIFICATION']['source_nick'])(
799 ' @' + source['screen_name'])
800 notify = color_func(c['NOTIFICATION']['notify'])(
38a6dc30 801 'subscribed to your list')
99cd1fba
O
802 date = parser.parse(created_at)
803 date = arrow.get(date).to('local')
804 lang, encode = locale.getdefaultlocale()
805 clock = arrow.get(date).to('local').humanize(locale=lang)
806 clock = color_func(c['NOTIFICATION']['clock'])(clock)
38a6dc30
O
807 meta = c['NOTIFY_FORMAT']
808 meta = source_user.join(meta.split('#source_user'))
809 meta = notify.join(meta.split('#notify'))
810 meta = clock.join(meta.split('#clock'))
99cd1fba
O
811 # Output
812 printNicely('')
813 printNicely(meta)
814 print_list(target_object, noti=True)
815
816
817def notify_list_user_unsubscribed(e):
818 """
819 Notify a list_user_unsubscribed event
820 """
821 # Retrieve info
822 target = e['target']
823 if target['screen_name'] != c['original_name']:
824 return
825 source = e['source']
826 target_object = [e['target_object']] # list of Twitter list
827 created_at = e['created_at']
828 # Format
829 source_user = cycle_color(source['name']) + \
830 color_func(c['NOTIFICATION']['source_nick'])(
831 ' @' + source['screen_name'])
832 notify = color_func(c['NOTIFICATION']['notify'])(
38a6dc30 833 'unsubscribed from your list')
99cd1fba
O
834 date = parser.parse(created_at)
835 date = arrow.get(date).to('local')
836 lang, encode = locale.getdefaultlocale()
837 clock = arrow.get(date).to('local').humanize(locale=lang)
838 clock = color_func(c['NOTIFICATION']['clock'])(clock)
38a6dc30
O
839 meta = c['NOTIFY_FORMAT']
840 meta = source_user.join(meta.split('#source_user'))
841 meta = notify.join(meta.split('#notify'))
842 meta = clock.join(meta.split('#clock'))
99cd1fba
O
843 # Output
844 printNicely('')
845 printNicely(meta)
846 print_list(target_object, noti=True)
847
848
11858241
O
849def nothing(e):
850 """
851 Do nothing for other event
852 """
853 return
854
855
99cd1fba
O
856def print_event(e):
857 """
858 Notify an event
859 """
860 event_dict = {
38a6dc30 861 'retweet': notify_retweet,
99cd1fba
O
862 'favorite': notify_favorite,
863 'unfavorite': notify_unfavorite,
864 'follow': notify_follow,
865 'list_member_added': notify_list_member_added,
866 'list_member_removed': notify_list_member_removed,
867 'list_user_subscribed': notify_list_user_subscribed,
868 'list_user_unsubscribed': notify_list_user_unsubscribed,
869 }
7a8a52fc 870 event_dict.get(e['event'], nothing)(e)
99cd1fba
O
871
872
fe9bb33b 873def show_profile(u):
7500d90b
VNM
874 """
875 Show a profile
876 """
877 # Retrieve info
878 name = u['name']
879 screen_name = u['screen_name']
880 description = u['description']
881 profile_image_url = u['profile_image_url']
882 location = u['location']
883 url = u['url']
884 created_at = u['created_at']
885 statuses_count = u['statuses_count']
886 friends_count = u['friends_count']
887 followers_count = u['followers_count']
6fa09c14 888
7500d90b 889 # Create content
c075e6dc
O
890 statuses_count = color_func(
891 c['PROFILE']['statuses_count'])(
892 str(statuses_count) +
893 ' tweets')
894 friends_count = color_func(
895 c['PROFILE']['friends_count'])(
896 str(friends_count) +
897 ' following')
898 followers_count = color_func(
899 c['PROFILE']['followers_count'])(
900 str(followers_count) +
901 ' followers')
7500d90b 902 count = statuses_count + ' ' + friends_count + ' ' + followers_count
c075e6dc
O
903 user = cycle_color(
904 name) + color_func(c['PROFILE']['nick'])(' @' + screen_name + ' : ') + count
905 profile_image_raw_url = 'Profile photo: ' + \
906 color_func(c['PROFILE']['profile_image_url'])(profile_image_url)
7500d90b 907 description = ''.join(
c3bab4ef 908 lmap(lambda x: x + ' ' * 4 if x == '\n' else x, description))
632c6fa5
O
909 description = color_func(c['PROFILE']['description'])(description)
910 location = 'Location : ' + color_func(c['PROFILE']['location'])(location)
911 url = 'URL : ' + (color_func(c['PROFILE']['url'])(url) if url else '')
7500d90b 912 date = parser.parse(created_at)
8b3456f9 913 lang, encode = locale.getdefaultlocale()
914 clock = arrow.get(date).to('local').humanize(locale=lang)
632c6fa5 915 clock = 'Join at ' + color_func(c['PROFILE']['clock'])(clock)
6fa09c14 916
7500d90b
VNM
917 # Format
918 line1 = u"{u:>{uw}}".format(
919 u=user,
920 uw=len(user) + 2,
921 )
922 line2 = u"{p:>{pw}}".format(
923 p=profile_image_raw_url,
924 pw=len(profile_image_raw_url) + 4,
925 )
926 line3 = u"{d:>{dw}}".format(
927 d=description,
928 dw=len(description) + 4,
929 )
930 line4 = u"{l:>{lw}}".format(
931 l=location,
932 lw=len(location) + 4,
933 )
934 line5 = u"{u:>{uw}}".format(
935 u=url,
936 uw=len(url) + 4,
937 )
938 line6 = u"{c:>{cw}}".format(
939 c=clock,
940 cw=len(clock) + 4,
941 )
6fa09c14 942
7500d90b
VNM
943 # Display
944 printNicely('')
945 printNicely(line1)
fe9bb33b 946 if c['IMAGE_ON_TERM']:
17bc529d 947 try:
948 response = requests.get(profile_image_url)
c37c04a9 949 image_to_display(BytesIO(response.content))
17bc529d 950 except:
951 pass
7500d90b
VNM
952 else:
953 printNicely(line2)
954 for line in [line3, line4, line5, line6]:
955 printNicely(line)
956 printNicely('')
957
958
959def print_trends(trends):
960 """
961 Display topics
962 """
632c6fa5 963 for topic in trends[:c['TREND_MAX']]:
7500d90b
VNM
964 name = topic['name']
965 url = topic['url']
8394e34b 966 line = cycle_color(name) + ': ' + color_func(c['TREND']['url'])(url)
7500d90b
VNM
967 printNicely(line)
968 printNicely('')
2d341029
O
969
970
99cd1fba 971def print_list(group, noti=False):
2d341029
O
972 """
973 Display a list
974 """
99b52f5f 975 for grp in group:
2d341029 976 # Format
99b52f5f 977 name = grp['full_name']
2d341029 978 name = color_func(c['GROUP']['name'])(name + ' : ')
99b52f5f 979 member = str(grp['member_count'])
422dd385 980 member = color_func(c['GROUP']['member'])(member + ' member')
99b52f5f 981 subscriber = str(grp['subscriber_count'])
422dd385
O
982 subscriber = color_func(
983 c['GROUP']['subscriber'])(
984 subscriber +
985 ' subscriber')
99b52f5f 986 description = grp['description'].strip()
2d341029 987 description = color_func(c['GROUP']['description'])(description)
99b52f5f 988 mode = grp['mode']
422dd385 989 mode = color_func(c['GROUP']['mode'])('Type: ' + mode)
99b52f5f 990 created_at = grp['created_at']
2d341029 991 date = parser.parse(created_at)
8b3456f9 992 lang, encode = locale.getdefaultlocale()
993 clock = arrow.get(date).to('local').humanize(locale=lang)
2d341029
O
994 clock = 'Created at ' + color_func(c['GROUP']['clock'])(clock)
995
99cd1fba
O
996 prefix = ' ' * 2
997 # Add spaces in begining of line if this is inside a notification
998 if noti:
999 prefix = ' ' * 2 + prefix
2d341029 1000 # Create lines
99cd1fba
O
1001 line1 = prefix + name + member + ' ' + subscriber
1002 line2 = prefix + ' ' * 2 + description
1003 line3 = prefix + ' ' * 2 + mode
1004 line4 = prefix + ' ' * 2 + clock
2d341029
O
1005
1006 # Display
1007 printNicely('')
1008 printNicely(line1)
1009 printNicely(line2)
1010 printNicely(line3)
1011 printNicely(line4)
1012
38a6dc30
O
1013 if not noti:
1014 printNicely('')
59262e95
O
1015
1016
8141aca6 1017def show_calendar(month, date, rel):
1018 """
1019 Show the calendar in rainbow mode
1020 """
1021 month = random_rainbow(month)
1022 date = ' '.join([cycle_color(i) for i in date.split(' ')])
1023 today = str(int(os.popen('date +\'%d\'').read().strip()))
1024 # Display
1025 printNicely(month)
1026 printNicely(date)
1027 for line in rel:
1028 ary = line.split(' ')
1029 ary = lmap(
1030 lambda x: color_func(c['CAL']['today'])(x)
1031 if x == today
1032 else color_func(c['CAL']['days'])(x),
1033 ary)
1034 printNicely(' '.join(ary))
1035
1036
b7c9c570 1037def format_quote(tweet):
1038 """
1039 Quoting format
1040 """
1041 # Retrieve info
1042 screen_name = '@' + tweet['user']['screen_name']
1043 text = tweet['text']
1044 # Validate quote format
1045 if '#owner' not in c['QUOTE_FORMAT']:
1046 printNicely(light_magenta('Quote should contains #owner'))
1047 return False
1048 if '#comment' not in c['QUOTE_FORMAT']:
1049 printNicely(light_magenta('Quote format should have #comment'))
1050 return False
1051 # Build formater
1052 formater = ''
1053 try:
1054 formater = c['QUOTE_FORMAT']
1055 formater = screen_name.join(formater.split('#owner'))
1056 formater = text.join(formater.split('#tweet'))
1057 formater = u2str(formater)
1058 except:
1059 pass
1060 # Highlight like a tweet
4dc385b5
O
1061 notice = formater.split()
1062 notice = lmap(
b7c9c570 1063 lambda x: light_green(x)
1064 if x == '#comment'
1065 else x,
4dc385b5
O
1066 notice)
1067 notice = lmap(
b7c9c570 1068 lambda x: color_func(c['TWEET']['rt'])(x)
1069 if x == 'RT'
1070 else x,
4dc385b5
O
1071 notice)
1072 notice = lmap(lambda x: cycle_color(x) if x[0] == '@' else x, notice)
1073 notice = lmap(
b7c9c570 1074 lambda x: color_func(c['TWEET']['link'])(x)
1075 if x[0:4] == 'http'
1076 else x,
4dc385b5
O
1077 notice)
1078 notice = lmap(
b7c9c570 1079 lambda x: color_func(c['TWEET']['hashtag'])(x)
1080 if x.startswith('#')
1081 else x,
4dc385b5
O
1082 notice)
1083 notice = ' '.join(notice)
b7c9c570 1084 # Notice
4dc385b5 1085 notice = light_magenta('Quoting: "') + notice + light_magenta('"')
b7c9c570 1086 printNicely(notice)
1087 return formater
1088
1089
59262e95 1090# Start the color cycle
b2cde062 1091start_cycle()