[FIX] mail, im_livechat: fix /help command outputing tags

Mismatch of str and Markup led to escaping everything. Now properly
Markup code and escape the rest.

closes odoo/odoo#146399

Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
Zelong Lin
2024-01-03 16:59:08 +00:00
committed by zel-odoo
parent 0e2b986c2c
commit 55748288e6
6 changed files with 159 additions and 41 deletions
+10 -8
View File
@@ -59,6 +59,15 @@ msgstr ""
msgid "% of Happiness"
msgstr ""
#. module: im_livechat
#. odoo-python
#: code:addons/im_livechat/models/discuss_channel.py:0
#, python-format
msgid ""
"%(new_line)sType %(bold_start)s:shortcut%(bold_end)s to insert a canned "
"response in your message."
msgstr ""
#. module: im_livechat
#. odoo-python
#: code:addons/im_livechat/models/chatbot_script_step.py:0
@@ -1802,13 +1811,6 @@ msgstr ""
msgid "Treated sessions"
msgstr ""
#. module: im_livechat
#. odoo-python
#: code:addons/im_livechat/models/discuss_channel.py:0
#, python-format
msgid "Type <b>:shortcut</b> to insert a canned response in your message.<br>"
msgstr ""
#. module: im_livechat
#: model:ir.model.fields,field_description:im_livechat.field_im_livechat_channel_rule__regex_url
msgid "URL Regex"
@@ -1868,8 +1870,8 @@ msgid "User's raw answer"
msgstr ""
#. module: im_livechat
#. odoo-python
#. odoo-javascript
#. odoo-python
#: code:addons/im_livechat/controllers/main.py:0
#: code:addons/im_livechat/controllers/main.py:0
#: code:addons/im_livechat/models/im_livechat_channel.py:0
+3 -1
View File
@@ -83,7 +83,9 @@ class DiscussChannel(models.Model):
def _execute_command_help_message_extra(self):
msg = super()._execute_command_help_message_extra()
if self.channel_type == 'livechat':
return msg + _("Type <b>:shortcut</b> to insert a canned response in your message.<br>")
return msg + html_escape(
_("%(new_line)sType %(bold_start)s:shortcut%(bold_end)s to insert a canned response in your message.")
) % {"bold_start": Markup("<b>"), "bold_end": Markup("</b>"), "new_line": Markup("<br>")}
return msg
def execute_command_history(self, **kwargs):
@@ -6,11 +6,12 @@ from unittest.mock import patch, PropertyMock
from odoo import fields
from odoo.addons.im_livechat.tests.common import TestImLivechatCommon
from odoo.addons.mail.tests.common import MailCommon
from odoo.tests.common import tagged
@tagged("post_install", "-at_install")
class TestGetDiscussChannel(TestImLivechatCommon):
class TestGetDiscussChannel(TestImLivechatCommon, MailCommon):
def test_get_discuss_channel(self):
"""For a livechat with 5 available operators, we open 5 channels 5 times (25 channels total).
For every 5 channels opening, we check that all operators were assigned.
@@ -193,3 +194,36 @@ class TestGetDiscussChannel(TestImLivechatCommon):
with freeze_time(fields.Datetime.to_string(fields.datetime.now() + timedelta(days=1))):
member_of_operator._gc_unpin_livechat_sessions()
self.assertTrue(member_of_operator.is_pinned, "unread channel should not be unpinned after autovacuum")
def test_channel_command_help_in_livechat(self):
"""Ensures the command '/help' works in a livechat"""
channel_info = self.make_jsonrpc_request(
"/im_livechat/get_session",
{
"anonymous_name": "<strong>visitor</strong>",
"channel_id": self.livechat_channel.id,
"previous_operator_id": self.operators[1].partner_id.id
},
)
channel = self.env["discuss.channel"].browse(channel_info["id"])
self.env['bus.bus'].sudo().search([]).unlink()
with self.assertBus(
[(self.env.cr.dbname, "res.partner", self.env.user.partner_id.id)],
[
{
"type": "discuss.channel/transient_message",
"payload": {
"body":
"<span class='o_mail_notification'>You are in a private conversation with <b>@Paul</b> and <b>@Visitor</b>."
"<br><br>Type <b>@username</b> to mention someone, and grab their attention."
"<br>Type <b>#channel</b> to mention a channel."
"<br>Type <b>/command</b> to execute a command."
"<br>Type <b>:shortcut</b> to insert a canned response in your message."
"</span>",
"model": "discuss.channel",
"res_id": channel.id,
},
},
],
):
channel.execute_command_help()
+20 -20
View File
@@ -94,6 +94,17 @@ msgstr ""
msgid "%(name)s: %(message)s)"
msgstr ""
#. module: mail
#. odoo-python
#: code:addons/mail/models/discuss/discuss_channel.py:0
#, python-format
msgid ""
"%(new_line)s%(new_line)sType %(bold_start)s@username%(bold_end)s to mention "
"someone, and grab their attention.%(new_line)sType "
"%(bold_start)s#channel%(bold_end)s to mention a channel.%(new_line)sType "
"%(bold_start)s/command%(bold_end)s to execute a command."
msgstr ""
#. module: mail
#. odoo-javascript
#: code:addons/mail/static/src/discuss/core/web/discuss_core_web_service.js:0
@@ -321,17 +332,6 @@ msgid ""
"model</b>"
msgstr ""
#. module: mail
#. odoo-python
#: code:addons/mail/models/discuss/discuss_channel.py:0
#, python-format
msgid ""
"<br><br>\n"
" Type <b>@username</b> to mention someone, and grab their attention.<br>\n"
" Type <b>#channel</b> to mention a channel.<br>\n"
" Type <b>/command</b> to execute a command.<br>"
msgstr ""
#. module: mail
#: model_terms:ir.ui.view,arch_db:mail.view_document_file_kanban
msgid "<i class=\"fa fa-globe\" aria-label=\"Document url\"/>"
@@ -1084,13 +1084,6 @@ msgstr ""
msgid "And 1 other member."
msgstr ""
#. module: mail
#. odoo-python
#: code:addons/mail/models/discuss/discuss_channel.py:0
#, python-format
msgid "Anonymous"
msgstr ""
#. module: mail
#: model:ir.model.fields,field_description:mail.field_mail_activity_plan__res_model_id
#: model:ir.model.fields,field_description:mail.field_mail_activity_schedule__res_model_id
@@ -9964,6 +9957,13 @@ msgid ""
"continue?"
msgstr ""
#. module: mail
#. odoo-python
#: code:addons/mail/models/discuss/discuss_channel.py:0
#, python-format
msgid "You are alone in a private conversation."
msgstr ""
#. module: mail
#. odoo-python
#: code:addons/mail/models/discuss/discuss_channel.py:0
@@ -9975,14 +9975,14 @@ msgstr ""
#. odoo-python
#: code:addons/mail/models/discuss/discuss_channel.py:0
#, python-format
msgid "You are in a private conversation with <b>@%s</b>."
msgid "You are in a private conversation with %(member_names)s."
msgstr ""
#. module: mail
#. odoo-python
#: code:addons/mail/models/discuss/discuss_channel.py:0
#, python-format
msgid "You are in channel <b>#%s</b>."
msgid "You are in channel %(bold_start)s#%(channel_name)s%(bold_end)s."
msgstr ""
#. module: mail
+31 -11
View File
@@ -2,6 +2,7 @@
import base64
import logging
from babel.lists import format_list
from collections import defaultdict
from hashlib import sha512
from secrets import choice
@@ -12,7 +13,7 @@ from odoo.addons.base.models.avatar_mixin import get_hsl_from_seed
from odoo.exceptions import UserError, ValidationError
from odoo.osv import expression
from odoo.tools import html_escape, get_lang
from odoo.tools.misc import DEFAULT_SERVER_DATETIME_FORMAT
from odoo.tools.misc import babel_locale_parse, DEFAULT_SERVER_DATETIME_FORMAT
_logger = logging.getLogger(__name__)
@@ -1207,22 +1208,41 @@ class Channel(models.Model):
})
def execute_command_help(self, **kwargs):
partner = self.env.user.partner_id
if self.channel_type == 'channel':
msg = _("You are in channel <b>#%s</b>.", html_escape(self.name))
msg = html_escape(_("You are in channel %(bold_start)s#%(channel_name)s%(bold_end)s.")) % {
"bold_start": Markup("<b>"),
"bold_end": Markup("</b>"),
"channel_name": self.name,
}
else:
all_channel_members = self.env['discuss.channel.member'].with_context(active_test=False)
channel_members = all_channel_members.search([('partner_id', '!=', partner.id), ('channel_id', '=', self.id)])
msg = _("You are in a private conversation with <b>@%s</b>.", _(" @").join(html_escape(member.partner_id.name or member.guest_id.name) for member in channel_members) if channel_members else _("Anonymous"))
channel_members = all_channel_members.search([("is_self", "=", False), ("channel_id", "=", self.id)], order='id asc')
if channel_members:
member_names = Markup(
format_list(
[f"<b>@%(member_{member.id})s</b>" for member in channel_members],
locale=babel_locale_parse(get_lang(self.env).code),
)
) % {
f"member_{member.id}": member.partner_id.name or member.guest_id.name for member in channel_members
}
msg = html_escape(_("You are in a private conversation with %(member_names)s.")) % {
"member_names": member_names,
}
else:
msg = _("You are alone in a private conversation.")
msg += self._execute_command_help_message_extra()
self._send_transient_message(partner, msg)
self._send_transient_message(self.env.user.partner_id, msg)
def _execute_command_help_message_extra(self):
msg = _("""<br><br>
Type <b>@username</b> to mention someone, and grab their attention.<br>
Type <b>#channel</b> to mention a channel.<br>
Type <b>/command</b> to execute a command.<br>""")
msg = html_escape(
_(
"%(new_line)s"
"%(new_line)sType %(bold_start)s@username%(bold_end)s to mention someone, and grab their attention."
"%(new_line)sType %(bold_start)s#channel%(bold_end)s to mention a channel."
"%(new_line)sType %(bold_start)s/command%(bold_end)s to execute a command."
)
) % {"bold_start": Markup("<b>"), "bold_end": Markup("</b>"), "new_line": Markup("<br>")}
return msg
def execute_command_leave(self, **kwargs):
@@ -402,3 +402,63 @@ class TestChannelInternals(MailCommon):
member_of_correspondent = self.env['discuss.channel.member'].search([('channel_id', '=', chat.id), ('partner_id', '=', self.test_partner.id)])
self.assertTrue(member_of_current_user.is_pinned)
self.assertFalse(member_of_correspondent.is_pinned)
@users("employee")
def test_channel_command_help_in_channel(self):
"""Ensures the command '/help' works in a channel"""
channel = self.env["discuss.channel"].browse(self.test_channel.ids)
channel.name = "<strong>R&D</strong>"
self.env['bus.bus'].sudo().search([]).unlink()
with self.assertBus(
[(self.env.cr.dbname, "res.partner", self.env.user.partner_id.id)],
[
{
"type": "discuss.channel/transient_message",
"payload": {
"body":
"<span class='o_mail_notification'>"
"You are in channel <b>#&lt;strong&gt;R&amp;D&lt;/strong&gt;</b>."
"<br><br>Type <b>@username</b> to mention someone, and grab their attention."
"<br>Type <b>#channel</b> to mention a channel."
"<br>Type <b>/command</b> to execute a command."
"</span>",
"model": "discuss.channel",
"res_id": channel.id,
},
},
],
):
channel.execute_command_help()
@users("employee")
def test_channel_command_help_in_group(self):
"""Ensures the command '/help' works in a group"""
self.partner_employee_nomail.name = f"<strong>{self.partner_employee_nomail.name}</strong>"
# Guarantee that the channel member ids in the group are in order.
test_group = self.env['discuss.channel'].create({
'name': 'Private Channel',
'channel_type': 'group',
'channel_partner_ids': [(6, 0, self.user_admin.partner_id.id)]
})
test_group.add_members(self.partner_employee_nomail.ids)
self.env['bus.bus'].sudo().search([]).unlink()
with self.assertBus(
[(self.env.cr.dbname, "res.partner", self.env.user.partner_id.id)],
[
{
"type": "discuss.channel/transient_message",
"payload": {
"body":
"<span class='o_mail_notification'>"
"You are in a private conversation with <b>@Mitchell Admin</b> and <b>@&lt;strong&gt;Evita Employee NoEmail&lt;/strong&gt;</b>."
"<br><br>Type <b>@username</b> to mention someone, and grab their attention."
"<br>Type <b>#channel</b> to mention a channel."
"<br>Type <b>/command</b> to execute a command."
"</span>",
"model": "discuss.channel",
"res_id": test_group.id,
},
},
],
):
test_group.execute_command_help()