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