from __future__ import annotations import logging import re from odoo import models, api _logger = logging.getLogger(__name__) _HTML_TAG = re.compile(r'<[^>]+>') def _strip_html(html: str) -> str: return _HTML_TAG.sub(' ', html or '').strip() class MailChannel(models.Model): _inherit = 'mail.channel' @api.model def _ai_bot_partner(self): return self.env.ref('activeblue_ai.partner_activeblue_ai', raise_if_not_found=False) def message_post(self, *, body='', author_id=None, **kwargs): result = super().message_post(body=body, author_id=author_id, **kwargs) # Only intercept direct-message channels if self.channel_type != 'chat': return result bot_partner = self._ai_bot_partner() if not bot_partner: return result member_partners = self.channel_member_ids.partner_id if bot_partner not in member_partners: return result # Don't react to the bot's own messages if author_id == bot_partner.id: return result text = _strip_html(body) if not text: return result # Identify the human sender human_partner = member_partners.filtered(lambda p: p != bot_partner)[:1] user = self.env['res.users'].search([('partner_id', '=', human_partner.id)], limit=1) uid = user.id if user else self.env.uid try: bot = self.env['ab.ai.bot'].sudo().search([('active', '=', True)], limit=1) if not bot: return result response = bot.dispatch_message( user_id=uid, message=text, context={'channel_id': self.id, 'source': 'discuss'}, ) reply = (response or {}).get('reply') or (response or {}).get('message') or \ 'I could not process your request right now.' self.sudo().message_post( body=reply, author_id=bot_partner.id, message_type='comment', subtype_xmlid='mail.mt_comment', ) except Exception as exc: _logger.error('AI bot Discuss reply failed: %s', exc) return result