Pass a message to add_message instead of messed up kwargs everywhere

Changes LOTS of things
This commit is contained in:
mathieui 2019-09-29 18:12:48 +02:00
parent fefbb0b088
commit a5e9280047
18 changed files with 411 additions and 336 deletions

View file

@ -4,11 +4,12 @@ date has changed.
"""
from gettext import gettext as _
from poezio.plugin import BasePlugin
import datetime
from poezio import tabs
from poezio import timed_events
from gettext import gettext as _
from poezio import timed_events, tabs
from poezio.plugin import BasePlugin
from poezio.ui.types import InfoMessage
class Plugin(BasePlugin):
@ -30,7 +31,7 @@ class Plugin(BasePlugin):
for tab in self.core.tabs:
if isinstance(tab, tabs.ChatTab):
tab.add_message(msg)
tab.add_message(InfoMessage(msg))
self.core.refresh_window()
self.schedule_event()

View file

@ -16,6 +16,7 @@ Usage
from poezio import tabs
from poezio.plugin import BasePlugin
from poezio.theming import get_theme
from poezio.ui.types import Message
class Plugin(BasePlugin):
@ -37,11 +38,13 @@ class Plugin(BasePlugin):
if not isinstance(tab, tabs.MucTab):
message['type'] = 'chat'
tab.add_message(
message['body'],
nickname=tab.core.own_nick,
nick_color=get_theme().COLOR_OWN_NICK,
identifier=message['id'],
jid=tab.core.xmpp.boundjid,
Message(
message['body'],
nickname=tab.core.own_nick,
nick_color=get_theme().COLOR_OWN_NICK,
identifier=message['id'],
jid=tab.core.xmpp.boundjid,
),
typ=1,
)
message.send()

View file

@ -17,7 +17,8 @@ from datetime import datetime
from poezio.plugin import BasePlugin
from poezio import tabs
from poezio.text_buffer import Message, TextBuffer
from poezio.text_buffer import TextBuffer
from poezio.ui.types import InfoMessage
def add_line(
@ -26,18 +27,7 @@ def add_line(
datetime: Optional[datetime] = None,
) -> None:
"""Adds a textual entry in the TextBuffer"""
text_buffer.add_message(
text,
datetime, # Time
None, # Nickname
None, # Nick Color
False, # History
None, # User
False, # Highlight
None, # Identifier
None, # str_time
None, # Jid
)
text_buffer.add_message(InfoMessage(text, time=datetime))
class Plugin(BasePlugin):

View file

@ -205,6 +205,7 @@ from poezio.tabs import StaticConversationTab, PrivateTab
from poezio.theming import get_theme, dump_tuple
from poezio.decorators import command_args_parser
from poezio.core.structs import Completion
from poezio.ui.types import InfoMessage, Message
POLICY_FLAGS = {
'ALLOW_V1': False,
@ -385,25 +386,30 @@ class PoezioContext(Context):
log.debug('OTR conversation with %s refreshed', self.peer)
if self.getCurrentTrust():
msg = OTR_REFRESH_TRUSTED % format_dict
tab.add_message(msg, typ=self.log)
tab.add_message(InfoMessage(msg), typ=self.log)
else:
msg = OTR_REFRESH_UNTRUSTED % format_dict
tab.add_message(msg, typ=self.log)
tab.add_message(InfoMessage(msg), typ=self.log)
hl(tab)
elif newstate == STATE_FINISHED or newstate == STATE_PLAINTEXT:
log.debug('OTR conversation with %s finished', self.peer)
if tab:
tab.add_message(OTR_END % format_dict, typ=self.log)
tab.add_message(InfoMessage(OTR_END % format_dict), typ=self.log)
hl(tab)
elif newstate == STATE_ENCRYPTED and tab:
if self.getCurrentTrust():
tab.add_message(OTR_START_TRUSTED % format_dict, typ=self.log)
tab.add_message(InfoMessage(OTR_START_TRUSTED % format_dict), typ=self.log)
else:
format_dict['our_fpr'] = self.user.getPrivkey()
format_dict['remote_fpr'] = self.getCurrentKey()
tab.add_message(OTR_TUTORIAL % format_dict, typ=0)
tab.add_message(
OTR_START_UNTRUSTED % format_dict, typ=self.log)
InfoMessage(OTR_TUTORIAL % format_dict),
typ=0
)
tab.add_message(
InfoMessage(OTR_START_UNTRUSTED % format_dict),
typ=self.log,
)
hl(tab)
log.debug('Set encryption state of %s to %s', self.peer,
@ -639,7 +645,7 @@ class Plugin(BasePlugin):
# Received an OTR error
proto_error = err.args[0].error # pylint: disable=no-member
format_dict['err'] = proto_error.decode('utf-8', errors='replace')
tab.add_message(OTR_ERROR % format_dict, typ=0)
tab.add_message(InfoMessage(OTR_ERROR % format_dict), typ=0)
del msg['body']
del msg['html']
hl(tab)
@ -649,7 +655,7 @@ class Plugin(BasePlugin):
# Encrypted message received, but unreadable as we do not have
# an OTR session in place.
text = MESSAGE_UNREADABLE % format_dict
tab.add_message(text, jid=msg['from'], typ=0)
tab.add_message(InfoMessage(text), typ=0)
hl(tab)
del msg['body']
del msg['html']
@ -658,7 +664,7 @@ class Plugin(BasePlugin):
except crypt.InvalidParameterError:
# Malformed OTR payload and stuff
text = MESSAGE_INVALID % format_dict
tab.add_message(text, jid=msg['from'], typ=0)
tab.add_message(InfoMessage(text), typ=0)
hl(tab)
del msg['body']
del msg['html']
@ -669,7 +675,7 @@ class Plugin(BasePlugin):
import traceback
exc = traceback.format_exc()
format_dict['exc'] = exc
tab.add_message(POTR_ERROR % format_dict, typ=0)
tab.add_message(InfoMessage(POTR_ERROR % format_dict), typ=0)
log.error('Unspecified error in the OTR plugin', exc_info=True)
return
# No error, proceed with the message
@ -688,10 +694,10 @@ class Plugin(BasePlugin):
abort = get_tlv(tlvs, potr.proto.SMPABORTTLV)
if abort:
ctx.reset_smp()
tab.add_message(SMP_ABORTED_PEER % format_dict, typ=0)
tab.add_message(InfoMessage(SMP_ABORTED_PEER % format_dict), typ=0)
elif ctx.in_smp and not ctx.smpIsValid():
ctx.reset_smp()
tab.add_message(SMP_ABORTED % format_dict, typ=0)
tab.add_message(InfoMessage(SMP_ABORTED % format_dict), typ=0)
elif smp1 or smp1q:
# Received an SMP request (with a question or not)
if smp1q:
@ -709,22 +715,22 @@ class Plugin(BasePlugin):
# we did not initiate it
ctx.smp_own = False
format_dict['q'] = question
tab.add_message(SMP_REQUESTED % format_dict, typ=0)
tab.add_message(InfoMessage(SMP_REQUESTED % format_dict), typ=0)
elif smp2:
# SMP reply received
if not ctx.in_smp:
ctx.reset_smp()
else:
tab.add_message(SMP_PROGRESS % format_dict, typ=0)
tab.add_message(InfoMessage(SMP_PROGRESS % format_dict), typ=0)
elif smp3 or smp4:
# Type 4 (SMP message 3) or 5 (SMP message 4) TLVs received
# in both cases it is the final message of the SMP exchange
if ctx.smpIsSuccess():
tab.add_message(SMP_SUCCESS % format_dict, typ=0)
tab.add_message(InfoMessage(SMP_SUCCESS % format_dict), typ=0)
if not ctx.getCurrentTrust():
tab.add_message(SMP_RECIPROCATE % format_dict, typ=0)
tab.add_message(InfoMessage(SMP_RECIPROCATE % format_dict), typ=0)
else:
tab.add_message(SMP_FAIL % format_dict, typ=0)
tab.add_message(InfoMessage(SMP_FAIL % format_dict), typ=0)
ctx.reset_smp()
hl(tab)
self.core.refresh_window()
@ -780,12 +786,15 @@ class Plugin(BasePlugin):
if decode_newlines:
body = body.replace('<br/>', '\n').replace('<br>', '\n')
tab.add_message(
body,
nickname=tab.nick,
jid=msg['from'],
forced_user=user,
Message(
body,
nickname=tab.nick,
jid=msg['from'],
user=user,
nick_color=nick_color
),
typ=ctx.log,
nick_color=nick_color)
)
hl(tab)
self.core.refresh_window()
del msg['body']
@ -826,19 +835,22 @@ class Plugin(BasePlugin):
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)
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 doesnt 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)
tab.add_message(InfoMessage(warning_msg), typ=0)
del msg['body']
del msg['replace']
del msg['html']
@ -856,7 +868,7 @@ class Plugin(BasePlugin):
('\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)
tab.add_message(InfoMessage(warning_msg), typ=0)
del msg['body']
del msg['replace']
del msg['html']
@ -900,22 +912,22 @@ class Plugin(BasePlugin):
self.otr_start(tab, name, format_dict)
elif action == 'ourfpr':
format_dict['fpr'] = self.account.getPrivkey()
tab.add_message(OTR_OWN_FPR % format_dict, typ=0)
tab.add_message(InfoMessage(OTR_OWN_FPR % format_dict), typ=0)
elif action == 'fpr':
if name in self.contexts:
ctx = self.contexts[name]
if ctx.getCurrentKey() is not None:
format_dict['fpr'] = ctx.getCurrentKey()
tab.add_message(OTR_REMOTE_FPR % format_dict, typ=0)
tab.add_message(InfoMessage(OTR_REMOTE_FPR % format_dict), typ=0)
else:
tab.add_message(OTR_NO_FPR % format_dict, typ=0)
tab.add_message(InfoMessage(OTR_NO_FPR % format_dict), typ=0)
elif action == 'drop':
# drop the privkey (and obviously, end the current conversations before that)
for context in self.contexts.values():
if context.state not in (STATE_FINISHED, STATE_PLAINTEXT):
context.disconnect()
self.account.drop_privkey()
tab.add_message(KEY_DROPPED % format_dict, typ=0)
tab.add_message(InfoMessage(KEY_DROPPED % format_dict), typ=0)
elif action == 'trust':
ctx = self.get_context(name)
key = ctx.getCurrentKey()
@ -927,7 +939,7 @@ class Plugin(BasePlugin):
format_dict['key'] = key
ctx.setTrust(fpr, 'verified')
self.account.saveTrusts()
tab.add_message(TRUST_ADDED % format_dict, typ=0)
tab.add_message(InfoMessage(TRUST_ADDED % format_dict), typ=0)
elif action == 'untrust':
ctx = self.get_context(name)
key = ctx.getCurrentKey()
@ -939,7 +951,7 @@ class Plugin(BasePlugin):
format_dict['key'] = key
ctx.setTrust(fpr, '')
self.account.saveTrusts()
tab.add_message(TRUST_REMOVED % format_dict, typ=0)
tab.add_message(InfoMessage(TRUST_REMOVED % format_dict), typ=0)
self.core.refresh_window()
def otr_start(self, tab, name, format_dict):
@ -954,7 +966,7 @@ class Plugin(BasePlugin):
if otr.state != STATE_ENCRYPTED:
format_dict['secs'] = secs
text = OTR_NOT_ENABLED % format_dict
tab.add_message(text, typ=0)
tab.add_message(InfoMessage(text), typ=0)
self.core.refresh_window()
if secs > 0:
@ -962,7 +974,7 @@ class Plugin(BasePlugin):
self.api.add_timed_event(event)
body = self.get_context(name).sendMessage(0, b'?OTRv?').decode()
self.core.xmpp.send_message(mto=name, mtype='chat', mbody=body)
tab.add_message(OTR_REQUEST % format_dict, typ=0)
tab.add_message(InfoMessage(OTR_REQUEST % format_dict), typ=0)
@staticmethod
def completion_otr(the_input):
@ -1012,13 +1024,13 @@ class Plugin(BasePlugin):
ctx.smpInit(secret, question)
else:
ctx.smpInit(secret)
tab.add_message(SMP_INITIATED % format_dict, typ=0)
tab.add_message(InfoMessage(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)
tab.add_message(InfoMessage(SMP_ABORTED % format_dict), typ=0)
self.core.refresh_window()
@staticmethod

View file

@ -53,8 +53,15 @@ from poezio.core.completions import CompletionCore
from poezio.core.tabs import Tabs
from poezio.core.commands import CommandCore
from poezio.core.handlers import HandlerCore
from poezio.core.structs import POSSIBLE_SHOW, DEPRECATED_ERRORS, \
ERROR_AND_STATUS_CODES, Command, Status
from poezio.core.structs import (
Command,
Status,
DEPRECATED_ERRORS,
ERROR_AND_STATUS_CODES,
POSSIBLE_SHOW,
)
from poezio.ui.types import Message, InfoMessage
log = logging.getLogger(__name__)
@ -1317,7 +1324,7 @@ class Core:
"""
tab = self.tabs.by_name_and_class(jid, tabs.ConversationTab)
if tab is not None:
tab.add_message(msg, typ=2)
tab.add_message(InfoMessage(msg), typ=2)
if self.tabs.current_tab is tab:
self.refresh_window()
@ -1349,9 +1356,11 @@ class Core:
colors = get_theme().INFO_COLORS
color = colors.get(typ.lower(), colors.get('default', None))
nb_lines = self.information_buffer.add_message(
txt=msg,
nickname=typ,
nick_color=color
Message(
txt=msg,
nickname=typ,
nick_color=color
)
)
popup_on = config.get('information_buffer_popup_on').split()
if isinstance(self.tabs.current_tab, tabs.RosterInfoTab):
@ -1582,17 +1591,6 @@ class Core:
self.tab_win.resize(1, tabs.Tab.width, tabs.Tab.height - 2, 0)
self.left_tab_win = None
def add_message_to_text_buffer(self, buff, txt, nickname=None):
"""
Add the message to the room if possible, else, add it to the Info window
(in the Info tab of the info window in the RosterTab)
"""
if not buff:
self.information('Trying to add a message in no room: %s' % txt,
'Error')
return
buff.add_message(txt, nickname=nickname)
def full_screen_redraw(self):
"""
Completely erase and redraw the screen
@ -2064,15 +2062,18 @@ class Core:
return
error_message = self.get_error_message(error)
tab.add_message(
error_message,
highlight=True,
nickname='Error',
nick_color=get_theme().COLOR_ERROR_MSG,
typ=2)
Message(
error_message,
highlight=True,
nickname='Error',
nick_color=get_theme().COLOR_ERROR_MSG,
),
typ=2,
)
code = error['error']['code']
if code == '401':
msg = 'To provide a password in order to join the room, type "/join / password" (replace "password" by the real password)'
tab.add_message(msg, typ=2)
tab.add_message(InfoMessage(msg), typ=2)
if code == '409':
if config.get('alternative_nickname') != '':
if not tab.joined:
@ -2081,8 +2082,12 @@ class Core:
else:
if not tab.joined:
tab.add_message(
'You can join the room with an other nick, by typing "/join /other_nick"',
typ=2)
InfoMessage(
'You can join the room with another nick, '
'by typing "/join /other_nick"'
),
typ=2,
)
self.refresh_window()

View file

@ -39,6 +39,7 @@ from poezio.logger import logger
from poezio.roster import roster
from poezio.text_buffer import CorrectionError, AckError
from poezio.theming import dump_tuple, get_theme
from poezio.ui.types import XMLLog, Message as PMessage, BaseMessage, InfoMessage
from poezio.core.commands import dumb_callback
@ -326,7 +327,7 @@ class HandlerCore:
error = '\x19%s}%s\x19o' % (dump_tuple(get_theme().COLOR_CHAR_NACK),
error_msg)
if not tab.nack_message('\n' + error, message['id'], message['to']):
tab.add_message(error, typ=0)
tab.add_message(InfoMessage(error), typ=0)
self.core.refresh_window()
def on_normal_message(self, message):
@ -421,14 +422,17 @@ class HandlerCore:
if not try_modify():
conversation.add_message(
body,
date,
nickname=remote_nick,
nick_color=color,
history=delayed,
identifier=message['id'],
jid=jid,
typ=1)
PMessage(
txt=body,
time=date,
nickname=remote_nick,
nick_color=color,
history=delayed,
identifier=message['id'],
jid=jid,
),
typ=1,
)
if not own and 'private' in config.get('beep_on').split():
if not config.get_by_tabname('disable_beep', conv_jid.bare):
@ -769,12 +773,15 @@ class HandlerCore:
except CorrectionError:
log.debug('Unable to correct a message', exc_info=True)
if not replaced and tab.add_message(
body,
date,
nick_from,
history=delayed,
identifier=message['id'],
jid=message['from'],
PMessage(
txt=body,
time=date,
nickname=nick_from,
history=delayed,
identifier=message['id'],
jid=message['from'],
user=user,
),
typ=1):
self.core.events.trigger('highlight', message, tab)
@ -862,14 +869,16 @@ class HandlerCore:
log.debug('Unable to correct a message', exc_info=True)
if not replaced:
tab.add_message(
body,
time=None,
nickname=sender_nick,
nick_color=get_theme().COLOR_OWN_NICK if sent else None,
forced_user=user,
identifier=message['id'],
jid=message['from'],
typ=1)
PMessage(
txt=body,
nickname=sender_nick,
nick_color=get_theme().COLOR_OWN_NICK if sent else None,
user=user,
identifier=message['id'],
jid=message['from'],
),
typ=1,
)
if sent:
tab.set_last_sent_message(message, correct=replaced)
else:
@ -1361,36 +1370,52 @@ class HandlerCore:
if show_unavailable or hide_unavailable or non_priv or logging_off\
or non_anon or semi_anon or full_anon:
tab.add_message(
'\x19%(info_col)s}Info: A configuration change not privacy-related occurred.' % info_col,
InfoMessage(
'Info: A configuration change not privacy-related occurred.'
),
typ=2)
modif = True
if show_unavailable:
tab.add_message(
'\x19%(info_col)s}Info: The unavailable members are now shown.' % info_col,
InfoMessage(
'Info: The unavailable members are now shown.'
),
typ=2)
elif hide_unavailable:
tab.add_message(
'\x19%(info_col)s}Info: The unavailable members are now hidden.' % info_col,
InfoMessage(
'Info: The unavailable members are now hidden.',
),
typ=2)
if non_anon:
tab.add_message(
'\x191}Warning:\x19%(info_col)s} The room is now not anonymous. (public JID)' % info_col,
InfoMessage(
'\x191}Warning:\x19%(info_col)s} The room is now not anonymous. (public JID)' % info_col
),
typ=2)
elif semi_anon:
tab.add_message(
'\x19%(info_col)s}Info: The room is now semi-anonymous. (moderators-only JID)' % info_col,
InfoMessage(
'Info: The room is now semi-anonymous. (moderators-only JID)',
),
typ=2)
elif full_anon:
tab.add_message(
'\x19%(info_col)s}Info: The room is now fully anonymous.' % info_col,
InfoMessage(
'Info: The room is now fully anonymous.',
),
typ=2)
if logging_on:
tab.add_message(
'\x191}Warning: \x19%(info_col)s}This room is publicly logged' % info_col,
InfoMessage(
'\x191}Warning: \x19%(info_col)s}This room is publicly logged' % info_col
),
typ=2)
elif logging_off:
tab.add_message(
'\x19%(info_col)s}Info: This room is not logged anymore.' % info_col,
InfoMessage(
'Info: This room is not logged anymore.',
),
typ=2)
if modif:
self.core.refresh_window()
@ -1434,15 +1459,17 @@ class HandlerCore:
if nick_from:
tab.add_message(
"%(user)s set the subject to: \x19%(text_col)s}%(subject)s"
% fmt,
str_time=time,
InfoMessage(
"%(user)s set the subject to: \x19%(text_col)s}%(subject)s" % fmt,
time=time,
),
typ=2)
else:
tab.add_message(
"\x19%(info_col)s}The subject is: \x19%(text_col)s}%(subject)s"
% fmt,
str_time=time,
InfoMessage(
"The subject is: \x19%(text_col)s}%(subject)s" % fmt,
time=time,
),
typ=2)
tab.topic = subject
tab.topic_from = nick_from
@ -1506,18 +1533,15 @@ class HandlerCore:
xhtml_text, force=True).rstrip('\x19o').strip()
else:
poezio_colored = str(stanza)
char = get_theme().CHAR_XML_OUT
self.core.add_message_to_text_buffer(
self.core.xml_buffer,
poezio_colored,
nickname=char)
self.core.xml_buffer.add_message(
XMLLog(txt=poezio_colored, incoming=False),
)
try:
if self.core.xml_tab.match_stanza(
ElementBase(ET.fromstring(stanza))):
self.core.add_message_to_text_buffer(
self.core.xml_tab.filtered_buffer,
poezio_colored,
nickname=char)
self.core.xml_tab.filtered_buffer.add_message(
XMLLog(txt=poezio_colored, incoming=False),
)
except:
# Most of the time what gets logged is whitespace pings. Skip.
# And also skip tab updates.
@ -1540,17 +1564,14 @@ class HandlerCore:
xhtml_text, force=True).rstrip('\x19o').strip()
else:
poezio_colored = str(stanza)
char = get_theme().CHAR_XML_IN
self.core.add_message_to_text_buffer(
self.core.xml_buffer,
poezio_colored,
nickname=char)
self.core.xml_buffer.add_message(
XMLLog(txt=poezio_colored, incoming=True),
)
try:
if self.core.xml_tab.match_stanza(stanza):
self.core.add_message_to_text_buffer(
self.core.xml_tab.filtered_buffer,
poezio_colored,
nickname=char)
self.core.xml_tab.filtered_buffer.add_message(
XMLLog(txt=poezio_colored, incoming=True),
)
except:
log.debug('', exc_info=True)
if isinstance(self.core.tabs.current_tab, tabs.XMLTab):

View file

@ -18,6 +18,7 @@ from poezio import tabs
from poezio import xhtml, colors
from poezio.config import config
from poezio.text_buffer import TextBuffer
from poezio.ui.types import Message
class DiscoInfoException(Exception): pass
@ -63,16 +64,15 @@ def add_line(
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,
jid=None,
Message(
txt=text,
time=time,
nickname=nick,
nick_color=color,
history=True,
user=None,
top=top,
)
)

View file

@ -47,6 +47,7 @@ from poezio.text_buffer import TextBuffer
from poezio.theming import get_theme, dump_tuple
from poezio.ui.funcs import truncate_nick
from poezio.ui.consts import LONG_FORMAT_LENGTH
from poezio.ui.types import BaseMessage, InfoMessage
from slixmpp import JID, InvalidJID, Message
@ -572,40 +573,19 @@ class ChatTab(Tab):
def general_jid(self) -> JID:
raise NotImplementedError
def log_message(self,
txt: str,
nickname: str,
time: Optional[datetime] = None,
typ=1):
def log_message(self, message: BaseMessage, typ=1):
"""
Log the messages in the archives.
"""
name = self.jid.bare
if not logger.log_message(name, nickname, txt, date=time, typ=typ):
if not isinstance(message, Message):
return
if not logger.log_message(name, message.nickname, message.txt, date=message.time, typ=typ):
self.core.information('Unable to write in the log file', 'Error')
def add_message(self,
txt,
time=None,
nickname=None,
forced_user=None,
nick_color=None,
identifier=None,
jid=None,
history=None,
typ=1,
highlight=False):
self.log_message(txt, nickname, time=time, typ=typ)
self._text_buffer.add_message(
txt,
time=time,
nickname=nickname,
highlight=highlight,
nick_color=nick_color,
history=history,
user=forced_user,
identifier=identifier,
jid=jid)
def add_message(self, message: BaseMessage, typ=1):
self.log_message(message, typ=typ)
self._text_buffer.add_message(message)
def modify_message(self,
txt,
@ -614,10 +594,10 @@ class ChatTab(Tab):
user=None,
jid=None,
nickname=None):
self.log_message(txt, nickname, typ=1)
message = self._text_buffer.modify_message(
txt, old_id, new_id, time=time, user=user, jid=jid)
txt, old_id, new_id, user=user, jid=jid)
if message:
self.log_message(message, typ=1)
self.text_win.modify_message(message.identifier, message)
self.core.refresh_window()
return True
@ -1010,7 +990,10 @@ class OneToOneTab(ChatTab):
msg += 'status: %s, ' % status.message
if status.show in SHOW_NAME:
msg += 'show: %s, ' % SHOW_NAME[status.show]
self.add_message(msg[:-2], typ=2)
self.add_message(
InfoMessage(txt=msg[:-2]),
typ=2,
)
def ack_message(self, msg_id: str, msg_jid: JID):
"""
@ -1042,11 +1025,14 @@ class OneToOneTab(ChatTab):
message.send()
body = xhtml.xhtml_to_poezio_colors(xhtml_data, force=True)
self._text_buffer.add_message(
body,
nickname=self.core.own_nick,
nick_color=get_theme().COLOR_OWN_NICK,
identifier=message['id'],
jid=self.core.xmpp.boundjid)
Message(
body,
nickname=self.core.own_nick,
nick_color=get_theme().COLOR_OWN_NICK,
identifier=message['id'],
jid=self.core.xmpp.boundjid,
)
)
self.refresh()
def check_features(self):

