From 67c663f814e895d4cb8ec95ee76d60db1456c6c5 Mon Sep 17 00:00:00 2001 From: Orakaro Date: Mon, 25 Aug 2014 00:46:19 +0900 Subject: [PATCH] prototype for message thread --- docs/conf.py | 4 +- rainbowstream/colorset/larapaste.json | 10 +- rainbowstream/colorset/monokai.json | 8 +- rainbowstream/colorset/solarized.json | 10 +- rainbowstream/colorset/tomorrow_night.json | 10 +- rainbowstream/draw.py | 106 ++++++++++++++++++++- rainbowstream/rainbow.py | 83 +++++++++------- setup.py | 2 +- 8 files changed, 177 insertions(+), 56 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index ece453c..0aff2ba 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -48,9 +48,9 @@ copyright = u'2014, Vu Nhat Minh' # built documents. # # The short X.Y version. -version = '0.8.6' +version = '0.8.7' # The full version, including alpha/beta/rc tags. -release = '0.8.6' +release = '0.8.7' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/rainbowstream/colorset/larapaste.json b/rainbowstream/colorset/larapaste.json index c91dcb6..3f4011e 100644 --- a/rainbowstream/colorset/larapaste.json +++ b/rainbowstream/colorset/larapaste.json @@ -25,10 +25,10 @@ "TWEET" : { "nick" : 37, "clock" : 184, - "id" : 202, + "id" : 184, "favorited" : 154, - "retweet_count" : 202, - "favorite_count" : 154, + "retweet_count" : 154, + "favorite_count" : 202, "rt" : 202, "link" : 154, "hashtag" : 37, @@ -36,8 +36,8 @@ }, "MESSAGE" : { - "sender" : 37, - "recipient" : 37, + "partner" : 37, + "me" : 37, "to" : 154, "clock" : 184, "id" : 202 diff --git a/rainbowstream/colorset/monokai.json b/rainbowstream/colorset/monokai.json index 4365b7c..3473aea 100644 --- a/rainbowstream/colorset/monokai.json +++ b/rainbowstream/colorset/monokai.json @@ -27,8 +27,8 @@ "clock" : 57, "id" : 166, "favorited" : 50, - "retweet_count" : 198, - "favorite_count" : 50, + "retweet_count" : 50, + "favorite_count" : 198, "rt" : 179, "link" : 74, "hashtag" : 198, @@ -36,8 +36,8 @@ }, "MESSAGE" : { - "sender" : 112, - "recipient" : 112, + "partner" : 112, + "me" : 112, "to" : 50, "clock" : 57, "id" : 166 diff --git a/rainbowstream/colorset/solarized.json b/rainbowstream/colorset/solarized.json index 6340d74..a0ee32f 100644 --- a/rainbowstream/colorset/solarized.json +++ b/rainbowstream/colorset/solarized.json @@ -25,10 +25,10 @@ "TWEET" : { "nick" : 64, "clock" : 32, - "id" : 124, + "id" : 130, "favorited" : 64, - "retweet_count" : 130, - "favorite_count" : 64, + "retweet_count" : 64, + "favorite_count" : 124, "rt" : 66, "link" : 23, "hashtag" : 64, @@ -36,8 +36,8 @@ }, "MESSAGE" : { - "sender" : 64, - "recipient" : 64, + "partner" : 64, + "me" : 64, "to" : 130, "clock" : 32, "id" : 124 diff --git a/rainbowstream/colorset/tomorrow_night.json b/rainbowstream/colorset/tomorrow_night.json index 1199e16..80557ba 100644 --- a/rainbowstream/colorset/tomorrow_night.json +++ b/rainbowstream/colorset/tomorrow_night.json @@ -25,10 +25,10 @@ "TWEET" : { "nick" : 67, "clock" : 58, - "id" : 166, + "id" : 58, "favorited" : 97, - "retweet_count" : 166, - "favorite_count" : 97, + "retweet_count" : 97, + "favorite_count" : 166, "rt" : 145, "link" : 30, "hashtag" : 67, @@ -36,8 +36,8 @@ }, "MESSAGE" : { - "sender" : 67, - "recipient" : 67, + "partner" : 67, + "me" : 67, "to" : 97, "clock" : 58, "id" : 166 diff --git a/rainbowstream/draw.py b/rainbowstream/draw.py index bfa3e2c..e123ba9 100644 --- a/rainbowstream/draw.py +++ b/rainbowstream/draw.py @@ -1,10 +1,10 @@ import random import itertools import requests -import time import locale import arrow import re +import os from twitter.util import printNicely from functools import wraps @@ -310,6 +310,110 @@ def draw(t, keyword=None, humanize=True, fil=[], ig=[]): printNicely(red('Sorry, image link is broken')) +def print_threads(d): + """ + Print threads of messages + """ + id = 1 + rel = {} + for partner in d: + messages = d[partner] + count = len(messages) + screen_name = '@' + partner[0] + name = partner[1] + screen_name = color_func(c['MESSAGE']['partner'])(screen_name) + name = cycle_color(name) + thread_id = color_func(c['MESSAGE']['id'])('thread id:'+str(id)) + line = ' '*2 + name + ' ' + screen_name + \ + ' (' + str(count) + ' message) ' + thread_id + printNicely(line) + rel[id] = partner + id += 1 + dg['thread'] = d + return rel + + +def print_thread(partner, me_nick, me_name): + """ + Print a thread of messages + """ + # Sort messages by time + messages = dg['thread'][partner] + messages.sort(key = lambda x:parser.parse(x['created_at'])) + + # Print the 1st line + dg['message_thread_margin'] = margin = 2 + left_size = len(partner[0])+len(partner[1]) + margin + right_size = len(me_nick) + len(me_name) + margin + partner_screen_name = color_func(c['MESSAGE']['partner'])('@' + partner[0]) + partner_name = cycle_color(partner[1]) + me_screen_name = color_func(c['MESSAGE']['me'])('@' + me_nick) + me_name = cycle_color(me_name) + left = ' ' * margin + partner_name + ' ' + partner_screen_name + right = me_name + ' ' + me_screen_name + ' ' * margin + h, w = os.popen('stty size', 'r').read().split() + w = int(w) + line = '{}{}{}'.format(left, ' '*(w - left_size - right_size - 2 * margin), right) + printNicely('') + printNicely(line) + printNicely('') + + # Print messages + for m in messages: + if m['sender_screen_name'] == me_nick: + print_right_message(m) + elif m['recipient_screen_name'] == me_nick: + print_left_message(m) + + +def print_right_message(m): + """ + Print a message on the right of screen + """ + h, w = os.popen('stty size', 'r').read().split() + w = int(w) + frame_width = w //3 - dg['message_thread_margin'] + step = frame_width - 2 * dg['message_thread_margin'] + slicing = [m['text'][i:i+step] for i in range(0, len(m['text']), step)] + spaces = w - frame_width - dg['message_thread_margin'] + dotline = ' ' * spaces + '-' * frame_width + + printNicely(dotline) + for line in slicing: + fill = step - len(line) + screen_line = ' ' * spaces + '| ' + line + ' ' * fill + ' ' + if slicing[-1] == line: + screen_line = screen_line + ' >' + else: + screen_line = screen_line + '|' + printNicely(screen_line) + printNicely(dotline) + + +def print_left_message(m): + """ + Print a message on the left of screen + """ + h, w = os.popen('stty size', 'r').read().split() + w = int(w) + frame_width = w //3 - dg['message_thread_margin'] + step = frame_width - 2 * dg['message_thread_margin'] + slicing = [m['text'][i:i+step] for i in range(0, len(m['text']), step)] + spaces = dg['message_thread_margin'] + dotline = ' ' * spaces + '-' * frame_width + + printNicely(dotline) + for line in slicing: + fill = step - len(line) + screen_line = ' ' + line + ' ' * fill + ' |' + if slicing[-1] == line: + screen_line = ' ' * (spaces-1) + '< ' + screen_line + else: + screen_line = ' ' * spaces + '|' + screen_line + printNicely(screen_line) + printNicely(dotline) + + def print_message(m): """ Print direct message diff --git a/rainbowstream/rainbow.py b/rainbowstream/rainbow.py index 94b2e4b..6bd1720 100644 --- a/rainbowstream/rainbow.py +++ b/rainbowstream/rainbow.py @@ -117,10 +117,13 @@ def init(args): signal.signal(signal.SIGINT, ctrl_c_handler) # Get name t = Twitter(auth=authen()) - name = '@' + t.account.verify_credentials()['screen_name'] + credential = t.account.verify_credentials() + screen_name = '@' + credential['screen_name'] + name = credential['name'] if not get_config('PREFIX'): - set_config('PREFIX', name) - g['original_name'] = name[1:] + set_config('PREFIX', screen_name) + g['original_name'] = screen_name[1:] + g['full_name'] = name g['decorated_name'] = lambda x: color_func( c['DECORATED_NAME'])('[' + x + ']: ') # Theme init @@ -128,6 +131,7 @@ def init(args): themes = [f.split('.')[0] for f in files if f.split('.')[-1] == 'json'] g['themes'] = themes g['pause'] = False + g['message_threads'] = {} # Startup cmd g['cmd'] = '' # Semaphore init @@ -470,17 +474,17 @@ def urlopen(): def inbox(): """ - Inbox direct messages + Inbox threads """ t = Twitter(auth=authen()) num = c['MESSAGES_DISPLAY'] - rel = [] if g['stuff'].isdigit(): num = g['stuff'] + # Get inbox messages cur_page = 1 - # Max message per page is 20 so we have to loop + inbox = [] while num > 20: - rel = rel + t.direct_messages( + inbox = inbox + t.direct_messages( count=20, page=cur_page, include_entities=False, @@ -488,32 +492,20 @@ def inbox(): ) num -= 20 cur_page += 1 - rel = rel + t.direct_messages( + inbox = inbox + t.direct_messages( count=num, page=cur_page, include_entities=False, skip_status=False ) - # Display - printNicely('Inbox: newest ' + str(len(rel)) + ' messages.') - for m in reversed(rel): - print_message(m) - printNicely('') - - -def sent(): - """ - Sent direct messages - """ - t = Twitter(auth=authen()) + # Get sent messages num = c['MESSAGES_DISPLAY'] - rel = [] if g['stuff'].isdigit(): - num = int(g['stuff']) + num = g['stuff'] cur_page = 1 - # Max message per page is 20 so we have to loop + sent = [] while num > 20: - rel = rel + t.direct_messages.sent( + sent = sent + t.direct_messages.sent( count=20, page=cur_page, include_entities=False, @@ -521,17 +513,42 @@ def sent(): ) num -= 20 cur_page += 1 - rel = rel + t.direct_messages.sent( + sent = sent + t.direct_messages.sent( count=num, page=cur_page, include_entities=False, skip_status=False ) - # Display - printNicely('Sent: newest ' + str(len(rel)) + ' messages.') - for m in reversed(rel): - print_message(m) - printNicely('') + + d = {} + uniq_inbox = list(set( + [(m['sender_screen_name'],m['sender']['name']) for m in inbox] + )) + uniq_sent= list(set( + [(m['recipient_screen_name'],m['recipient']['name']) for m in sent] + )) + for partner in uniq_inbox: + inbox_ary = [m for m in inbox if m['sender_screen_name'] == partner[0]] + sent_ary = [m for m in sent if m['recipient_screen_name'] == partner[0]] + d[partner] = inbox_ary + sent_ary + for partner in uniq_sent: + if partner not in d: + d[partner] = [m for m in sent if m['recipient_screen_name'] == partner[0]] + g['message_threads'] = print_threads(d) + + +def thread(): + """ + View a thread of message + """ + try: + thread_id = int(g['stuff']) + print_thread(g['message_threads'][thread_id],g['original_name'],g['full_name']) + except Exception as e: + print(e) + import traceback + print(traceback.format_exc()) + printNicely(red('No such thread.')) def message(): @@ -1520,7 +1537,7 @@ cmdset = [ 'open', 'ls', 'inbox', - 'sent', + 'thread', 'trash', 'whois', 'fl', @@ -1564,7 +1581,7 @@ funcset = [ urlopen, ls, inbox, - sent, + thread, trash, whois, follow, @@ -1621,7 +1638,7 @@ def listen(): [''], # open url ['fl', 'fr'], # list [], # inbox - [], # sent + [i for i in g['message_threads']], #sent [], # trash ['@'], # whois ['@'], # follow diff --git a/setup.py b/setup.py index a4e6dba..8a1cf09 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ import os import os.path # Bumped version -version = '0.8.6' +version = '0.8.7' # Require install_requires = [ -- 2.25.1