Example #1
0
 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))
Example #2
0
 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()
Example #3
0
 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
Example #4
0
    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()
Example #5
0
 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
Example #6
0
 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)
Example #7
0
 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
Example #8
0
 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()
Example #9
0
 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
Example #10
0
File: otr.py Project: louiz/poezio
    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)
Example #14
0
 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)
Example #15
0
 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()
Example #16
0
 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()
Example #17
0
 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)
Example #18
0
 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()
Example #19
0
 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))
Example #20
0
 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()
Example #21
0
 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
Example #22
0
 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))
Example #23
0
 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()
Example #24
0
 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()
Example #25
0
 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))
Example #26
0
 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()
Example #27
0
 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()
Example #28
0
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,
    )
Example #29
0
 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))
Example #30
0
 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)
Example #31
0
 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)
Example #32
0
 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))
Example #33
0
 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()
Example #34
0
 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))
Example #35
0
 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()
Example #36
0
 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()
Example #37
0
    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()
Example #38
0
    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)
Example #40
0
 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()
Example #41
0
 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))
Example #42
0
 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()
Example #43
0
    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
Example #44
0
    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)
Example #45
0
    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)
Example #46
0
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,
    )
Example #47
0
    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
Example #48
0
 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))
Example #49
0
 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))
Example #50
0
    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,
        )
Example #51
0
    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()
Example #52
0
 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))
Example #53
0
    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()
Example #54
0
 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
Example #55
0
    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)
Example #56
0
 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()
Example #57
0
    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