View file

@ -28,6 +28,7 @@ from poezio.roster import roster
from poezio.text_buffer import CorrectionError
from poezio.theming import get_theme, dump_tuple
from poezio.decorators import command_args_parser
from poezio.ui.types import InfoMessage
log = logging.getLogger(__name__)
@ -179,7 +180,7 @@ class ConversationTab(OneToOneTab):
(' and their last status was %s' % status)
if status else '',
)
self.add_message(msg)
self.add_message(InfoMessage(msg), typ=0)
self.core.refresh_window()
self.core.xmpp.plugin['xep_0012'].get_last_activity(
@ -200,17 +201,21 @@ class ConversationTab(OneToOneTab):
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)
})
self.add_message(
InfoMessage(
"Show: %(show)s, %(status)s" % {
'show': resource.presence or 'available',
'status': status,
}
),
typ=0,
)
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)})
self.add_message(
InfoMessage("No information available"),
typ=0,
)
return True
@command_args_parser.quoted(0, 1)

View file

@ -40,6 +40,7 @@ from poezio.roster import roster
from poezio.theming import get_theme, dump_tuple
from poezio.user import User
from poezio.core.structs import Completion, Status
from poezio.ui.types import BaseMessage, Message, InfoMessage, StatusMessage
log = logging.getLogger(__name__)
@ -197,8 +198,7 @@ class MucTab(ChatTab):
'color_spec': spec_col,
'nick': self.own_nick,
}
self.add_message(msg, typ=2)
self.add_message(InfoMessage(msg), typ=2)
self.disconnect()
muc.leave_groupchat(self.core.xmpp, self.jid.bare, self.own_nick,
message)
@ -301,7 +301,7 @@ class MucTab(ChatTab):
'role': user.role or 'None',
'status': '\n%s' % user.status if user.status else ''
}
self.add_message(info, typ=0)
self.add_message(InfoMessage(info), typ=0)
return True
def change_topic(self, topic: str):
@ -327,9 +327,13 @@ class MucTab(ChatTab):
else:
user_string = ''
self._text_buffer.add_message(
"\x19%s}The subject of the room is: \x19%s}%s %s" %
(info_text, norm_text, self.topic, user_string))
self.add_message(
InfoMessage(
"The subject of the room is: \x19%s}%s %s" %
(norm_text, self.topic, user_string),
),
typ=0,
)
@refresh_wrapper.always
def recolor(self, random_colors=False):
@ -558,28 +562,32 @@ class MucTab(ChatTab):
'nick_col': color,
'info_col': info_col,
}
self.add_message(enable_message, typ=2)
self.add_message(InfoMessage(enable_message), typ=2)
self.core.enable_private_tabs(self.jid.bare, enable_message)
if '201' in status_codes:
self.add_message(
'\x19%(info_col)s}Info: The room '
'has been created' % {'info_col': info_col},
typ=0)
InfoMessage('Info: The room has been created'),
typ=0
)
if '170' in status_codes:
self.add_message(
'\x19%(warn_col)s}Warning:\x19%(info_col)s}'
' This room is publicly logged' % {
'info_col': info_col,
'warn_col': warn_col
},
InfoMessage(
'\x19%(warn_col)s}Warning:\x19%(info_col)s}'
' This room is publicly logged' % {
'info_col': info_col,
'warn_col': warn_col
},
),
typ=0)
if '100' in status_codes:
self.add_message(
'\x19%(warn_col)s}Warning:\x19%(info_col)s}'
' This room is not anonymous.' % {
'info_col': info_col,
'warn_col': warn_col
},
InfoMessage(
'\x19%(warn_col)s}Warning:\x19%(info_col)s}'
' This room is not anonymous.' % {
'info_col': info_col,
'warn_col': warn_col
},
),
typ=0)
def handle_presence_joined(self, presence, status_codes):
@ -635,18 +643,20 @@ class MucTab(ChatTab):
def on_non_member_kicked(self):
"""We have been kicked because the MUC is members-only"""
self.add_message(
'\x19%(info_col)s}You have been kicked because you '
'are not a member and the room is now members-only.' %
{'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)},
InfoMessage(
'You have been kicked because you '
'are not a member and the room is now members-only.'
),
typ=2)
self.disconnect()
def on_muc_shutdown(self):
"""We have been kicked because the MUC service is shutting down"""
self.add_message(
'\x19%(info_col)s}You have been kicked because the'
' MUC service is shutting down.' %
{'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)},
InfoMessage(
'You have been kicked because the'
' MUC service is shutting down.'
),
typ=2)
self.disconnect()
@ -693,7 +703,7 @@ class MucTab(ChatTab):
'jid_color': dump_tuple(theme.COLOR_MUC_JID),
'color_spec': spec_col,
}
self.add_message(msg, typ=2)
self.add_message(InfoMessage(msg), typ=2)
self.core.on_user_rejoined_private_conversation(self.jid.bare, from_nick)
def on_user_nick_change(self, presence, user, from_nick, from_room):
@ -723,14 +733,16 @@ class MucTab(ChatTab):
old_color = color = 3
info_col = dump_tuple(get_theme().COLOR_INFORMATION_TEXT)
self.add_message(
'\x19%(old_color)s}%(old)s\x19%(info_col)s} is'
' now known as \x19%(color)s}%(new)s' % {
'old': from_nick,
'new': new_nick,
'color': color,
'old_color': old_color,
'info_col': info_col
},
InfoMessage(
'\x19%(old_color)s}%(old)s\x19%(info_col)s} is'
' now known as \x19%(color)s}%(new)s' % {
'old': from_nick,
'new': new_nick,
'color': color,
'old_color': old_color,
'info_col': info_col
},
),
typ=2)
# rename the private tabs if needed
self.core.rename_private_tabs(self.jid.bare, from_nick, user)
@ -814,7 +826,7 @@ class MucTab(ChatTab):
'reason': reason.text,
'info_col': info_col
}
self.add_message(kick_msg, typ=2)
self.add_message(InfoMessage(kick_msg), typ=2)
def on_user_kicked(self, presence, user, from_nick):
"""
@ -892,7 +904,7 @@ class MucTab(ChatTab):
'reason': reason.text,
'info_col': info_col
}
self.add_message(kick_msg, typ=2)
self.add_message(InfoMessage(kick_msg), typ=2)
def on_user_leave_groupchat(self,
user: User,
@ -957,7 +969,7 @@ class MucTab(ChatTab):
}
if status:
leave_msg += ' (\x19o%s\x19%s})' % (status, info_col)
self.add_message(leave_msg, typ=2)
self.add_message(InfoMessage(leave_msg), typ=2)
self.core.on_user_left_private_conversation(from_room, user, status)
def on_user_change_status(self, user, from_nick, from_room, affiliation,
@ -1016,7 +1028,7 @@ class MucTab(ChatTab):
or show != user.show or status != user.status)) or (
affiliation != user.affiliation or role != user.role):
# display the message in the room
self._text_buffer.add_message(msg)
self.add_message(InfoMessage(msg))
self.core.on_user_changed_status_in_private(
'%s/%s' % (from_room, from_nick), Status(show, status))
self.users.remove(user)
@ -1118,7 +1130,6 @@ class MucTab(ChatTab):
nickname=None,
user=None,
jid=None):
self.log_message(txt, nickname, time=time, typ=1)
highlight = self.do_highlight(txt, time, nickname, corrected=True)
message = self._text_buffer.modify_message(
txt,
@ -1129,6 +1140,7 @@ class MucTab(ChatTab):
user=user,
jid=jid)
if message:
self.log_message(message, typ=1)
self.text_win.modify_message(message.identifier, message)
return highlight
return False
@ -1192,9 +1204,11 @@ class MucTab(ChatTab):
def on_self_ping_failed(self, iq):
if not self.lagged:
self.lagged = True
info_text = dump_tuple(get_theme().COLOR_INFORMATION_TEXT)
self._text_buffer.add_message(
"\x19%s}MUC service not responding." % info_text)
InfoMessage(
"MUC service not responding."
),
)
self._state = 'disconnected'
self.core.refresh_window()
self.enable_self_ping_event()
@ -1202,9 +1216,9 @@ class MucTab(ChatTab):
def reset_lag(self):
if self.lagged:
self.lagged = False
info_text = dump_tuple(get_theme().COLOR_INFORMATION_TEXT)
self._text_buffer.add_message(
"\x19%s}MUC service is responding again." % info_text)
self.add_message(
InfoMessage("MUC service is responding again.")
)
if self != self.core.tabs.current_tab:
self._state = 'joined'
else:
@ -1551,7 +1565,7 @@ class MucTab(ChatTab):
buff.append('\n')
message = ' '.join(buff)
self._text_buffer.add_message(message)
self.add_message(InfoMessage(message), typ=0)
self.text_win.refresh()
self.input.refresh()

View file

@ -27,6 +27,7 @@ from poezio.decorators import refresh_wrapper
from poezio.logger import logger
from poezio.theming import get_theme, dump_tuple
from poezio.decorators import command_args_parser
from poezio.ui.types import BaseMessage, Message, InfoMessage
log = logging.getLogger(__name__)
@ -106,12 +107,14 @@ class PrivateTab(OneToOneTab):
def remove_information_element(plugin_name):
del PrivateTab.additional_information[plugin_name]
def log_message(self, txt, nickname, time=None, typ=1):
def log_message(self, msg: BaseMessage, typ=1):
"""
Log the messages in the archives.
"""
if not isinstance(msg, Message):
return
if not logger.log_message(
self.jid.full, nickname, txt, date=time, typ=typ):
self.jid.full, msg.nickname, msg.txt, date=msg.time, typ=typ):
self.core.information('Unable to write in the log file', 'Error')
def on_close(self):
@ -163,8 +166,6 @@ class PrivateTab(OneToOneTab):
self.core.events.trigger('private_say', msg, self)
if not msg['body']:
return
user = self.parent_muc.get_user_by_name(self.own_nick)
replaced = False
if correct or msg['replace']['id']:
msg['replace']['id'] = self.last_sent_message['id']
else:
@ -311,13 +312,15 @@ class PrivateTab(OneToOneTab):
display a message.
"""
self.add_message(
'\x19%(nick_col)s}%(old)s\x19%(info_col)s} is now '
'known as \x19%(nick_col)s}%(new)s' % {
'old': old_nick,
'new': user.nick,
'nick_col': dump_tuple(user.color),
'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)
},
InfoMessage(
'\x19%(nick_col)s}%(old)s\x19%(info_col)s} is now '
'known as \x19%(nick_col)s}%(new)s' % {
'old': old_nick,
'new': user.nick,
'nick_col': dump_tuple(user.color),
'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)
},
),
typ=2)
new_jid = self.jid.bare + '/' + user.nick
self.name = new_jid
@ -338,27 +341,31 @@ class PrivateTab(OneToOneTab):
if not status_message:
self.add_message(
'\x19%(quit_col)s}%(spec)s \x19%(nick_col)s}'
'%(nick)s\x19%(info_col)s} has left the room' % {
'nick': user.nick,
'spec': theme.CHAR_QUIT,
'nick_col': color,
'quit_col': dump_tuple(theme.COLOR_QUIT_CHAR),
'info_col': dump_tuple(theme.COLOR_INFORMATION_TEXT)
},
InfoMessage(
'\x19%(quit_col)s}%(spec)s \x19%(nick_col)s}'
'%(nick)s\x19%(info_col)s} has left the room' % {
'nick': user.nick,
'spec': theme.CHAR_QUIT,
'nick_col': color,
'quit_col': dump_tuple(theme.COLOR_QUIT_CHAR),
'info_col': dump_tuple(theme.COLOR_INFORMATION_TEXT)
},
),
typ=2)
else:
self.add_message(
'\x19%(quit_col)s}%(spec)s \x19%(nick_col)s}'
'%(nick)s\x19%(info_col)s} has left the room'
' (%(status)s)' % {
'status': status_message,
'nick': user.nick,
'spec': theme.CHAR_QUIT,
'nick_col': color,
'quit_col': dump_tuple(theme.COLOR_QUIT_CHAR),
'info_col': dump_tuple(theme.COLOR_INFORMATION_TEXT)
},
InfoMessage(
'\x19%(quit_col)s}%(spec)s \x19%(nick_col)s}'
'%(nick)s\x19%(info_col)s} has left the room'
' (%(status)s)' % {
'status': status_message,
'nick': user.nick,
'spec': theme.CHAR_QUIT,
'nick_col': color,
'quit_col': dump_tuple(theme.COLOR_QUIT_CHAR),
'info_col': dump_tuple(theme.COLOR_INFORMATION_TEXT)
},
),
typ=2)
return self.core.tabs.current_tab is self
@ -378,26 +385,28 @@ class PrivateTab(OneToOneTab):
if user:
color = dump_tuple(user.color)
self.add_message(
'\x19%(join_col)s}%(spec)s \x19%(color)s}%(nick)s\x19'
'%(info_col)s} joined the room' % {
'nick': nick,
'color': color,
'spec': theme.CHAR_JOIN,
'join_col': dump_tuple(theme.COLOR_JOIN_CHAR),
'info_col': dump_tuple(theme.COLOR_INFORMATION_TEXT)
},
InfoMessage(
'\x19%(join_col)s}%(spec)s \x19%(color)s}%(nick)s\x19'
'%(info_col)s} joined the room' % {
'nick': nick,
'color': color,
'spec': theme.CHAR_JOIN,
'join_col': dump_tuple(theme.COLOR_JOIN_CHAR),
'info_col': dump_tuple(theme.COLOR_INFORMATION_TEXT)
},
),
typ=2)
return self.core.tabs.current_tab is self
def activate(self, reason=None):
self.on = True
if reason:
self.add_message(txt=reason, typ=2)
self.add_message(InfoMessage(reason), typ=2)
def deactivate(self, reason=None):
self.on = False
if reason:
self.add_message(txt=reason, typ=2)
self.add_message(InfoMessage(reason), typ=2)
def matching_names(self):
return [(3, self.jid.resource), (4, self.name)]
@ -407,9 +416,12 @@ class PrivateTab(OneToOneTab):
error = '\x19%s}%s\x19o' % (dump_tuple(theme.COLOR_CHAR_NACK),
error_message)
self.add_message(
error,
highlight=True,
nickname='Error',
nick_color=theme.COLOR_ERROR_MSG,
typ=2)
Message(
error,
highlight=True,
nickname='Error',
nick_color=theme.COLOR_ERROR_MSG,
),
typ=2,
)
self.core.refresh_window()

