semaphore ater enter key are pushed
[rainbowstream.git] / rainbowstream / rainbow.py
1 """
2 Colorful user's timeline stream
3 """
4 from multiprocessing import Process
5
6 import os
7 import os.path
8 import sys
9 import signal
10 import argparse
11 import time
12 import requests
13 import webbrowser
14 import json
15
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
21
22 from .draw import *
23 from .colors import *
24 from .config import *
25 from .consumer import *
26 from .interactive import *
27 from .db import *
28 from .c_image import *
29 from .py3patch import *
30
31
32 g = {}
33 db = RainbowDB()
34 cmdset = [
35 'switch',
36 'trend',
37 'home',
38 'view',
39 'mentions',
40 't',
41 'rt',
42 'quote',
43 'allrt',
44 'fav',
45 'rep',
46 'del',
47 'ufav',
48 's',
49 'mes',
50 'show',
51 'open',
52 'ls',
53 'inbox',
54 'sent',
55 'trash',
56 'whois',
57 'fl',
58 'ufl',
59 'mute',
60 'unmute',
61 'muting',
62 'block',
63 'unblock',
64 'report',
65 'list',
66 'cal',
67 'theme',
68 'h',
69 'c',
70 'q'
71 ]
72
73
74 def parse_arguments():
75 """
76 Parse the arguments
77 """
78 parser = argparse.ArgumentParser(description=__doc__ or "")
79 parser.add_argument(
80 '-to',
81 '--timeout',
82 help='Timeout for the stream (seconds).')
83 parser.add_argument(
84 '-ht',
85 '--heartbeat-timeout',
86 help='Set heartbeat timeout.',
87 default=90)
88 parser.add_argument(
89 '-nb',
90 '--no-block',
91 action='store_true',
92 help='Set stream to non-blocking.')
93 parser.add_argument(
94 '-tt',
95 '--track-keywords',
96 help='Search the stream for specific text.')
97 parser.add_argument(
98 '-fil',
99 '--filter',
100 help='Filter specific screen_name.')
101 parser.add_argument(
102 '-ig',
103 '--ignore',
104 help='Ignore specific screen_name.')
105 parser.add_argument(
106 '-iot',
107 '--image-on-term',
108 action='store_true',
109 help='Display all image on terminal.')
110 return parser.parse_args()
111
112
113 def authen():
114 """
115 Authenticate with Twitter OAuth
116 """
117 # When using rainbow stream you must authorize.
118 twitter_credential = os.environ.get(
119 'HOME',
120 os.environ.get(
121 'USERPROFILE',
122 '')) + os.sep + '.rainbow_oauth'
123 if not os.path.exists(twitter_credential):
124 oauth_dance("Rainbow Stream",
125 CONSUMER_KEY,
126 CONSUMER_SECRET,
127 twitter_credential)
128 oauth_token, oauth_token_secret = read_token_file(twitter_credential)
129 return OAuth(
130 oauth_token,
131 oauth_token_secret,
132 CONSUMER_KEY,
133 CONSUMER_SECRET)
134
135
136 def get_decorated_name():
137 """
138 Init function
139 """
140 # Get name
141 t = Twitter(auth=authen())
142 name = '@' + t.account.verify_credentials()['screen_name']
143 g['original_name'] = name[1:]
144 g['decorated_name'] = color_func(c['DECORATED_NAME'])('[' + name + ']: ')
145
146 # Theme init
147 files = os.listdir(os.path.dirname(__file__) + '/colorset')
148 themes = [f.split('.')[0] for f in files if f.split('.')[-1] == 'json']
149 g['themes'] = themes
150 db.theme_store(c['THEME'])
151
152 # Semaphore init
153 db.semaphore_store(False)
154
155
156 def switch():
157 """
158 Switch stream
159 """
160 try:
161 target = g['stuff'].split()[0]
162
163 # Filter and ignore
164 args = parse_arguments()
165 try:
166 if g['stuff'].split()[-1] == '-f':
167 only = raw_input('Only nicks: ')
168 ignore = raw_input('Ignore nicks: ')
169 args.filter = filter(None, only.split(','))
170 args.ignore = filter(None, ignore.split(','))
171 elif g['stuff'].split()[-1] == '-d':
172 args.filter = c['ONLY_LIST']
173 args.ignore = c['IGNORE_LIST']
174 except:
175 printNicely(red('Sorry, wrong format.'))
176 return
177
178 # Public stream
179 if target == 'public':
180 keyword = g['stuff'].split()[1]
181 if keyword[0] == '#':
182 keyword = keyword[1:]
183 # Kill old process
184 os.kill(g['stream_pid'], signal.SIGKILL)
185 args.track_keywords = keyword
186 # Start new process
187 p = Process(
188 target=stream,
189 args=(
190 c['PUBLIC_DOMAIN'],
191 args))
192 p.start()
193 g['stream_pid'] = p.pid
194
195 # Personal stream
196 elif target == 'mine':
197 # Kill old process
198 os.kill(g['stream_pid'], signal.SIGKILL)
199 # Start new process
200 p = Process(
201 target=stream,
202 args=(
203 c['USER_DOMAIN'],
204 args,
205 g['original_name']))
206 p.start()
207 g['stream_pid'] = p.pid
208 printNicely('')
209 if args.filter:
210 printNicely(cyan('Only: ' + str(args.filter)))
211 if args.ignore:
212 printNicely(red('Ignore: ' + str(args.ignore)))
213 printNicely('')
214 except:
215 printNicely(red('Sorry I can\'t understand.'))
216
217
218 def trend():
219 """
220 Trend
221 """
222 t = Twitter(auth=authen())
223 # Get country and town
224 try:
225 country = g['stuff'].split()[0]
226 except:
227 country = ''
228 try:
229 town = g['stuff'].split()[1]
230 except:
231 town = ''
232
233 avail = t.trends.available()
234 # World wide
235 if not country:
236 trends = t.trends.place(_id=1)[0]['trends']
237 print_trends(trends)
238 else:
239 for location in avail:
240 # Search for country and Town
241 if town:
242 if location['countryCode'] == country \
243 and location['placeType']['name'] == 'Town' \
244 and location['name'] == town:
245 trends = t.trends.place(_id=location['woeid'])[0]['trends']
246 print_trends(trends)
247 # Search for country only
248 else:
249 if location['countryCode'] == country \
250 and location['placeType']['name'] == 'Country':
251 trends = t.trends.place(_id=location['woeid'])[0]['trends']
252 print_trends(trends)
253
254
255 def home():
256 """
257 Home
258 """
259 t = Twitter(auth=authen())
260 num = c['HOME_TWEET_NUM']
261 if g['stuff'].isdigit():
262 num = int(g['stuff'])
263 for tweet in reversed(t.statuses.home_timeline(count=num)):
264 draw(t=tweet, iot=g['iot'])
265 printNicely('')
266
267
268 def view():
269 """
270 Friend view
271 """
272 t = Twitter(auth=authen())
273 user = g['stuff'].split()[0]
274 if user[0] == '@':
275 try:
276 num = int(g['stuff'].split()[1])
277 except:
278 num = c['HOME_TWEET_NUM']
279 for tweet in reversed(t.statuses.user_timeline(count=num, screen_name=user[1:])):
280 draw(t=tweet, iot=g['iot'])
281 printNicely('')
282 else:
283 printNicely(red('A name should begin with a \'@\''))
284
285
286 def mentions():
287 """
288 Mentions timeline
289 """
290 t = Twitter(auth=authen())
291 num = c['HOME_TWEET_NUM']
292 if g['stuff'].isdigit():
293 num = int(g['stuff'])
294 for tweet in reversed(t.statuses.mentions_timeline(count=num)):
295 draw(t=tweet, iot=g['iot'])
296 printNicely('')
297
298
299 def tweet():
300 """
301 Tweet
302 """
303 t = Twitter(auth=authen())
304 t.statuses.update(status=g['stuff'])
305
306
307 def retweet():
308 """
309 ReTweet
310 """
311 t = Twitter(auth=authen())
312 try:
313 id = int(g['stuff'].split()[0])
314 except:
315 printNicely(red('Sorry I can\'t understand.'))
316 return
317 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
318 t.statuses.retweet(id=tid, include_entities=False, trim_user=True)
319
320
321 def quote():
322 """
323 Quote a tweet
324 """
325 t = Twitter(auth=authen())
326 try:
327 id = int(g['stuff'].split()[0])
328 except:
329 printNicely(red('Sorry I can\'t understand.'))
330 return
331 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
332 tweet = t.statuses.show(id=tid)
333 screen_name = tweet['user']['screen_name']
334 text = tweet['text']
335 quote = '\"@' + screen_name + ': ' + text + '\"'
336 quote = quote.encode('utf8')
337 notice = light_magenta('Compose mode ')
338 notice += light_yellow('(Enter nothing will cancel the quote)')
339 notice += light_magenta(':')
340 printNicely(notice)
341 extra = raw_input(quote)
342 if extra:
343 t.statuses.update(status=quote + extra)
344 else:
345 printNicely(light_magenta('No text added.'))
346
347
348 def allretweet():
349 """
350 List all retweet
351 """
352 t = Twitter(auth=authen())
353 # Get rainbow id
354 try:
355 id = int(g['stuff'].split()[0])
356 except:
357 printNicely(red('Sorry I can\'t understand.'))
358 return
359 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
360 # Get display num if exist
361 try:
362 num = int(g['stuff'].split()[1])
363 except:
364 num = c['RETWEETS_SHOW_NUM']
365 # Get result and display
366 rt_ary = t.statuses.retweets(id=tid, count=num)
367 if not rt_ary:
368 printNicely(magenta('This tweet has no retweet.'))
369 return
370 for tweet in reversed(rt_ary):
371 draw(t=tweet, iot=g['iot'])
372 printNicely('')
373
374
375 def favorite():
376 """
377 Favorite
378 """
379 t = Twitter(auth=authen())
380 try:
381 id = int(g['stuff'].split()[0])
382 except:
383 printNicely(red('Sorry I can\'t understand.'))
384 return
385 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
386 t.favorites.create(_id=tid, include_entities=False)
387 printNicely(green('Favorited.'))
388 draw(t.statuses.show(id=tid), iot=g['iot'])
389 printNicely('')
390
391
392 def reply():
393 """
394 Reply
395 """
396 t = Twitter(auth=authen())
397 try:
398 id = int(g['stuff'].split()[0])
399 except:
400 printNicely(red('Sorry I can\'t understand.'))
401 return
402 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
403 user = t.statuses.show(id=tid)['user']['screen_name']
404 status = ' '.join(g['stuff'].split()[1:])
405 status = '@' + user + ' ' + status.decode('utf-8')
406 t.statuses.update(status=status, in_reply_to_status_id=tid)
407
408
409 def delete():
410 """
411 Delete
412 """
413 t = Twitter(auth=authen())
414 try:
415 rid = int(g['stuff'].split()[0])
416 except:
417 printNicely(red('Sorry I can\'t understand.'))
418 return
419 tid = db.rainbow_to_tweet_query(rid)[0].tweet_id
420 t.statuses.destroy(id=tid)
421 printNicely(green('Okay it\'s gone.'))
422
423
424 def unfavorite():
425 """
426 Unfavorite
427 """
428 t = Twitter(auth=authen())
429 try:
430 id = int(g['stuff'].split()[0])
431 except:
432 printNicely(red('Sorry I can\'t understand.'))
433 return
434 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
435 t.favorites.destroy(_id=tid)
436 printNicely(green('Okay it\'s unfavorited.'))
437 draw(t.statuses.show(id=tid), iot=g['iot'])
438 printNicely('')
439
440
441 def search():
442 """
443 Search
444 """
445 t = Twitter(auth=authen())
446 g['stuff'] = g['stuff'].strip()
447 rel = t.search.tweets(q=g['stuff'])['statuses']
448 if rel:
449 printNicely('Newest tweets:')
450 for i in reversed(xrange(c['SEARCH_MAX_RECORD'])):
451 draw(t=rel[i],
452 iot=g['iot'],
453 keyword=g['stuff'])
454 printNicely('')
455 else:
456 printNicely(magenta('I\'m afraid there is no result'))
457
458
459 def message():
460 """
461 Send a direct message
462 """
463 t = Twitter(auth=authen())
464 user = g['stuff'].split()[0]
465 if user[0].startswith('@'):
466 try:
467 content = g['stuff'].split()[1]
468 except:
469 printNicely(red('Sorry I can\'t understand.'))
470 t.direct_messages.new(
471 screen_name=user[1:],
472 text=content
473 )
474 printNicely(green('Message sent.'))
475 else:
476 printNicely(red('A name should begin with a \'@\''))
477
478
479 def show():
480 """
481 Show image
482 """
483 t = Twitter(auth=authen())
484 try:
485 target = g['stuff'].split()[0]
486 if target != 'image':
487 return
488 id = int(g['stuff'].split()[1])
489 tid = db.rainbow_to_tweet_query(id)[0].tweet_id
490 tweet = t.statuses.show(id=tid)
491 media = tweet['entities']['media']
492 for m in media:
493 res = requests.get(m['media_url'])
494 img = Image.open(BytesIO(res.content))
495 img.show()
496 except:
497 printNicely(red('Sorry I can\'t show this image.'))
498
499
500 def urlopen():
501 """
502 Open url
503 """
504 t = Twitter(auth=authen())
505 try:
506 if not g['stuff'].isdigit():
507 return
508 tid = db.rainbow_to_tweet_query(g['stuff'])[0].tweet_id
509 tweet = t.statuses.show(id=tid)
510 link_ary = [
511 u for u in tweet['text'].split() if u.startswith('http://')]
512 if not link_ary:
513 printNicely(light_magenta('No url here @.@!'))
514 return
515 for link in link_ary:
516 webbrowser.open(link)
517 except:
518 printNicely(red('Sorry I can\'t open url in this tweet.'))
519
520
521 def ls():
522 """
523 List friends for followers
524 """
525 t = Twitter(auth=authen())
526 # Get name
527 try:
528 name = g['stuff'].split()[1]
529 if name.startswith('@'):
530 name = name[1:]
531 else:
532 printNicely(red('A name should begin with a \'@\''))
533 raise Exception('Invalid name')
534 except:
535 name = g['original_name']
536 # Get list followers or friends
537 try:
538 target = g['stuff'].split()[0]
539 except:
540 printNicely(red('Omg some syntax is wrong.'))
541 # Init cursor
542 d = {'fl': 'followers', 'fr': 'friends'}
543 next_cursor = -1
544 rel = {}
545 # Cursor loop
546 while next_cursor != 0:
547 list = getattr(t, d[target]).list(
548 screen_name=name,
549 cursor=next_cursor,
550 skip_status=True,
551 include_entities=False,
552 )
553 for u in list['users']:
554 rel[u['name']] = '@' + u['screen_name']
555 next_cursor = list['next_cursor']
556 # Print out result
557 printNicely('All: ' + str(len(rel)) + ' ' + d[target] + '.')
558 for name in rel:
559 user = ' ' + cycle_color(name)
560 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
561 printNicely(user)
562
563
564 def inbox():
565 """
566 Inbox direct messages
567 """
568 t = Twitter(auth=authen())
569 num = c['MESSAGES_DISPLAY']
570 rel = []
571 if g['stuff'].isdigit():
572 num = g['stuff']
573 cur_page = 1
574 # Max message per page is 20 so we have to loop
575 while num > 20:
576 rel = rel + t.direct_messages(
577 count=20,
578 page=cur_page,
579 include_entities=False,
580 skip_status=False
581 )
582 num -= 20
583 cur_page += 1
584 rel = rel + t.direct_messages(
585 count=num,
586 page=cur_page,
587 include_entities=False,
588 skip_status=False
589 )
590 # Display
591 printNicely('Inbox: newest ' + str(len(rel)) + ' messages.')
592 for m in reversed(rel):
593 print_message(m)
594 printNicely('')
595
596
597 def sent():
598 """
599 Sent direct messages
600 """
601 t = Twitter(auth=authen())
602 num = c['MESSAGES_DISPLAY']
603 rel = []
604 if g['stuff'].isdigit():
605 num = int(g['stuff'])
606 cur_page = 1
607 # Max message per page is 20 so we have to loop
608 while num > 20:
609 rel = rel + t.direct_messages.sent(
610 count=20,
611 page=cur_page,
612 include_entities=False,
613 skip_status=False
614 )
615 num -= 20
616 cur_page += 1
617 rel = rel + t.direct_messages.sent(
618 count=num,
619 page=cur_page,
620 include_entities=False,
621 skip_status=False
622 )
623 # Display
624 printNicely('Sent: newest ' + str(len(rel)) + ' messages.')
625 for m in reversed(rel):
626 print_message(m)
627 printNicely('')
628
629
630 def trash():
631 """
632 Remove message
633 """
634 t = Twitter(auth=authen())
635 try:
636 rid = int(g['stuff'].split()[0])
637 except:
638 printNicely(red('Sorry I can\'t understand.'))
639 mid = db.rainbow_to_message_query(rid)[0].message_id
640 t.direct_messages.destroy(id=mid)
641 printNicely(green('Message deleted.'))
642
643
644 def whois():
645 """
646 Show profile of a specific user
647 """
648 t = Twitter(auth=authen())
649 screen_name = g['stuff'].split()[0]
650 if screen_name.startswith('@'):
651 try:
652 user = t.users.show(
653 screen_name=screen_name[1:],
654 include_entities=False)
655 show_profile(user, g['iot'])
656 except:
657 printNicely(red('Omg no user.'))
658 else:
659 printNicely(red('A name should begin with a \'@\''))
660
661
662 def follow():
663 """
664 Follow a user
665 """
666 t = Twitter(auth=authen())
667 screen_name = g['stuff'].split()[0]
668 if screen_name.startswith('@'):
669 t.friendships.create(screen_name=screen_name[1:], follow=True)
670 printNicely(green('You are following ' + screen_name + ' now!'))
671 else:
672 printNicely(red('A name should begin with a \'@\''))
673
674
675 def unfollow():
676 """
677 Unfollow a user
678 """
679 t = Twitter(auth=authen())
680 screen_name = g['stuff'].split()[0]
681 if screen_name.startswith('@'):
682 t.friendships.destroy(
683 screen_name=screen_name[1:],
684 include_entities=False)
685 printNicely(green('Unfollow ' + screen_name + ' success!'))
686 else:
687 printNicely(red('A name should begin with a \'@\''))
688
689
690 def mute():
691 """
692 Mute a user
693 """
694 t = Twitter(auth=authen())
695 try:
696 screen_name = g['stuff'].split()[0]
697 except:
698 printNicely(red('A name should be specified. '))
699 return
700 if screen_name.startswith('@'):
701 rel = t.mutes.users.create(screen_name=screen_name[1:])
702 if isinstance(rel, dict):
703 printNicely(green(screen_name + ' is muted.'))
704 else:
705 printNicely(red(rel))
706 else:
707 printNicely(red('A name should begin with a \'@\''))
708
709
710 def unmute():
711 """
712 Unmute a user
713 """
714 t = Twitter(auth=authen())
715 try:
716 screen_name = g['stuff'].split()[0]
717 except:
718 printNicely(red('A name should be specified. '))
719 return
720 if screen_name.startswith('@'):
721 rel = t.mutes.users.destroy(screen_name=screen_name[1:])
722 if isinstance(rel, dict):
723 printNicely(green(screen_name + ' is unmuted.'))
724 else:
725 printNicely(red(rel))
726 else:
727 printNicely(red('A name should begin with a \'@\''))
728
729
730 def muting():
731 """
732 List muting user
733 """
734 t = Twitter(auth=authen())
735 # Init cursor
736 next_cursor = -1
737 rel = {}
738 # Cursor loop
739 while next_cursor != 0:
740 list = t.mutes.users.list(
741 screen_name=g['original_name'],
742 cursor=next_cursor,
743 skip_status=True,
744 include_entities=False,
745 )
746 for u in list['users']:
747 rel[u['name']] = '@' + u['screen_name']
748 next_cursor = list['next_cursor']
749 # Print out result
750 printNicely('All: ' + str(len(rel)) + ' people.')
751 for name in rel:
752 user = ' ' + cycle_color(name)
753 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
754 printNicely(user)
755
756
757 def block():
758 """
759 Block a user
760 """
761 t = Twitter(auth=authen())
762 screen_name = g['stuff'].split()[0]
763 if screen_name.startswith('@'):
764 t.blocks.create(
765 screen_name=screen_name[1:],
766 include_entities=False,
767 skip_status=True)
768 printNicely(green('You blocked ' + screen_name + '.'))
769 else:
770 printNicely(red('A name should begin with a \'@\''))
771
772
773 def unblock():
774 """
775 Unblock a user
776 """
777 t = Twitter(auth=authen())
778 screen_name = g['stuff'].split()[0]
779 if screen_name.startswith('@'):
780 t.blocks.destroy(
781 screen_name=screen_name[1:],
782 include_entities=False,
783 skip_status=True)
784 printNicely(green('Unblock ' + screen_name + ' success!'))
785 else:
786 printNicely(red('A name should begin with a \'@\''))
787
788
789 def report():
790 """
791 Report a user as a spam account
792 """
793 t = Twitter(auth=authen())
794 screen_name = g['stuff'].split()[0]
795 if screen_name.startswith('@'):
796 t.users.report_spam(
797 screen_name=screen_name[1:])
798 printNicely(green('You reported ' + screen_name + '.'))
799 else:
800 printNicely(red('Sorry I can\'t understand.'))
801
802
803 def get_slug():
804 """
805 Get Slug Decorator
806 """
807 # Get list name
808 list_name = raw_input(light_magenta('Give me the list\'s name: '))
809 # Get list name and owner
810 try:
811 owner, slug = list_name.split('/')
812 if slug.startswith('@'):
813 slug = slug[1:]
814 return owner, slug
815 except:
816 printNicely(light_magenta('List name should follow "@owner/list_name" format.'))
817 raise Exception('Wrong list name')
818
819
820 def show_lists(t):
821 """
822 List list
823 """
824 rel = t.lists.list(screen_name=g['original_name'])
825 if rel:
826 print_list(rel)
827 else:
828 printNicely(light_magenta('You belong to no lists :)'))
829
830
831 def list_home(t):
832 """
833 List home
834 """
835 owner, slug = get_slug()
836 res = t.lists.statuses(
837 slug=slug,
838 owner_screen_name=owner,
839 count=c['LIST_MAX'],
840 include_entities=False)
841 for tweet in res:
842 draw(t=tweet)
843 printNicely('')
844
845
846 def list_members(t):
847 """
848 List members
849 """
850 owner, slug = get_slug()
851 # Get members
852 rel = {}
853 next_cursor = -1
854 while next_cursor != 0:
855 m = t.lists.members(
856 slug=slug,
857 owner_screen_name=owner,
858 cursor=next_cursor,
859 include_entities=False)
860 for u in m['users']:
861 rel[u['name']] = '@' + u['screen_name']
862 next_cursor = m['next_cursor']
863 printNicely('All: ' + str(len(rel)) + ' members.')
864 for name in rel:
865 user = ' ' + cycle_color(name)
866 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
867 printNicely(user)
868
869
870 def list_subscribers(t):
871 """
872 List subscribers
873 """
874 owner, slug = get_slug()
875 # Get subscribers
876 rel = {}
877 next_cursor = -1
878 while next_cursor != 0:
879 m = t.lists.subscribers(
880 slug=slug,
881 owner_screen_name=owner,
882 cursor=next_cursor,
883 include_entities=False)
884 for u in m['users']:
885 rel[u['name']] = '@' + u['screen_name']
886 next_cursor = m['next_cursor']
887 printNicely('All: ' + str(len(rel)) + ' subscribers.')
888 for name in rel:
889 user = ' ' + cycle_color(name)
890 user += color_func(c['TWEET']['nick'])(' ' + rel[name] + ' ')
891 printNicely(user)
892
893
894 def list_add(t):
895 """
896 Add specific user to a list
897 """
898 owner, slug = get_slug()
899 # Add
900 user_name = raw_input(light_magenta('Give me name of the newbie: '))
901 if user_name.startswith('@'):
902 user_name = user_name[1:]
903 try:
904 t.lists.members.create(
905 slug=slug,
906 owner_screen_name=owner,
907 screen_name=user_name)
908 printNicely(light_green('Added.'))
909 except:
910 printNicely(light_magenta('I\'m sorry we can not add him/her.'))
911
912
913 def list_remove(t):
914 """
915 Remove specific user from a list
916 """
917 owner, slug = get_slug()
918 # Remove
919 user_name = raw_input(light_magenta('Give me name of the unlucky one: '))
920 if user_name.startswith('@'):
921 user_name = user_name[1:]
922 try:
923 t.lists.members.destroy(
924 slug=slug,
925 owner_screen_name=owner,
926 screen_name=user_name)
927 printNicely(light_green('Gone.'))
928 except:
929 printNicely(light_magenta('I\'m sorry we can not remove him/her.'))
930
931
932 def list_subscribe(t):
933 """
934 Subscribe to a list
935 """
936 owner, slug = get_slug()
937 # Subscribe
938 try:
939 t.lists.subscribers.create(
940 slug=slug,
941 owner_screen_name=owner)
942 printNicely(light_green('Done.'))
943 except:
944 printNicely(
945 light_magenta('I\'m sorry you can not subscribe to this list.'))
946
947
948 def list_unsubscribe(t):
949 """
950 Unsubscribe a list
951 """
952 owner, slug = get_slug()
953 # Subscribe
954 try:
955 t.lists.subscribers.destroy(
956 slug=slug,
957 owner_screen_name=owner)
958 printNicely(light_green('Done.'))
959 except:
960 printNicely(
961 light_magenta('I\'m sorry you can not unsubscribe to this list.'))
962
963
964 def list_own(t):
965 """
966 List own
967 """
968 rel = []
969 next_cursor = -1
970 while next_cursor != 0:
971 res = t.lists.ownerships(
972 screen_name=g['original_name'],
973 cursor=next_cursor)
974 rel += res['lists']
975 next_cursor = res['next_cursor']
976 if rel:
977 print_list(rel)
978 else:
979 printNicely(light_magenta('You own no lists :)'))
980
981
982 def list_new(t):
983 """
984 Create a new list
985 """
986 name = raw_input(light_magenta('New list\'s name: '))
987 mode = raw_input(light_magenta('New list\'s mode (public/private): '))
988 description = raw_input(light_magenta('New list\'s description: '))
989 try:
990 t.lists.create(
991 name=name,
992 mode=mode,
993 description=description)
994 printNicely(light_green(name + ' list is created.'))
995 except:
996 printNicely(red('Oops something is wrong with Twitter :('))
997
998
999 def list_update(t):
1000 """
1001 Update a list
1002 """
1003 slug = raw_input(light_magenta('Your list that you want to update: '))
1004 name = raw_input(light_magenta('Update name (leave blank to unchange): '))
1005 mode = raw_input(light_magenta('Update mode (public/private): '))
1006 description = raw_input(light_magenta('Update description: '))
1007 try:
1008 if name:
1009 t.lists.update(
1010 slug='-'.join(slug.split()),
1011 owner_screen_name=g['original_name'],
1012 name=name,
1013 mode=mode,
1014 description=description)
1015 else:
1016 t.lists.update(
1017 slug=slug,
1018 owner_screen_name=g['original_name'],
1019 mode=mode,
1020 description=description)
1021 printNicely(light_green(slug + ' list is updated.'))
1022 except:
1023 printNicely(red('Oops something is wrong with Twitter :('))
1024
1025
1026 def list_delete(t):
1027 """
1028 Delete a list
1029 """
1030 slug = raw_input(light_magenta('Your list that you want to update: '))
1031 try:
1032 t.lists.destroy(
1033 slug='-'.join(slug.split()),
1034 owner_screen_name=g['original_name'])
1035 printNicely(light_green(slug + ' list is deleted.'))
1036 except:
1037 printNicely(red('Oops something is wrong with Twitter :('))
1038
1039
1040 def list():
1041 """
1042 Twitter's list
1043 """
1044 t = Twitter(auth=authen())
1045 # List all lists or base on action
1046 try:
1047 g['list_action'] = g['stuff'].split()[0]
1048 except:
1049 show_lists(t)
1050 return
1051 # Sub-function
1052 action_ary = {
1053 'home': list_home,
1054 'all_mem': list_members,
1055 'all_sub': list_subscribers,
1056 'add': list_add,
1057 'rm': list_remove,
1058 'sub': list_subscribe,
1059 'unsub': list_unsubscribe,
1060 'own': list_own,
1061 'new': list_new,
1062 'update': list_update,
1063 'del': list_delete,
1064 }
1065 try:
1066 return action_ary[g['list_action']](t)
1067 except:
1068 printNicely(red('Please try again.'))
1069
1070
1071 def cal():
1072 """
1073 Unix's command `cal`
1074 """
1075 # Format
1076 rel = os.popen('cal').read().split('\n')
1077 month = rel.pop(0)
1078 date = rel.pop(0)
1079 show_calendar(month, date, rel)
1080
1081
1082 def theme():
1083 """
1084 List and change theme
1085 """
1086 if not g['stuff']:
1087 # List themes
1088 for theme in g['themes']:
1089 line = light_magenta(theme)
1090 if c['THEME'] == theme:
1091 line = ' ' * 2 + light_yellow('* ') + line
1092 else:
1093 line = ' ' * 4 + line
1094 printNicely(line)
1095 elif g['stuff'] == 'current_as_default':
1096 # Set as default
1097 def fixup(adict, k, v):
1098 for key in adict.keys():
1099 if key == k:
1100 adict[key] = v
1101 elif type(adict[key]) is dict:
1102 fixup(adict[key], k, v)
1103 # Modify
1104 path = os.environ.get(
1105 'HOME',
1106 os.environ.get(
1107 'USERPROFILE',
1108 '')) + os.sep + '.rainbow_config.json'
1109 data = load_config(rainbow_config)
1110 fixup(data, 'THEME', c['THEME'])
1111 # Save
1112 with open(path, 'w') as out:
1113 json.dump(data, out, indent = 4)
1114 os.system('chmod 777 ' + path)
1115 printNicely(light_green('Okay it will be applied from next time :)'))
1116 else:
1117 # Change theme
1118 try:
1119 # Load new config
1120 if g['stuff'] != 'custom':
1121 new_config = os.path.dirname(
1122 __file__) + '/colorset/' + g['stuff'] + '.json'
1123 else:
1124 new_config = os.environ.get(
1125 'HOME', os.environ.get(
1126 'USERPROFILE',
1127 '')) + os.sep + '.rainbow_config.json'
1128 new_config = load_config(new_config)
1129 if new_config:
1130 for nc in new_config:
1131 c[nc] = new_config[nc]
1132 # Update db and reset colors
1133 db.theme_update(g['stuff'])
1134 c['THEME'] = g['stuff']
1135 start_cycle()
1136 g['decorated_name'] = color_func(
1137 c['DECORATED_NAME'])(
1138 '[@' + g['original_name'] + ']: ')
1139 printNicely(green('Theme changed.'))
1140 except:
1141 printNicely(red('No such theme exists.'))
1142
1143
1144 def help_discover():
1145 """
1146 Discover the world
1147 """
1148 s = ' ' * 2
1149 # Discover the world
1150 usage = '\n'
1151 usage += s + grey(u'\u266A' + ' Discover the world \n')
1152 usage += s * 2 + light_green('trend') + ' will show global trending topics. ' + \
1153 'You can try ' + light_green('trend US') + ' or ' + \
1154 light_green('trend JP Tokyo') + '.\n'
1155 usage += s * 2 + light_green('home') + ' will show your timeline. ' + \
1156 light_green('home 7') + ' will show 7 tweets.\n'
1157 usage += s * 2 + light_green('mentions') + ' will show mentions timeline. ' + \
1158 light_green('mentions 7') + ' will show 7 mention tweets.\n'
1159 usage += s * 2 + light_green('whois @mdo') + ' will show profile of ' + \
1160 magenta('@mdo') + '.\n'
1161 usage += s * 2 + light_green('view @mdo') + \
1162 ' will show ' + magenta('@mdo') + '\'s home.\n'
1163 usage += s * 2 + light_green('s AKB48') + ' will search for "' + \
1164 light_yellow('AKB48') + '" and return 5 newest tweet. ' + \
1165 'Search can be performed with or without hashtag.\n'
1166 printNicely(usage)
1167
1168
1169 def help_tweets():
1170 """
1171 Tweets
1172 """
1173 s = ' ' * 2
1174 # Tweet
1175 usage = '\n'
1176 usage += s + grey(u'\u266A' + ' Tweets \n')
1177 usage += s * 2 + light_green('t oops ') + \
1178 'will tweet "' + light_yellow('oops') + '" immediately.\n'
1179 usage += s * 2 + \
1180 light_green('rt 12 ') + ' will retweet to tweet with ' + \
1181 light_yellow('[id=12]') + '.\n'
1182 usage += s * 2 + \
1183 light_green('quote 12 ') + ' will quote the tweet with ' + \
1184 light_yellow('[id=12]') + '. If no extra text is added, ' + \
1185 'the quote will be canceled.\n'
1186 usage += s * 2 + \
1187 light_green('allrt 12 20 ') + ' will list 20 newest retweet of the tweet with ' + \
1188 light_yellow('[id=12]') + '.\n'
1189 usage += s * 2 + light_green('rep 12 oops') + ' will reply "' + \
1190 light_yellow('oops') + '" to tweet with ' + \
1191 light_yellow('[id=12]') + '.\n'
1192 usage += s * 2 + \
1193 light_green('fav 12 ') + ' will favorite the tweet with ' + \
1194 light_yellow('[id=12]') + '.\n'
1195 usage += s * 2 + \
1196 light_green('ufav 12 ') + ' will unfavorite tweet with ' + \
1197 light_yellow('[id=12]') + '.\n'
1198 usage += s * 2 + \
1199 light_green('del 12 ') + ' will delete tweet with ' + \
1200 light_yellow('[id=12]') + '.\n'
1201 usage += s * 2 + light_green('show image 12') + ' will show image in tweet with ' + \
1202 light_yellow('[id=12]') + ' in your OS\'s image viewer.\n'
1203 usage += s * 2 + light_green('open 12') + ' will open url in tweet with ' + \
1204 light_yellow('[id=12]') + ' in your OS\'s default browser.\n'
1205 printNicely(usage)
1206
1207
1208 def help_messages():
1209 """
1210 Messages
1211 """
1212 s = ' ' * 2
1213 # Direct message
1214 usage = '\n'
1215 usage += s + grey(u'\u266A' + ' Direct messages \n')
1216 usage += s * 2 + light_green('inbox') + ' will show inbox messages. ' + \
1217 light_green('inbox 7') + ' will show newest 7 messages.\n'
1218 usage += s * 2 + light_green('sent') + ' will show sent messages. ' + \
1219 light_green('sent 7') + ' will show newest 7 messages.\n'
1220 usage += s * 2 + light_green('mes @dtvd88 hi') + ' will send a "hi" messege to ' + \
1221 magenta('@dtvd88') + '.\n'
1222 usage += s * 2 + light_green('trash 5') + ' will remove message with ' + \
1223 light_yellow('[message_id=5]') + '.\n'
1224 printNicely(usage)
1225
1226
1227 def help_friends_and_followers():
1228 """
1229 Friends and Followers
1230 """
1231 s = ' ' * 2
1232 # Follower and following
1233 usage = '\n'
1234 usage += s + grey(u'\u266A' + ' Friends and followers \n')
1235 usage += s * 2 + \
1236 light_green('ls fl') + \
1237 ' will list all followers (people who are following you).\n'
1238 usage += s * 2 + \
1239 light_green('ls fr') + \
1240 ' will list all friends (people who you are following).\n'
1241 usage += s * 2 + light_green('fl @dtvd88') + ' will follow ' + \
1242 magenta('@dtvd88') + '.\n'
1243 usage += s * 2 + light_green('ufl @dtvd88') + ' will unfollow ' + \
1244 magenta('@dtvd88') + '.\n'
1245 usage += s * 2 + light_green('mute @dtvd88') + ' will mute ' + \
1246 magenta('@dtvd88') + '.\n'
1247 usage += s * 2 + light_green('unmute @dtvd88') + ' will unmute ' + \
1248 magenta('@dtvd88') + '.\n'
1249 usage += s * 2 + light_green('muting') + ' will list muting users.\n'
1250 usage += s * 2 + light_green('block @dtvd88') + ' will block ' + \
1251 magenta('@dtvd88') + '.\n'
1252 usage += s * 2 + light_green('unblock @dtvd88') + ' will unblock ' + \
1253 magenta('@dtvd88') + '.\n'
1254 usage += s * 2 + light_green('report @dtvd88') + ' will report ' + \
1255 magenta('@dtvd88') + ' as a spam account.\n'
1256 printNicely(usage)
1257
1258
1259 def help_list():
1260 """
1261 Lists
1262 """
1263 s = ' ' * 2
1264 # Twitter list
1265 usage = '\n'
1266 usage += s + grey(u'\u266A' + ' Twitter list\n')
1267 usage += s * 2 + light_green('list') + \
1268 ' will show all lists you are belong to.\n'
1269 usage += s * 2 + light_green('list home') + \
1270 ' will show timeline of list. You will be asked for list\'s name.\n'
1271 usage += s * 2 + light_green('list all_mem') + \
1272 ' will show list\'s all members.\n'
1273 usage += s * 2 + light_green('list all_sub') + \
1274 ' will show list\'s all subscribers.\n'
1275 usage += s * 2 + light_green('list add') + \
1276 ' will add specific person to a list owned by you.' + \
1277 ' You will be asked for list\'s name and person\'s name.\n'
1278 usage += s * 2 + light_green('list rm') + \
1279 ' will remove specific person from a list owned by you.' + \
1280 ' You will be asked for list\'s name and person\'s name.\n'
1281 usage += s * 2 + light_green('list sub') + \
1282 ' will subscribe you to a specific list.\n'
1283 usage += s * 2 + light_green('list unsub') + \
1284 ' will unsubscribe you from a specific list.\n'
1285 usage += s * 2 + light_green('list own') + \
1286 ' will show all list owned by you.\n'
1287 usage += s * 2 + light_green('list new') + \
1288 ' will create a new list.\n'
1289 usage += s * 2 + light_green('list update') + \
1290 ' will update a list owned by you.\n'
1291 usage += s * 2 + light_green('list del') + \
1292 ' will delete a list owned by you.\n'
1293 printNicely(usage)
1294
1295
1296 def help_stream():
1297 """
1298 Stream switch
1299 """
1300 s = ' ' * 2
1301 # Switch
1302 usage = '\n'
1303 usage += s + grey(u'\u266A' + ' Switching streams \n')
1304 usage += s * 2 + light_green('switch public #AKB') + \
1305 ' will switch to public stream and follow "' + \
1306 light_yellow('AKB') + '" keyword.\n'
1307 usage += s * 2 + light_green('switch mine') + \
1308 ' will switch to your personal stream.\n'
1309 usage += s * 2 + light_green('switch mine -f ') + \
1310 ' will prompt to enter the filter.\n'
1311 usage += s * 3 + light_yellow('Only nicks') + \
1312 ' filter will decide nicks will be INCLUDE ONLY.\n'
1313 usage += s * 3 + light_yellow('Ignore nicks') + \
1314 ' filter will decide nicks will be EXCLUDE.\n'
1315 usage += s * 2 + light_green('switch mine -d') + \
1316 ' will use the config\'s ONLY_LIST and IGNORE_LIST.\n'
1317 printNicely(usage)
1318
1319
1320 def help():
1321 """
1322 Help
1323 """
1324 s = ' ' * 2
1325 h, w = os.popen('stty size', 'r').read().split()
1326
1327 # Start
1328 usage = '\n'
1329 usage += s + 'Hi boss! I\'m ready to serve you right now!\n'
1330 usage += s + '-' * (int(w) - 4) + '\n'
1331 usage += s + 'You are ' + \
1332 light_yellow('already') + ' on your personal stream.\n'
1333 usage += s + 'Any update from Twitter will show up ' + \
1334 light_yellow('immediately') + '.\n'
1335 usage += s + 'In addtion, following commands are available right now:\n'
1336
1337 # Twitter help section
1338 usage += '\n'
1339 usage += s + grey(u'\u266A' + ' Twitter help\n')
1340 usage += s * 2 + light_green('h discover') + \
1341 ' will show help for discover commands.\n'
1342 usage += s * 2 + light_green('h tweets') + \
1343 ' will show help for tweets commands.\n'
1344 usage += s * 2 + light_green('h messages') + \
1345 ' will show help for messages commands.\n'
1346 usage += s * 2 + light_green('h friends_and_followers') + \
1347 ' will show help for friends and followers commands.\n'
1348 usage += s * 2 + light_green('h list') + \
1349 ' will show help for list commands.\n'
1350 usage += s * 2 + light_green('h stream') + \
1351 ' will show help for stream commands.\n'
1352
1353 # Smart shell
1354 usage += '\n'
1355 usage += s + grey(u'\u266A' + ' Smart shell\n')
1356 usage += s * 2 + light_green('111111 * 9 / 7') + ' or any math expression ' + \
1357 'will be evaluate by Python interpreter.\n'
1358 usage += s * 2 + 'Even ' + light_green('cal') + ' will show the calendar' + \
1359 ' for current month.\n'
1360
1361 # Screening
1362 usage += '\n'
1363 usage += s + grey(u'\u266A' + ' Screening \n')
1364 usage += s * 2 + light_green('theme') + ' will list available theme.' + \
1365 light_green('theme monokai') + ' will apply ' + light_yellow('monokai') + \
1366 ' theme immediately.\n'
1367 usage += s * 2 + light_green('h') + ' will show this help again.\n'
1368 usage += s * 2 + light_green('c') + ' will clear the screen.\n'
1369 usage += s * 2 + light_green('q') + ' will quit.\n'
1370
1371 # End
1372 usage += '\n'
1373 usage += s + '-' * (int(w) - 4) + '\n'
1374 usage += s + 'Have fun and hang tight! \n'
1375
1376 # Show help
1377 d = {
1378 'discover': help_discover,
1379 'tweets': help_tweets,
1380 'messages': help_messages,
1381 'friends_and_followers': help_friends_and_followers,
1382 'list': help_list,
1383 'stream': help_stream,
1384 }
1385 if g['stuff']:
1386 d[g['stuff'].strip()]()
1387 else:
1388 printNicely(usage)
1389
1390
1391 def clear():
1392 """
1393 Clear screen
1394 """
1395 os.system('clear')
1396
1397
1398 def quit():
1399 """
1400 Exit all
1401 """
1402 save_history()
1403 os.system('rm -rf rainbow.db')
1404 os.kill(g['stream_pid'], signal.SIGKILL)
1405 sys.exit()
1406
1407
1408 def reset():
1409 """
1410 Reset prefix of line
1411 """
1412 if g['reset']:
1413 printNicely(magenta('Need tips ? Type "h" and hit Enter key!'))
1414 g['reset'] = False
1415 try:
1416 printNicely(str(eval(g['cmd'])))
1417 except Exception:
1418 pass
1419
1420
1421 def process(cmd):
1422 """
1423 Process switch
1424 """
1425 return dict(zip(
1426 cmdset,
1427 [
1428 switch,
1429 trend,
1430 home,
1431 view,
1432 mentions,
1433 tweet,
1434 retweet,
1435 quote,
1436 allretweet,
1437 favorite,
1438 reply,
1439 delete,
1440 unfavorite,
1441 search,
1442 message,
1443 show,
1444 urlopen,
1445 ls,
1446 inbox,
1447 sent,
1448 trash,
1449 whois,
1450 follow,
1451 unfollow,
1452 mute,
1453 unmute,
1454 muting,
1455 block,
1456 unblock,
1457 report,
1458 list,
1459 cal,
1460 theme,
1461 help,
1462 clear,
1463 quit
1464 ]
1465 )).get(cmd, reset)
1466
1467
1468 def listen():
1469 """
1470 Listen to user's input
1471 """
1472 d = dict(zip(
1473 cmdset,
1474 [
1475 ['public', 'mine'], # switch
1476 [], # trend
1477 [], # home
1478 ['@'], # view
1479 [], # mentions
1480 [], # tweet
1481 [], # retweet
1482 [], # quote
1483 [], # allretweet
1484 [], # favorite
1485 [], # reply
1486 [], # delete
1487 [], # unfavorite
1488 ['#'], # search
1489 ['@'], # message
1490 ['image'], # show image
1491 [''], # open url
1492 ['fl', 'fr'], # list
1493 [], # inbox
1494 [], # sent
1495 [], # trash
1496 ['@'], # whois
1497 ['@'], # follow
1498 ['@'], # unfollow
1499 ['@'], # mute
1500 ['@'], # unmute
1501 ['@'], # muting
1502 ['@'], # block
1503 ['@'], # unblock
1504 ['@'], # report
1505 [
1506 'home',
1507 'all_mem',
1508 'all_sub',
1509 'add',
1510 'rm',
1511 'sub',
1512 'unsub',
1513 'own',
1514 'new',
1515 'update',
1516 'del'
1517 ], # list
1518 [], # cal
1519 g['themes'] + ['current_as_default'], # theme
1520 [
1521 'discover',
1522 'tweets',
1523 'messages',
1524 'friends_and_followers',
1525 'list',
1526 'stream'
1527 ], # help
1528 [], # clear
1529 [], # quit
1530 ]
1531 ))
1532 init_interactive_shell(d)
1533 read_history()
1534 reset()
1535 while True:
1536 if g['prefix']:
1537 line = raw_input(g['decorated_name'])
1538 else:
1539 line = raw_input()
1540 try:
1541 cmd = line.split()[0]
1542 except:
1543 cmd = ''
1544 g['cmd'] = cmd
1545 try:
1546 # Lock the semaphore
1547 db.semaphore_update(True)
1548 # Save cmd to global variable and call process
1549 g['stuff'] = ' '.join(line.split()[1:])
1550 # Process the command
1551 process(cmd)()
1552 # Not re-display
1553 if cmd in ['switch', 't', 'rt', 'rep']:
1554 g['prefix'] = False
1555 else:
1556 g['prefix'] = True
1557 # Release the semaphore lock
1558 db.semaphore_update(False)
1559 except Exception:
1560 printNicely(red('OMG something is wrong with Twitter right now.'))
1561
1562
1563 def stream(domain, args, name='Rainbow Stream'):
1564 """
1565 Track the stream
1566 """
1567
1568 # The Logo
1569 art_dict = {
1570 c['USER_DOMAIN']: name,
1571 c['PUBLIC_DOMAIN']: args.track_keywords,
1572 c['SITE_DOMAIN']: name,
1573 }
1574 if c['ASCII_ART']:
1575 ascii_art(art_dict[domain])
1576
1577 # These arguments are optional:
1578 stream_args = dict(
1579 timeout=args.timeout,
1580 block=not args.no_block,
1581 heartbeat_timeout=args.heartbeat_timeout)
1582
1583 # Track keyword
1584 query_args = dict()
1585 if args.track_keywords:
1586 query_args['track'] = args.track_keywords
1587
1588 # Get stream
1589 stream = TwitterStream(
1590 auth=authen(),
1591 domain=domain,
1592 **stream_args)
1593
1594 try:
1595 if domain == c['USER_DOMAIN']:
1596 tweet_iter = stream.user(**query_args)
1597 elif domain == c['SITE_DOMAIN']:
1598 tweet_iter = stream.site(**query_args)
1599 else:
1600 if args.track_keywords:
1601 tweet_iter = stream.statuses.filter(**query_args)
1602 else:
1603 tweet_iter = stream.statuses.sample()
1604
1605 # Iterate over the stream.
1606 for tweet in tweet_iter:
1607 if tweet is None:
1608 printNicely("-- None --")
1609 elif tweet is Timeout:
1610 printNicely("-- Timeout --")
1611 elif tweet is HeartbeatTimeout:
1612 printNicely("-- Heartbeat Timeout --")
1613 elif tweet is Hangup:
1614 printNicely("-- Hangup --")
1615 elif tweet.get('text'):
1616 draw(
1617 t=tweet,
1618 iot=args.image_on_term,
1619 keyword=args.track_keywords,
1620 check_semaphore=True,
1621 fil=args.filter,
1622 ig=args.ignore,
1623 )
1624 except TwitterHTTPError:
1625 printNicely('')
1626 printNicely(
1627 magenta("We have maximum connection problem with twitter'stream API right now :("))
1628
1629
1630 def fly():
1631 """
1632 Main function
1633 """
1634 # Spawn stream process
1635 args = parse_arguments()
1636 try:
1637 get_decorated_name()
1638
1639 except TwitterHTTPError:
1640 printNicely('')
1641 printNicely(
1642 magenta("Something wrong with Twitter Oauth right now :("))
1643 printNicely(
1644 magenta("Please delete ~/.rainbow_oauth and try again."))
1645 save_history()
1646 os.system('rm -rf rainbow.db')
1647 sys.exit()
1648
1649 p = Process(
1650 target=stream,
1651 args=(
1652 c['USER_DOMAIN'],
1653 args,
1654 g['original_name']))
1655 p.start()
1656
1657 # Start listen process
1658 time.sleep(0.5)
1659 g['reset'] = True
1660 g['prefix'] = True
1661 g['stream_pid'] = p.pid
1662 g['iot'] = args.image_on_term
1663 listen()