# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from odoo.tools import email_normalize, html_escape, html2plaintext, plaintext2html
from markupsafe import Markup
class MailChannel(models.Model):
""" Chat Session
Reprensenting a conversation between users.
It extends the base method for anonymous usage.
"""
_name = 'mail.channel'
_inherit = ['mail.channel', 'rating.mixin']
anonymous_name = fields.Char('Anonymous Name')
channel_type = fields.Selection(selection_add=[('livechat', 'Livechat Conversation')], ondelete={'livechat': 'cascade'})
livechat_active = fields.Boolean('Is livechat ongoing?', help='Livechat session is active until visitor leaves the conversation.')
livechat_channel_id = fields.Many2one('im_livechat.channel', 'Channel', index='btree_not_null')
livechat_operator_id = fields.Many2one('res.partner', string='Operator')
chatbot_current_step_id = fields.Many2one('chatbot.script.step', string='Chatbot Current Step')
chatbot_message_ids = fields.One2many('chatbot.message', 'mail_channel_id', string='Chatbot Messages')
country_id = fields.Many2one('res.country', string="Country", help="Country of the visitor of the channel")
_sql_constraints = [('livechat_operator_id', "CHECK((channel_type = 'livechat' and livechat_operator_id is not null) or (channel_type != 'livechat'))",
'Livechat Operator ID is required for a channel of type livechat.')]
def _compute_is_chat(self):
super(MailChannel, self)._compute_is_chat()
for record in self:
if record.channel_type == 'livechat':
record.is_chat = True
def _channel_message_notifications(self, message, message_format=False):
""" When a anonymous user create a mail.channel, the operator is not notify (to avoid massive polling when
clicking on livechat button). So when the anonymous person is sending its FIRST message, the channel header
should be added to the notification, since the user cannot be listining to the channel.
"""
notifications = super()._channel_message_notifications(message=message, message_format=message_format)
for channel in self:
# add uuid to allow anonymous to listen
if channel.channel_type == 'livechat':
notifications.append([channel.uuid, 'mail.channel/new_message', notifications[0][2]])
if not message.author_id:
unpinned_members = self.channel_member_ids.filtered(lambda member: not member.is_pinned)
if unpinned_members:
unpinned_members.write({'is_pinned': True})
notifications = self._channel_channel_notifications(unpinned_members.partner_id.ids) + notifications
return notifications
def channel_info(self):
""" Extends the channel header by adding the livechat operator and the 'anonymous' profile
:rtype : list(dict)
"""
channel_infos = super().channel_info()
channel_infos_dict = dict((c['id'], c) for c in channel_infos)
for channel in self:
channel_infos_dict[channel.id]['channel']['anonymous_name'] = channel.anonymous_name
channel_infos_dict[channel.id]['channel']['anonymous_country'] = {
'code': channel.country_id.code,
'id': channel.country_id.id,
'name': channel.country_id.name,
} if channel.country_id else [('clear',)]
if channel.livechat_operator_id:
display_name = channel.livechat_operator_id.user_livechat_username or channel.livechat_operator_id.display_name
channel_infos_dict[channel.id]['operator_pid'] = (channel.livechat_operator_id.id, display_name.replace(',', ''))
return list(channel_infos_dict.values())
@api.autovacuum
def _gc_empty_livechat_sessions(self):
hours = 1 # never remove empty session created within the last hour
self.env.cr.execute("""
SELECT id as id
FROM mail_channel C
WHERE NOT EXISTS (
SELECT 1
FROM mail_message M
WHERE M.res_id = C.id AND m.model = 'mail.channel'
) AND C.channel_type = 'livechat' AND livechat_channel_id IS NOT NULL AND
COALESCE(write_date, create_date, (now() at time zone 'UTC'))::timestamp
< ((now() at time zone 'UTC') - interval %s)""", ("%s hours" % hours,))
empty_channel_ids = [item['id'] for item in self.env.cr.dictfetchall()]
self.browse(empty_channel_ids).unlink()
def _execute_command_help_message_extra(self):
msg = super(MailChannel, self)._execute_command_help_message_extra()
return msg + _("Type :shortcut to insert a canned response in your message.
")
def execute_command_history(self, **kwargs):
self.env['bus.bus']._sendone(self.uuid, 'im_livechat.history_command', {'id': self.id})
def _send_history_message(self, pid, page_history):
message_body = _('No history found')
if page_history:
html_links = ['