View file

@ -27,6 +27,7 @@ from poezio.theming import get_theme, dump_tuple
from poezio.decorators import command_args_parser
from poezio.core.structs import Command, Completion
from poezio.tabs import Tab
from poezio.ui.types import InfoMessage
log = logging.getLogger(__name__)
@ -402,11 +403,11 @@ class RosterInfoTab(Tab):
if not tab:
log.debug('Received message from nonexistent tab: %s',
message['from'])
message = '\x19%(info_col)s}Cannot send message to %(jid)s: contact blocked' % {
message = 'Cannot send message to %(jid)s: contact blocked' % {
'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT),
'jid': message['from'],
}
tab.add_message(message)
tab.add_message(InfoMessage(message), typ=0)
@command_args_parser.ignored
def command_list_blocks(self):

View file

@ -65,7 +65,7 @@ class XMLTab(Tab):
self.filtered_buffer = text_buffer.TextBuffer()
self.info_header = windows.XMLInfoWin()
self.text_win = windows.XMLTextWin()
self.text_win = windows.TextWin()
self.core_buffer.add_window(self.text_win)
self.default_help_message = windows.HelpText("/ to enter a command")

View file

@ -14,7 +14,7 @@ log = logging.getLogger(__name__)
from typing import Dict, Union, Optional, List, Tuple
from datetime import datetime
from poezio.config import config
from poezio.ui.types import Message
from poezio.ui.types import Message, BaseMessage
@ -38,7 +38,7 @@ class TextBuffer:
messages_nb_limit = config.get('max_messages_in_memory')
self._messages_nb_limit = messages_nb_limit # type: int
# Message objects
self.messages = [] # type: List[Message]
self.messages = [] # type: List[BaseMessage]
# COMPAT: Correction id -> Original message id.
self.correction_ids = {} # type: Dict[str, str]
# we keep track of one or more windows
@ -53,33 +53,10 @@ class TextBuffer:
def last_message(self) -> Optional[Message]:
return self.messages[-1] if self.messages else None
def add_message(self,
txt: str,
time: Optional[datetime] = None,
nickname: Optional[str] = None,
nick_color: Optional[Tuple] = None,
history: bool = False,
user: Optional[str] = None,
highlight: bool = False,
top: Optional[bool] = False,
identifier: Optional[str] = None,
jid: Optional[str] = None,
ack: int = 0) -> int:
def add_message(self, msg: BaseMessage):
"""
Create a message and add it to the text buffer
"""
msg = Message(
txt,
time=time,
nickname=nickname,
nick_color=nick_color,
history=history,
user=user,
identifier=identifier,
top=top,
highlight=highlight,
jid=jid,
ack=ack)
self.messages.append(msg)
while len(self.messages) > self._messages_nb_limit:
@ -92,13 +69,11 @@ class TextBuffer:
# build the lines from the new message
nb = window.build_new_message(
msg,
history=history,
highlight=highlight,
timestamp=show_timestamps,
top=top,
nick_size=nick_size)
if ret_val == 0:
ret_val = nb
top = isinstance(msg, Message) and msg.top
if window.pos != 0 and top is False:
window.scroll_up(nb)
@ -156,7 +131,7 @@ class TextBuffer:
highlight: bool = False,
time: Optional[datetime] = None,
user: Optional[str] = None,
jid: Optional[str] = None):
jid: Optional[str] = None) -> Message:
"""
Correct a message in a text buffer.

View file

@ -3,10 +3,14 @@ import curses
from datetime import datetime
from functools import singledispatch
from typing import List, Optional, Tuple
from typing import List, Tuple
from math import ceil, log10
from poezio import poopt
from poezio.theming import (
get_theme,
)
from poezio.windows import Win
from poezio.ui.consts import (
FORMAT_CHAR,
LONG_FORMAT,
@ -16,12 +20,10 @@ from poezio.ui.funcs import (
truncate_nick,
parse_attrs,
)
from poezio.theming import (
get_theme,
)
from poezio.ui.types import (
BaseMessage,
Message,
StatusMessage,
XMLLog,
)
@ -86,6 +88,17 @@ def build_message(msg: Message, width: int, timestamp: bool, nick_size: int = 10
return []
offset = msg.compute_offset(timestamp, nick_size)
lines = poopt.cut_text(txt, width - offset - 1)
generated_lines = generate_lines(lines, msg, default_color='')
if msg.top:
generated_lines.reverse()
return generated_lines
@build_lines.register(StatusMessage)
def build_status(msg: StatusMessage, width: int, timestamp: bool, nick_size: int = 10) -> List[Line]:
msg.rebuild()
offset = msg.compute_offset(timestamp, nick_size)
lines = poopt.cut_text(msg.txt, width - offset - 1)
return generate_lines(lines, msg, default_color='')
@ -97,7 +110,7 @@ def build_xmllog(msg: XMLLog, width: int, timestamp: bool, nick_size: int = 10)
@singledispatch
def write_pre(msg: BaseMessage, win, with_timestamps: bool, nick_size: int) -> int:
def write_pre(msg: BaseMessage, win: Win, with_timestamps: bool, nick_size: int) -> int:
"""Write the part before text (only the timestamp)"""
if with_timestamps:
return PreMessageHelpers.write_time(win, False, msg.time)
@ -105,7 +118,7 @@ def write_pre(msg: BaseMessage, win, with_timestamps: bool, nick_size: int) -> i
@write_pre.register(Message)
def write_pre_message(msg: Message, win, with_timestamps: bool, nick_size: int) -> int:
def write_pre_message(msg: Message, win: Win, with_timestamps: bool, nick_size: int) -> int:
"""Write the part before the body:
- timestamp (short or long)
- ack/nack
@ -149,7 +162,7 @@ def write_pre_message(msg: Message, win, with_timestamps: bool, nick_size: int)
@write_pre.register(XMLLog)
def write_pre_xmllog(msg: XMLLog, win, with_timestamps: bool, nick_size: int) -> int:
def write_pre_xmllog(msg: XMLLog, win: Win, with_timestamps: bool, nick_size: int) -> int:
"""Write the part before the stanza (timestamp + IN/OUT)"""
offset = 0
if with_timestamps:
@ -170,7 +183,7 @@ def write_pre_xmllog(msg: XMLLog, win, with_timestamps: bool, nick_size: int) ->
class PreMessageHelpers:
@staticmethod
def write_revisions(buffer, msg: Message) -> int:
def write_revisions(buffer: Win, msg: Message) -> int:
if msg.revisions:
color = get_theme().COLOR_REVISIONS_MESSAGE
with buffer.colored_text(color=color):
@ -179,7 +192,7 @@ class PreMessageHelpers:
return 0
@staticmethod
def write_ack(buffer) -> int:
def write_ack(buffer: Win) -> int:
theme = get_theme()
color = theme.COLOR_CHAR_ACK
with buffer.colored_text(color=color):
@ -188,7 +201,7 @@ class PreMessageHelpers:
return poopt.wcswidth(theme.CHAR_ACK_RECEIVED) + 1
@staticmethod
def write_nack(buffer) -> int:
def write_nack(buffer: Win) -> int:
theme = get_theme()
color = theme.COLOR_CHAR_NACK
with buffer.colored_text(color=color):
@ -197,7 +210,7 @@ class PreMessageHelpers:
return poopt.wcswidth(theme.CHAR_NACK) + 1
@staticmethod
def write_nickname(buffer, nickname: str, color, highlight=False) -> None:
def write_nickname(buffer: Win, nickname: str, color, highlight=False) -> None:
"""
Write the nickname, using the user's color
and return the number of written characters
@ -215,7 +228,7 @@ class PreMessageHelpers:
buffer.addstr(nickname)
@staticmethod
def write_time(buffer, history: bool, time: datetime) -> int:
def write_time(buffer: Win, history: bool, time: datetime) -> int:
"""
Write the date on the yth line of the window
"""

View file

@ -27,6 +27,12 @@ class BaseMessage:
return SHORT_FORMAT_LENGTH + 1
class InfoMessage(BaseMessage):
def __init__(self, txt: str, identifier: str = '', time: Optional[datetime] = None):
txt = ('\x19%s}' % dump_tuple(get_theme().COLOR_INFORMATION_TEXT)) + txt
super().__init__(txt=txt, identifier=identifier, time=time)
class XMLLog(BaseMessage):
"""XML Log message"""
__slots__ = ('txt', 'time', 'identifier', 'incoming')
@ -59,6 +65,25 @@ class XMLLog(BaseMessage):
return offset
class StatusMessage(BaseMessage):
__slots__ = ('txt', 'time', 'identifier', 'format_string', 'format_args')
def __init__(self, format_string: str, format_args: dict):
BaseMessage.__init__(
self,
txt='',
)
self.format_string = format_string
self.format_args = format_args
self.rebuild()
def rebuild(self):
real_args = {}
for key, func in self.format_args.items():
real_args[key] = func()
self.txt = self.format_string.format(**real_args)
class Message(BaseMessage):
__slots__ = ('txt', 'nick_color', 'time', 'nickname', 'user', 'history',
'identifier', 'top', 'highlight', 'me', 'old_message', 'revisions',

View file

@ -97,7 +97,8 @@ class User:
"""
time: datetime object
"""
self.last_talked = time
if time > self.last_talked:
self.last_talked = time
def has_talked_since(self, t: int) -> bool:
"""

View file

@ -4,7 +4,7 @@ from datetime import datetime
from poezio.theming import get_theme
from poezio.ui.render import build_lines, Line, write_pre
from poezio.ui.consts import SHORT_FORMAT
from poezio.ui.types import BaseMessage, Message, XMLLog
from poezio.ui.types import BaseMessage, Message, StatusMessage, XMLLog
def test_simple_build_basemsg():
msg = BaseMessage(txt='coucou')
@ -28,6 +28,17 @@ def test_simple_render_separator():
line = build_lines(None, 100, True, 10)[0]
assert line is None
def test_simple_render_status():
class Obj:
name = 'toto'
msg = StatusMessage("Coucou {name}", {'name': lambda: Obj.name})
assert msg.txt == "Coucou toto"
Obj.name = 'titi'
build_lines(msg, 100, True, 10)[0]
assert msg.txt == "Coucou titi"
class FakeBuffer:
def __init__(self):
self.text = ''