summaryrefslogtreecommitdiff
path: root/addons/pad/models
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/pad/models
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/pad/models')
-rw-r--r--addons/pad/models/__init__.py6
-rw-r--r--addons/pad/models/pad.py149
-rw-r--r--addons/pad/models/res_company.py11
-rw-r--r--addons/pad/models/res_config_settings.py11
4 files changed, 177 insertions, 0 deletions
diff --git a/addons/pad/models/__init__.py b/addons/pad/models/__init__.py
new file mode 100644
index 00000000..24e85f37
--- /dev/null
+++ b/addons/pad/models/__init__.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import res_config_settings
+from . import pad
+from . import res_company
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)
diff --git a/addons/pad/models/res_company.py b/addons/pad/models/res_company.py
new file mode 100644
index 00000000..18c05556
--- /dev/null
+++ b/addons/pad/models/res_company.py
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import fields, models
+
+
+class ResCompany(models.Model):
+ _inherit = 'res.company'
+
+ pad_server = fields.Char(help="Etherpad lite server. Example: beta.primarypad.com")
+ pad_key = fields.Char('Pad Api Key', help="Etherpad lite api key.", groups="base.group_system")
diff --git a/addons/pad/models/res_config_settings.py b/addons/pad/models/res_config_settings.py
new file mode 100644
index 00000000..25b3ece4
--- /dev/null
+++ b/addons/pad/models/res_config_settings.py
@@ -0,0 +1,11 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import fields, models
+
+
+class ResConfigSettings(models.TransientModel):
+ _inherit = 'res.config.settings'
+
+ pad_server = fields.Char(related='company_id.pad_server', string="Pad Server", readonly=False)
+ pad_key = fields.Char(related='company_id.pad_key', string="Pad API Key", readonly=False)