diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/pad/models/pad.py | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/pad/models/pad.py')
| -rw-r--r-- | addons/pad/models/pad.py | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/addons/pad/models/pad.py b/addons/pad/models/pad.py new file mode 100644 index 00000000..03db1075 --- /dev/null +++ b/addons/pad/models/pad.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +import logging +import random +import re +import string + +import requests + +from odoo import api, models, _ +from odoo.exceptions import UserError + +from ..py_etherpad import EtherpadLiteClient + +_logger = logging.getLogger(__name__) + + +class PadCommon(models.AbstractModel): + _name = 'pad.common' + _description = 'Pad Common' + + def _valid_field_parameter(self, field, name): + return name == 'pad_content_field' or super()._valid_field_parameter(field, name) + + @api.model + def pad_is_configured(self): + return bool(self.env.company.pad_server) + + @api.model + def pad_generate_url(self): + company = self.env.company.sudo() + + pad = { + "server": company.pad_server, + "key": company.pad_key, + } + + # make sure pad server in the form of http://hostname + if not pad["server"]: + return pad + if not pad["server"].startswith('http'): + pad["server"] = 'http://' + pad["server"] + pad["server"] = pad["server"].rstrip('/') + # generate a salt + s = string.ascii_uppercase + string.digits + salt = ''.join([s[random.SystemRandom().randint(0, len(s) - 1)] for i in range(10)]) + # path + # etherpad hardcodes pad id length limit to 50 + path = '-%s-%s' % (self._name, salt) + path = '%s%s' % (self.env.cr.dbname.replace('_', '-')[0:50 - len(path)], path) + # contruct the url + url = '%s/p/%s' % (pad["server"], path) + + # if create with content + if self.env.context.get('field_name') and self.env.context.get('model'): + myPad = EtherpadLiteClient(pad["key"], pad["server"] + '/api') + try: + myPad.createPad(path) + except IOError: + raise UserError(_("Pad creation failed, either there is a problem with your pad server URL or with your connection.")) + + # get attr on the field model + model = self.env[self.env.context["model"]] + field = model._fields[self.env.context['field_name']] + real_field = field.pad_content_field + + res_id = self.env.context.get("object_id") + record = model.browse(res_id) + # get content of the real field + real_field_value = record[real_field] or self.env.context.get('record', {}).get(real_field, '') + if real_field_value: + myPad.setHtmlFallbackText(path, real_field_value) + + return { + "server": pad["server"], + "path": path, + "url": url, + } + + @api.model + def pad_get_content(self, url): + company = self.env.company.sudo() + myPad = EtherpadLiteClient(company.pad_key, (company.pad_server or '') + '/api') + content = '' + if url: + split_url = url.split('/p/') + path = len(split_url) == 2 and split_url[1] + try: + content = myPad.getHtml(path).get('html', '') + except IOError: + _logger.warning('Http Error: the credentials might be absent for url: "%s". Falling back.' % url) + try: + r = requests.get('%s/export/html' % url) + r.raise_for_status() + except Exception: + _logger.warning("No pad found with url '%s'.", url) + else: + mo = re.search('<body>(.*)</body>', r.content.decode(), re.DOTALL) + if mo: + content = mo.group(1) + + return content + + # TODO + # reverse engineer protocol to be setHtml without using the api key + + def write(self, vals): + self._set_field_to_pad(vals) + self._set_pad_to_field(vals) + return super(PadCommon, self).write(vals) + + @api.model + def create(self, vals): + # Case of a regular creation: we receive the pad url, so we need to update the + # corresponding field + self._set_pad_to_field(vals) + pad = super(PadCommon, self).create(vals) + + # Case of a programmatical creation (e.g. copy): we receive the field content, so we need + # to create the corresponding pad + if self.env.context.get('pad_no_create', False): + return pad + for k, field in self._fields.items(): + if hasattr(field, 'pad_content_field') and k not in vals: + ctx = { + 'model': self._name, + 'field_name': k, + 'object_id': pad.id, + } + pad_info = self.with_context(**ctx).pad_generate_url() + pad[k] = pad_info.get('url') + return pad + + def _set_field_to_pad(self, vals): + # Update the pad if the `pad_content_field` is modified + for k, field in self._fields.items(): + if hasattr(field, 'pad_content_field') and vals.get(field.pad_content_field) and self[k]: + company = self.env.user.sudo().company_id + myPad = EtherpadLiteClient(company.pad_key, (company.pad_server or '') + '/api') + path = self[k].split('/p/')[1] + myPad.setHtmlFallbackText(path, vals[field.pad_content_field]) + + def _set_pad_to_field(self, vals): + # Update the `pad_content_field` if the pad is modified + for k, v in list(vals.items()): + field = self._fields.get(k) + if hasattr(field, 'pad_content_field'): + vals[field.pad_content_field] = self.pad_get_content(v) |
