def write_contact_jid(self, jid): """ Just write the jid that we are talking to """ self.addstr('[', to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) self.addstr(jid.full, to_curses_attr(get_theme().COLOR_CONVERSATION_NAME)) self.addstr('] ', to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
def callback(iq): if iq['type'] != 'result': if iq['error']['type'] == 'auth': self.core.information( 'You are not allowed to see the activity of this contact.', 'Error') else: self.core.information('Error retrieving the activity', 'Error') return seconds = iq['last_activity']['seconds'] status = iq['last_activity']['status'] from_ = iq['from'] msg = '\x19%s}The last activity of %s was %s ago%s' if not safeJID(from_).user: msg = '\x19%s}The uptime of %s is %s.' % ( dump_tuple(get_theme().COLOR_INFORMATION_TEXT), from_, common.parse_secs_to_str(seconds)) else: msg = '\x19%s}The last activity of %s was %s ago%s' % ( dump_tuple(get_theme().COLOR_INFORMATION_TEXT), from_, common.parse_secs_to_str(seconds), (' and his/her last status was %s' % status) if status else '', ) self.add_message(msg) self.core.refresh_window()
def command_info(self): contact = roster[self.get_dest_jid()] jid = safeJID(self.get_dest_jid()) if contact: if jid.resource: resource = contact[jid.full] else: resource = contact.get_highest_priority_resource() else: resource = None if resource: status = ( 'Status: %s' % resource.status) if resource.status else '' self._text_buffer.add_message( "\x19%(info_col)s}Show: %(show)s, %(status)s\x19o" % { 'show': resource.presence or 'available', 'status': status, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT) }) return True else: self._text_buffer.add_message( "\x19%(info_col)s}No information available\x19o" % {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) return True
def features_checked(self, iq): "Features check callback" features = iq['disco_info'].get_features() or [] before = ('correct' in self.commands, self.remote_supports_attention, self.remote_supports_receipts) correct = self._feature_correct(features) attention = self._feature_attention(features) receipts = self._feature_receipts(features) if (correct, attention, receipts) == before and self.__initial_disco: return else: self.__initial_disco = True if not (correct or attention or receipts): return # don’t display anything ok = get_theme().CHAR_OK nope = get_theme().CHAR_EMPTY correct = ok if correct else nope attention = ok if attention else nope receipts = ok if receipts else nope msg = ('\x19%s}Contact supports: correction [%s], ' 'attention [%s], receipts [%s].') color = dump_tuple(get_theme().COLOR_INFORMATION_TEXT) msg = msg % (color, correct, attention, receipts) self.add_message(msg, typ=0) self.core.refresh_window()
def write_nack(self): color = get_theme().COLOR_CHAR_NACK self._win.attron(to_curses_attr(color)) self.addstr(get_theme().CHAR_NACK) self._win.attroff(to_curses_attr(color)) self.addstr(' ') return poopt.wcswidth(get_theme().CHAR_NACK) + 1
def draw_group_info(self, group: RosterGroup) -> None: """ draw the group information """ self.addstr(0, 0, group.name, to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) self.finish_line(get_theme().COLOR_INFORMATION_BAR)
def write_ack(self) -> int: color = get_theme().COLOR_CHAR_ACK self._win.attron(to_curses_attr(color)) self.addstr(get_theme().CHAR_ACK_RECEIVED) self._win.attroff(to_curses_attr(color)) self.addstr(' ') return poopt.wcswidth(get_theme().CHAR_ACK_RECEIVED) + 1
def refresh(self): self._win.erase() y = -self.scroll_pos i = 0 for name, field in self._form.getFields().items(): if field['type'] == 'hidden': continue self.inputs[i]['label'].resize(1, self.width//2, y + 1, 0) self.inputs[i]['input'].resize(1, self.width//2, y+1, self.width//2) # TODO: display the field description y += 1 i += 1 self._win.refresh() for i, inp in enumerate(self.inputs): if i < self.scroll_pos: continue if i >= self.height + self.scroll_pos: break inp['label'].refresh() inp['input'].refresh() inp['label'].refresh() if self.inputs and self.current_input < self.height-1: self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_SELECTED_ROW) self.inputs[self.current_input]['input'].refresh() self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_SELECTED_ROW) self.inputs[self.current_input]['label'].refresh()
def build_message(self, message, timestamp=False, nick_size=10): txt = message.txt ret = [] default_color = None nick = truncate_nick(message.nickname, nick_size) offset = 0 if nick: offset += poopt.wcswidth(nick) + 1 # + nick + ' ' length if message.str_time: offset += 1 + len(message.str_time) if get_theme().CHAR_TIME_LEFT and message.str_time: offset += 1 if get_theme().CHAR_TIME_RIGHT and message.str_time: offset += 1 lines = poopt.cut_text(txt, self.width-offset-1) prepend = default_color if default_color else '' attrs = [] for line in lines: saved = Line(msg=message, start_pos=line[0], end_pos=line[1], prepend=prepend) attrs = parse_attrs(message.txt[line[0]:line[1]], attrs) if attrs: prepend = FORMAT_CHAR + FORMAT_CHAR.join(attrs) else: if default_color: prepend = default_color else: prepend = '' ret.append(saved) return ret
def on_conversation_say(self, msg, tab): """ On message sent """ name = tab.name jid = safeJID(tab.name) format_dict = { 'jid_c': '\x19%s}' % dump_tuple(get_theme().COLOR_MUC_JID), 'info': '\x19%s}' % dump_tuple(get_theme().COLOR_INFORMATION_TEXT), 'jid': name, } ctx = self.find_encrypted_context_with_matching(jid) default_ctx = self.get_context(name) if ctx is None: ctx = default_ctx if is_relevant(tab) and ctx and ctx.state == STATE_ENCRYPTED: ctx.sendMessage(0, msg['body'].encode('utf-8')) if not tab.send_chat_state('active'): tab.send_chat_state('inactive', always_send=True) tab.add_message( msg['body'], nickname=self.core.own_nick or tab.own_nick, nick_color=get_theme().COLOR_OWN_NICK, identifier=msg['id'], jid=self.core.xmpp.boundjid, typ=ctx.log) # remove everything from the message so that it doesn’t get sent del msg['body'] del msg['replace'] del msg['html'] elif is_relevant(tab) and ctx and ctx.getPolicy('REQUIRE_ENCRYPTION'): warning_msg = MESSAGE_NOT_SENT % format_dict tab.add_message(warning_msg, typ=0) del msg['body'] del msg['replace'] del msg['html'] self.otr_start(tab, name, format_dict) elif not is_relevant(tab) and ctx and ( ctx.state == STATE_ENCRYPTED or ctx.getPolicy('REQUIRE_ENCRYPTION')): contact = roster[tab.name] res = [] if contact: res = [resource.jid for resource in contact.resources] help_msg = '' if res: help_msg = TAB_HELP_RESOURCE % ''.join( ('\n - /message %s' % jid) for jid in res) format_dict['help'] = help_msg warning_msg = INCOMPATIBLE_TAB % format_dict tab.add_message(warning_msg, typ=0) del msg['body'] del msg['replace'] del msg['html']
def refresh(self, txt=None): log.debug('Refresh: %s', self.__class__.__name__) if txt: self.txt = txt self._win.erase() self.addstr(0, 0, self.txt[:self.width-1], to_curses_attr(get_theme().COLOR_WARNING_PROMPT)) self.finish_line(get_theme().COLOR_WARNING_PROMPT) self._refresh()
def go_to_next_horizontal_input(self): if not self.lines: return self.lines[self.current_input][self.current_horizontal_input].set_color(get_theme().COLOR_NORMAL_TEXT) self.current_horizontal_input += 1 if self.current_horizontal_input > 3: self.current_horizontal_input = 0 self.lines[self.current_input][self.current_horizontal_input].set_color(get_theme().COLOR_SELECTED_ROW)
def go_to_previous_horizontal_input(self): if not self.lines: return if self.current_horizontal_input == 0: return self.lines[self.current_input][self.current_horizontal_input].set_color(get_theme().COLOR_NORMAL_TEXT) self.current_horizontal_input -= 1 self.lines[self.current_input][self.current_horizontal_input].set_color(get_theme().COLOR_SELECTED_ROW)
def draw_roster_information(self, roster): """ The header at the top """ self.addstr( 'Roster: %s/%s contacts' % (roster.get_nb_connected_contacts(), len(roster)), to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) self.finish_line(get_theme().COLOR_INFORMATION_BAR)
def refresh(self, txt: Optional[str] = None) -> None: log.debug('Refresh: %s', self.__class__.__name__) if txt is not None: self.txt = txt self._win.erase() self.addstr(0, 0, self.txt[:self.width - 1], to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) self.finish_line(get_theme().COLOR_INFORMATION_BAR) self._refresh()
def add_error(self, error_message): error = '\x19%s}%s\x19o' % (dump_tuple( get_theme().COLOR_CHAR_NACK), error_message) self.add_message(error, highlight=True, nickname='Error', nick_color=get_theme().COLOR_ERROR_MSG, typ=2) self.core.refresh_window()
def draw_roster_information(self, roster: Roster) -> None: """ The header at the top """ self.addstr( 'Roster: %s/%s contacts' % (roster.get_nb_connected_contacts(), len(roster)), to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) self.finish_line(get_theme().COLOR_INFORMATION_BAR)
def write_contact_informations(self, contact): """ Write the informations about the contact """ if not contact: self.addstr("(contact not in roster)", to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) return display_name = contact.name if display_name: self.addstr('%s '%(display_name), to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
def add_error(self, error_message): error = '\x19%s}%s\x19o' % (dump_tuple(get_theme().COLOR_CHAR_NACK), error_message) self.add_message( error, highlight=True, nickname='Error', nick_color=get_theme().COLOR_ERROR_MSG, typ=2) self.core.refresh_window()
def build_message(self, message: Optional[Message], timestamp: bool = False, nick_size: int = 10) -> List[Union[None, Line]]: """ Build a list of lines from a message, without adding it to a list """ if message is None: # line separator return [None] txt = message.txt if not txt: return [] if len(message.str_time) > 8: default_color = ( FORMAT_CHAR + dump_tuple(get_theme().COLOR_LOG_MSG) + '}') # type: Optional[str] else: default_color = None ret = [] # type: List[Union[None, Line]] nick = truncate_nick(message.nickname, nick_size) offset = 0 if message.ack: if message.ack > 0: offset += poopt.wcswidth(get_theme().CHAR_ACK_RECEIVED) + 1 else: offset += poopt.wcswidth(get_theme().CHAR_NACK) + 1 if nick: offset += poopt.wcswidth(nick) + 2 # + nick + '> ' length if message.revisions > 0: offset += ceil(log10(message.revisions + 1)) if message.me: offset += 1 # '* ' before and ' ' after if timestamp: if message.str_time: offset += 1 + len(message.str_time) if get_theme().CHAR_TIME_LEFT and message.str_time: offset += 1 if get_theme().CHAR_TIME_RIGHT and message.str_time: offset += 1 lines = poopt.cut_text(txt, self.width - offset - 1) prepend = default_color if default_color else '' attrs = [] # type: List[str] for line in lines: saved = Line( msg=message, start_pos=line[0], end_pos=line[1], prepend=prepend) attrs = parse_attrs(message.txt[line[0]:line[1]], attrs) if attrs: prepend = FORMAT_CHAR + FORMAT_CHAR.join(attrs) else: if default_color: prepend = default_color else: prepend = '' ret.append(saved) return ret
def draw_status_chatstate(self, y: int, user: User) -> None: show_col = get_theme().color_show(user.show) if user.chatstate == 'composing': char = get_theme().CHAR_CHATSTATE_COMPOSING elif user.chatstate == 'active': char = get_theme().CHAR_CHATSTATE_ACTIVE elif user.chatstate == 'paused': char = get_theme().CHAR_CHATSTATE_PAUSED else: char = get_theme().CHAR_STATUS self.addstr(y, 0, char, to_curses_attr(show_col))
def refresh(self): log.debug('Refresh: %s', self.__class__.__name__) self._win.erase() if self.critical: color = get_theme().COLOR_WARNING_PROMPT else: color = get_theme().COLOR_INFORMATION_BAR c_color = to_curses_attr(color) self.addstr(self.text, c_color) self.finish_line(color) self._refresh()
def refresh(self, name=None, window=None): log.debug('Refresh: %s', self.__class__.__name__) self._win.erase() if name: self.addstr(name, to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) else: self.addstr(self.message, to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) if window: self.print_scroll_position(window) self.finish_line(get_theme().COLOR_INFORMATION_BAR) self._refresh()
def write_contact_jid(self, jid): """ Just displays the resource in an other color """ log.debug("write_contact_jid DynamicConversationInfoWin, jid: %s", jid.resource) self.addstr('[', to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) self.addstr(jid.bare, to_curses_attr(get_theme().COLOR_CONVERSATION_NAME)) if jid.resource: self.addstr("/%s" % (jid.resource,), to_curses_attr(get_theme().COLOR_CONVERSATION_RESOURCE)) self.addstr('] ', to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
def draw_resource_line(self, y, resource, colored): """ Draw a specific resource line """ color = get_theme().color_show(resource.presence) self.addstr(y, 4, get_theme().CHAR_STATUS, to_curses_attr(color)) if colored: self.addstr(y, 8, self.truncate_name(str(resource.jid), 6), to_curses_attr(get_theme().COLOR_SELECTED_ROW)) else: self.addstr(y, 8, self.truncate_name(str(resource.jid), 6)) self.finish_line()
def add_line( tab, text_buffer: TextBuffer, text: str, time: datetime, nick: str, top: bool, ) -> None: """Adds a textual entry in the TextBuffer""" # Convert to local timezone time = time.replace(tzinfo=timezone.utc).astimezone(tz=None) time = time.replace(tzinfo=None) deterministic = config.get_by_tabname('deterministic_nick_colors', tab.jid.bare) if isinstance(tab, tabs.MucTab): nick = nick.split('/')[1] user = tab.get_user_by_name(nick) if deterministic: if user: color = user.color else: theme = get_theme() if theme.ccg_palette: fg_color = colors.ccg_text_to_color( theme.ccg_palette, nick) color = fg_color, -1 else: mod = len(theme.LIST_COLOR_NICKNAMES) nick_pos = int(md5(nick.encode('utf-8')).hexdigest(), 16) % mod color = theme.LIST_COLOR_NICKNAMES[nick_pos] else: color = random.choice(list(xhtml.colors)) color = xhtml.colors.get(color) color = (color, -1) else: nick = nick.split('/')[0] color = get_theme().COLOR_OWN_NICK text_buffer.add_message( txt=text, time=time, nickname=nick, nick_color=color, history=True, user=None, highlight=False, top=top, identifier=None, str_time=None, jid=None, )
def write_resource_information(self, resource): """ Write the information about the resource """ if not resource: presence = "unavailable" else: presence = resource.presence color = get_theme().color_show(presence) self.addstr('[', to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) self.addstr(get_theme().CHAR_STATUS, to_curses_attr(color)) self.addstr(']', to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
def go_to_previous_horizontal_input(self) -> None: if not self.lines: return if self.current_horizontal_input == 0: return self.lines[self.current_input][ self.current_horizontal_input].set_color( get_theme().COLOR_NORMAL_TEXT) self.current_horizontal_input -= 1 self.lines[self.current_input][ self.current_horizontal_input].set_color( get_theme().COLOR_SELECTED_ROW)
def go_to_next_horizontal_input(self) -> None: if not self.lines: return self.lines[self.current_input][ self.current_horizontal_input].set_color( get_theme().COLOR_NORMAL_TEXT) self.current_horizontal_input += 1 if self.current_horizontal_input > 3: self.current_horizontal_input = 0 self.lines[self.current_input][ self.current_horizontal_input].set_color( get_theme().COLOR_SELECTED_ROW)
def write_contact_information(self, contact): """ Write the information about the contact """ if not contact: self.addstr("(contact not in roster)", to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) return display_name = contact.name if display_name: self.addstr('%s ' % (display_name), to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
def refresh(self, filter_t='', filter='', window=None): log.debug('Refresh: %s', self.__class__.__name__) self._win.erase() bar = to_curses_attr(get_theme().COLOR_INFORMATION_BAR) if not filter_t: self.addstr('[No filter]', bar) else: info = '[%s] %s' % (filter_t, filter) self.addstr(info, bar) self.print_scroll_position(window) self.finish_line(get_theme().COLOR_INFORMATION_BAR) self._refresh()
def write_resource_information(self, resource): """ Write the informations about the resource """ if not resource: presence = "unavailable" else: presence = resource.presence color = get_theme().color_show(presence) self.addstr('[', to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) self.addstr(get_theme().CHAR_STATUS, to_curses_attr(color)) self.addstr(']', to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
def command_smp(self, args): """ /otrsmp <ask|answer|abort> [question] [secret] """ if args is None or not args: return self.core.command.help('otrsmp') length = len(args) action = args.pop(0) if length == 2: question = None secret = args.pop(0).encode('utf-8') elif length == 3: question = args.pop(0).encode('utf-8') secret = args.pop(0).encode('utf-8') else: question = secret = None tab = self.api.current_tab() name = tab.name if isinstance(tab, DynamicConversationTab) and tab.locked_resource: name = safeJID(tab.name) name.resource = tab.locked_resource name = name.full format_dict = { 'jid_c': '\x19%s}' % dump_tuple(get_theme().COLOR_MUC_JID), 'info': '\x19%s}' % dump_tuple(get_theme().COLOR_INFORMATION_TEXT), 'jid': name, 'bare_jid': safeJID(name).bare } ctx = self.get_context(name) if ctx.state != STATE_ENCRYPTED: self.api.information('The current conversation is not encrypted', 'Error') return if action == 'ask': ctx.in_smp = True ctx.smp_own = True if question: ctx.smpInit(secret, question) else: ctx.smpInit(secret) tab.add_message(SMP_INITIATED % format_dict, typ=0) elif action == 'answer': ctx.smpGotSecret(secret) elif action == 'abort': if ctx.in_smp: ctx.smpAbort() tab.add_message(SMP_ABORTED % format_dict, typ=0) self.core.refresh_window()
def go_to_previous_line_input(self): if not self.lines: return if self.current_input == 0: return self.lines[self.current_input][self.current_horizontal_input].set_color(get_theme().COLOR_NORMAL_TEXT) self.current_input -= 1 # Adjust the scroll position if the current_input would be outside # of the visible area if self.current_input < self.scroll_pos: self.scroll_pos = self.current_input self.refresh() self.lines[self.current_input][self.current_horizontal_input].set_color(get_theme().COLOR_SELECTED_ROW)
def write_contact_jid(self, jid): """ Just displays the resource in an other color """ log.debug("write_contact_jid DynamicConversationInfoWin, jid: %s", jid.resource) self.addstr('[', to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) self.addstr(jid.bare, to_curses_attr(get_theme().COLOR_CONVERSATION_NAME)) if jid.resource: self.addstr( "/%s" % (jid.resource, ), to_curses_attr(get_theme().COLOR_CONVERSATION_RESOURCE)) self.addstr('] ', to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
def refresh(self, topic: Optional[str] = None) -> None: log.debug('Refresh: %s', self.__class__.__name__) self._win.erase() if topic is not None: msg = topic[:self.width - 1] else: msg = self._message[:self.width - 1] self.addstr(0, 0, msg, to_curses_attr(get_theme().COLOR_TOPIC_BAR)) _, x = self._win.getyx() remaining_size = self.width - x if remaining_size: self.addnstr(' ' * remaining_size, remaining_size, to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) self._refresh()
def __init__(self, txt: str, time: Optional[datetime], nickname: Optional[str], nick_color: Optional[Tuple], history: bool, user: Optional[str], identifier: Optional[str], str_time: Optional[str] = None, highlight: bool = False, old_message: Optional['Message'] = None, revisions: int = 0, jid: Optional[str] = None, ack: int = 0) -> None: """ Create a new Message object with parameters, check for /me messages, and delayed messages """ time = time if time is not None else datetime.now() if txt.startswith('/me '): me = True txt = '\x19%s}%s\x19o' % (dump_tuple(get_theme().COLOR_ME_MESSAGE), txt[4:]) else: me = False if history: txt = txt.replace( '\x19o', '\x19o\x19%s}' % dump_tuple(get_theme().COLOR_LOG_MSG)) str_time = time.strftime("%Y-%m-%d %H:%M:%S") else: if str_time is None: str_time = time.strftime("%H:%M:%S") else: str_time = '' self.txt = txt.replace('\t', ' ') + '\x19o' self.nick_color = nick_color self.time = time self.str_time = str_time self.nickname = nickname self.user = user self.identifier = identifier self.highlight = highlight self.me = me self.old_message = old_message self.revisions = revisions self.jid = jid self.ack = ack
def on_conversation_say(self, msg, tab): """ On message sent """ if isinstance(tab, DynamicConversationTab) and tab.locked_resource: jid = safeJID(tab.name) jid.resource = tab.locked_resource name = jid.full else: name = tab.name jid = safeJID(tab.name) format_dict = { 'jid_c': '\x19%s}' % dump_tuple(get_theme().COLOR_MUC_JID), 'info': '\x19%s}' % dump_tuple(get_theme().COLOR_INFORMATION_TEXT), 'jid': name, } ctx = None default_ctx = self.get_context(name) if isinstance(tab, DynamicConversationTab) and not tab.locked_resource: log.debug('Unlocked tab %s found, falling back to the first encrypted chat we find.', name) ctx = self.find_encrypted_context_with_matching(jid.bare) if ctx is None: ctx = default_ctx if ctx and ctx.state == STATE_ENCRYPTED: ctx.sendMessage(0, msg['body'].encode('utf-8')) if not tab.send_chat_state('active'): tab.send_chat_state('inactive', always_send=True) tab.add_message(msg['body'], nickname=self.core.own_nick or tab.own_nick, nick_color=get_theme().COLOR_OWN_NICK, identifier=msg['id'], jid=self.core.xmpp.boundjid, typ=ctx.log) # remove everything from the message so that it doesn’t get sent del msg['body'] del msg['replace'] del msg['html'] elif ctx and ctx.getPolicy('REQUIRE_ENCRYPTION'): tab.add_message(MESSAGE_NOT_SENT % format_dict, typ=0) del msg['body'] del msg['replace'] del msg['html'] self.otr_start(tab, name, format_dict)
def make_line( tab: tabs.ChatTab, text: str, time: datetime, jid: JID, identifier: str = '', deterministic: bool = True, ) -> Message: """Adds a textual entry in the TextBuffer""" # Convert to local timezone time = time.replace(tzinfo=timezone.utc).astimezone(tz=None) time = time.replace(tzinfo=None) if isinstance(tab, tabs.MucTab): nick = jid.resource user = tab.get_user_by_name(nick) if deterministic: if user: color = user.color else: theme = get_theme() if theme.ccg_palette: fg_color = colors.ccg_text_to_color(theme.ccg_palette, nick) color = fg_color, -1 else: mod = len(theme.LIST_COLOR_NICKNAMES) nick_pos = int(md5(nick.encode('utf-8')).hexdigest(), 16) % mod color = theme.LIST_COLOR_NICKNAMES[nick_pos] else: color = random.choice(list(xhtml.colors)) color = xhtml.colors.get(color) color = (color, -1) else: if jid.bare == tab.core.xmpp.boundjid.bare: nick = tab.core.own_nick color = get_theme().COLOR_OWN_NICK else: color = get_theme().COLOR_REMOTE_USER nick = tab.get_nick() return Message( txt=text, identifier=identifier, time=time, nickname=nick, nick_color=color, history=True, user=None, )
def __init__(self, txt, time, nickname, nick_color, history, user, identifier, str_time=None, highlight=False, old_message=None, revisions=0, jid=None, ack=0): """ Create a new Message object with parameters, check for /me messages, and delayed messages """ time = time or datetime.now() if txt.startswith('/me '): me = True txt = '\x19%s}%s\x19o' % (dump_tuple(get_theme().COLOR_ME_MESSAGE), txt[4:]) else: me = False if history: txt = txt.replace( '\x19o', '\x19o\x19%s}' % dump_tuple(get_theme().COLOR_LOG_MSG)) str_time = time.strftime("%Y-%m-%d %H:%M:%S") else: if str_time is None: str_time = time.strftime("%H:%M:%S") else: str_time = '' self.txt = txt.replace('\t', ' ') + '\x19o' self.nick_color = nick_color self.time = time self.str_time = str_time self.nickname = nickname self.user = user self.identifier = identifier self.highlight = highlight self.me = me self.old_message = old_message self.revisions = revisions self.jid = jid self.ack = ack
def draw_plus(self, y: int) -> None: """ Draw the indicator that shows that the list is longer than what is displayed """ self.addstr(y, self.width - 5, '++++', to_curses_attr(get_theme().COLOR_MORE_INDICATOR))
def write_room_name(self, name): jid = safeJID(name) room_name, nick = jid.bare, jid.resource theme = get_theme() self.addstr(nick, to_curses_attr(theme.COLOR_PRIVATE_NAME)) txt = ' from room %s' % room_name self.addstr(txt, to_curses_attr(theme.COLOR_INFORMATION_BAR))
def update_status(self, status): old_status = self.__status if not (old_status.show != status.show or old_status.message != status.message): return self.__status = status hide_status_change = config.get_by_tabname('hide_status_change', self.jid.bare) now = datetime.now() dff = now - self.last_remote_message if hide_status_change > -1 and dff.total_seconds() > hide_status_change: return info_c = dump_tuple(get_theme().COLOR_INFORMATION_TEXT) nick = self.get_nick() remote = self.remote_user_color() msg = '\x19%(color)s}%(nick)s\x19%(info)s} changed: ' msg %= {'color': remote, 'nick': nick, 'info': info_c} if status.message != old_status.message and status.message: msg += 'status: %s, ' % status.message if status.show in SHOW_NAME: msg += 'show: %s, ' % SHOW_NAME[status.show] self.add_message( InfoMessage(txt=msg[:-2]), typ=2, )
def refresh(self) -> None: self._win.erase() # draw QR code code = qrcode.QRCode() code.add_data(self.qr) out = io.StringIO() code.print_ascii(out, invert=self.inverted) self.addstr(" " + self.qr + "\n") self.addstr(out.getvalue(), to_curses_attr((15, 0))) self.addstr(" ") col = to_curses_attr(get_theme().COLOR_TAB_NORMAL) if self.invert: self.addstr(self.str_invert, col) else: self.addstr(self.str_invert) self.addstr(" ") if self.invert: self.addstr(self.str_close) else: self.addstr(self.str_close, col) self._refresh()
def write_disconnected(self, room): """ Shows a message if the room is not joined """ if not room.joined: self.addstr(' -!- Not connected ', to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
def command_say(self, line, attention=False, correct=False): msg = self.core.xmpp.make_message(self.get_dest_jid()) msg['type'] = 'chat' msg['body'] = line if not self.nick_sent: msg['nick'] = self.core.own_nick self.nick_sent = True # trigger the event BEFORE looking for colors. # and before displaying the message in the window # This lets a plugin insert \x19xxx} colors, that will # be converted in xhtml. self.core.events.trigger('conversation_say', msg, self) if not msg['body']: self.cancel_paused_delay() self.text_win.refresh() self.input.refresh() return replaced = False if correct or msg['replace']['id']: msg['replace']['id'] = self.last_sent_message['id'] if config.get_by_tabname('group_corrections', self.name): try: self.modify_message(msg['body'], self.last_sent_message['id'], msg['id'], jid=self.core.xmpp.boundjid, nickname=self.core.own_nick) replaced = True except CorrectionError: log.error('Unable to correct a message', exc_info=True) else: del msg['replace'] if msg['body'].find('\x19') != -1: msg.enable('html') msg['html']['body'] = xhtml.poezio_colors_to_html(msg['body']) msg['body'] = xhtml.clean_text(msg['body']) if (config.get_by_tabname('send_chat_states', self.general_jid) and self.remote_wants_chatstates is not False): needed = 'inactive' if self.inactive else 'active' msg['chat_state'] = needed if attention and self.remote_supports_attention: msg['attention'] = True self.core.events.trigger('conversation_say_after', msg, self) if not msg['body']: self.cancel_paused_delay() self.text_win.refresh() self.input.refresh() return if not replaced: self.add_message(msg['body'], nickname=self.core.own_nick, nick_color=get_theme().COLOR_OWN_NICK, identifier=msg['id'], jid=self.core.xmpp.boundjid, typ=1) self.last_sent_message = msg if self.remote_supports_receipts: msg._add_receipt = True msg.send() self.cancel_paused_delay() self.text_win.refresh() self.input.refresh()
def __init__(self, field): FieldInputMixin.__init__(self, field) Input.__init__(self) self.text = field.get_value() if isinstance(field.get_value(), str)\ else "" self.pos = len(self.text) self.color = get_theme().COLOR_NORMAL_TEXT
def refresh(self) -> None: # store the cursor status self._win.erase() y = -self.scroll_pos for i in range(len(self.lines)): self.lines[i][0].resize(1, self.width // 4, y + 1, 0) self.lines[i][1].resize(1, self.width // 4, y + 1, self.width // 4) self.lines[i][2].resize(1, self.width // 6, y + 1, 3 * self.width // 6) self.lines[i][3].resize(1, self.width // 6, y + 1, 4 * self.width // 6) self.lines[i][4].resize(1, self.width // 6, y + 1, 5 * self.width // 6) y += 1 self._refresh() for i, inp in enumerate(self.lines): if i < self.scroll_pos: continue if i >= self.height + self.scroll_pos: break for j in range(4): inp[j].refresh() if self.lines and self.current_input < self.height - 1: self.lines[self.current_input][ self.current_horizontal_input].set_color( get_theme().COLOR_SELECTED_ROW) self.lines[self.current_input][ self.current_horizontal_input].refresh() if not self.lines: curses.curs_set(0) else: curses.curs_set(1)
def refresh(self, jid, contact, window, chatstate, information): # contact can be None, if we receive a message # from someone not in our roster. In this case, we display # only the maximum information from the message we can get. log.debug('Refresh: %s', self.__class__.__name__) jid = safeJID(jid) if contact: if jid.resource: resource = contact[jid.full] else: resource = contact.get_highest_priority_resource() else: resource = None # if contact is None, then resource is None too: # user is not in the roster so we know almost nothing about it # If contact is a Contact, then # resource can now be a Resource: user is in the roster and online # or resource is None: user is in the roster but offline self._win.erase() if config.get('show_jid_in_conversations'): self.write_contact_jid(jid) self.write_contact_information(contact) self.write_resource_information(resource) self.print_scroll_position(window) self.write_chatstate(chatstate) self.write_additional_information(information, jid) self.finish_line(get_theme().COLOR_INFORMATION_BAR) self._refresh()
def write_pre_msg(self, msg, with_timestamps, nick_size) -> int: offset = 0 if with_timestamps: offset += self.write_time(msg.str_time) if not msg.nickname: # not a message, nothing to do afterwards return offset nick = truncate_nick(msg.nickname, nick_size) offset += poopt.wcswidth(nick) if msg.nick_color: color = msg.nick_color elif msg.user: color = msg.user.color else: color = None if msg.ack: if msg.ack > 0: offset += self.write_ack() else: offset += self.write_nack() if msg.me: self._win.attron(to_curses_attr(get_theme().COLOR_ME_MESSAGE)) self.addstr('* ') self.write_nickname(nick, color, msg.highlight) offset += self.write_revisions(msg) self.addstr(' ') offset += 3 else: self.write_nickname(nick, color, msg.highlight) offset += self.write_revisions(msg) self.addstr('> ') offset += 2 return offset