mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-20 07:12:02 +02:00
143 lines
6 KiB
Python
143 lines
6 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import re
|
|
import requests
|
|
|
|
from datetime import datetime
|
|
from dateutil.relativedelta import relativedelta
|
|
from lxml import html
|
|
from urllib.parse import urlparse
|
|
|
|
from odoo import api, models, fields, tools
|
|
from odoo.tools.misc import OrderedSet
|
|
from odoo.addons.mail.tools.link_preview import get_link_preview_from_url
|
|
from odoo.addons.mail.tools.discuss import Store
|
|
|
|
|
|
class MailLinkPreview(models.Model):
|
|
_name = 'mail.link.preview'
|
|
_inherit = ["bus.listener.mixin"]
|
|
_description = "Store link preview data"
|
|
|
|
source_url = fields.Char('URL', required=True)
|
|
og_type = fields.Char('Type')
|
|
og_title = fields.Char('Title')
|
|
og_site_name = fields.Char('Site name')
|
|
og_image = fields.Char('Image')
|
|
og_description = fields.Text('Description')
|
|
og_mimetype = fields.Char('MIME type')
|
|
image_mimetype = fields.Char('Image MIME type')
|
|
create_date = fields.Datetime(index=True)
|
|
message_link_preview_ids = fields.One2many(
|
|
"mail.message.link.preview", "link_preview_id", groups="base.group_erp_manager"
|
|
)
|
|
|
|
_unique_source_url = models.UniqueIndex("(source_url)")
|
|
|
|
@api.model
|
|
def _create_from_message_and_notify(self, message, request_url=None):
|
|
urls = []
|
|
if not tools.is_html_empty(message.body):
|
|
urls = OrderedSet(html.fromstring(message.body).xpath("//a[not(@data-oe-model)]/@href"))
|
|
if request_url:
|
|
ignore_pattern = re.compile(f"{re.escape(request_url)}(odoo|web|chat)(/|$|#|\\?)")
|
|
urls = list(filter(lambda url: not ignore_pattern.match(url), urls))
|
|
requests_session = requests.Session()
|
|
message_link_previews_ok = self.env["mail.message.link.preview"]
|
|
link_previews_values = [] # list of (sequence, values)
|
|
message_link_previews_values = [] # list of (sequence, mail.link.preview record)
|
|
message_link_preview_by_url = {
|
|
message_link_preview.link_preview_id.source_url: message_link_preview
|
|
for message_link_preview in message.sudo().message_link_preview_ids
|
|
}
|
|
link_preview_by_url = {}
|
|
if len(message_link_preview_by_url) != len(urls):
|
|
# don't make the query if all `mail.message.link.preview` have been found
|
|
link_preview_by_url = {
|
|
link_preview.source_url: link_preview
|
|
for link_preview in self.env["mail.link.preview"].search(
|
|
[("source_url", "in", urls)]
|
|
)
|
|
}
|
|
for index, url in enumerate(urls):
|
|
if message_link_preview := message_link_preview_by_url.get(url):
|
|
message_link_preview.sequence = index
|
|
message_link_previews_ok += message_link_preview
|
|
else:
|
|
if link_preview := link_preview_by_url.get(url):
|
|
message_link_previews_values.append((index, link_preview))
|
|
elif not self._is_domain_thottled(url):
|
|
if link_preview_values := get_link_preview_from_url(url, requests_session):
|
|
link_previews_values.append((index, link_preview_values))
|
|
if (
|
|
len(message_link_previews_ok)
|
|
+ len(message_link_previews_values)
|
|
+ len(link_previews_values)
|
|
> 5
|
|
):
|
|
break
|
|
new_link_preview_by_url = {
|
|
link_preview.source_url: link_preview
|
|
for link_preview in self.env["mail.link.preview"].create(
|
|
[values for sequence, values in link_previews_values]
|
|
)
|
|
}
|
|
for sequence, values in link_previews_values:
|
|
message_link_previews_values.append(
|
|
(sequence, new_link_preview_by_url[values["source_url"]])
|
|
)
|
|
message_link_previews_ok += self.env["mail.message.link.preview"].create(
|
|
[
|
|
{
|
|
"sequence": sequence,
|
|
"link_preview_id": link_preview.id,
|
|
"message_id": message.id,
|
|
}
|
|
for sequence, link_preview in message_link_previews_values
|
|
]
|
|
)
|
|
(message.sudo().message_link_preview_ids - message_link_previews_ok)._unlink_and_notify()
|
|
Store(
|
|
bus_channel=message._bus_channel(),
|
|
).add(message, "message_link_preview_ids").bus_send()
|
|
|
|
@api.model
|
|
def _is_link_preview_enabled(self):
|
|
link_preview_throttle = int(self.env['ir.config_parameter'].sudo().get_param('mail.link_preview_throttle', 99))
|
|
return link_preview_throttle > 0
|
|
|
|
def _is_domain_thottled(self, url):
|
|
domain = urlparse(url).netloc
|
|
date_interval = fields.Datetime.to_string((datetime.now() - relativedelta(seconds=10)))
|
|
call_counter = self.env["mail.link.preview"].search_count(
|
|
[("source_url", "ilike", domain), ("create_date", ">", date_interval)]
|
|
)
|
|
link_preview_throttle = int(
|
|
self.env["ir.config_parameter"].get_param("mail.link_preview_throttle", 99)
|
|
)
|
|
return call_counter > link_preview_throttle
|
|
|
|
@api.model
|
|
def _search_or_create_from_url(self, url):
|
|
"""Return the URL preview, first from the database if available otherwise make the request."""
|
|
preview = self.env["mail.link.preview"].search([("source_url", "=", url)])
|
|
if not preview:
|
|
if self._is_domain_thottled(url):
|
|
return self.env["mail.link.preview"]
|
|
preview_values = get_link_preview_from_url(url)
|
|
if not preview_values:
|
|
return self.env["mail.link.preview"]
|
|
preview = self.env['mail.link.preview'].create(preview_values)
|
|
return preview
|
|
|
|
def _to_store_defaults(self, target):
|
|
return [
|
|
"image_mimetype",
|
|
"og_description",
|
|
"og_image",
|
|
"og_mimetype",
|
|
"og_site_name",
|
|
"og_title",
|
|
"og_type",
|
|
"source_url",
|
|
]
|