mirror of https://github.com/OCA/social.git
[IMP] mail_broker: Set webhook
parent
1e5b8ad89c
commit
fc541ba6bd
|
@ -1 +0,0 @@
|
||||||
from . import main
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
from . import main
|
||||||
|
from . import bot_controller
|
|
@ -0,0 +1,41 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from odoo import http
|
||||||
|
import json
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class BrokerController(http.Controller):
|
||||||
|
@http.route(
|
||||||
|
"/broker/<string:bot_key>/update",
|
||||||
|
type="json",
|
||||||
|
auth="none",
|
||||||
|
method=["POST"],
|
||||||
|
csrf=False,
|
||||||
|
)
|
||||||
|
def post_bot_updates(self, bot_key, **kwargs):
|
||||||
|
print(kwargs)
|
||||||
|
json_request = http.request.jsonrequest
|
||||||
|
bot_id = http.request.env["mail.broker"]._get_broker_id(bot_key, **kwargs)
|
||||||
|
if not bot_id:
|
||||||
|
return {}
|
||||||
|
broker = http.request.env["mail.broker"].browse(bot_id)
|
||||||
|
broker.with_user(broker.webhook_user_id.id).with_context(
|
||||||
|
notify_broker=True
|
||||||
|
)._receive_update(json_request)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
@http.route(
|
||||||
|
"/braaoker/<string:bot_key>/update",
|
||||||
|
type="http",
|
||||||
|
auth="none",
|
||||||
|
method=["GET"],
|
||||||
|
csrf=False,
|
||||||
|
)
|
||||||
|
def get_baaot_updates(self, bot_key, **kwargs):
|
||||||
|
# This might be used for verification
|
||||||
|
print(kwargs)
|
||||||
|
bot_id = http.request.env["mail.broker"]._get_broker_id(bot_key, **kwargs)
|
||||||
|
if not bot_id:
|
||||||
|
return ""
|
||||||
|
return http.request.env["mail.broker"].browse(bot_id)._verify_bot(**kwargs)
|
|
@ -1,7 +1,7 @@
|
||||||
# Copyright 2020 Creu Blanca
|
# Copyright 2020 Creu Blanca
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
from odoo import api, fields, models
|
from odoo import api, fields, models, tools
|
||||||
|
|
||||||
|
|
||||||
class MailBroker(models.Model):
|
class MailBroker(models.Model):
|
||||||
|
@ -10,16 +10,68 @@ class MailBroker(models.Model):
|
||||||
|
|
||||||
name = fields.Char(required=True)
|
name = fields.Char(required=True)
|
||||||
token = fields.Char(required=True)
|
token = fields.Char(required=True)
|
||||||
_sql_constraints = [
|
|
||||||
("mail_broker_token", "unique(token)", "Token must be unique"),
|
|
||||||
]
|
|
||||||
broker_type = fields.Selection([], required=True)
|
broker_type = fields.Selection([], required=True)
|
||||||
show_on_app = fields.Boolean(default=True)
|
show_on_app = fields.Boolean(default=True)
|
||||||
webhook_url = fields.Char()
|
webhook_key = fields.Char()
|
||||||
|
integrated_webhook = fields.Boolean(readonly=True)
|
||||||
|
can_set_webhook = fields.Boolean(compute="_compute_webhook_checks")
|
||||||
|
webhook_url = fields.Char(compute="_compute_webhook_url")
|
||||||
|
has_new_channel_security = fields.Boolean(
|
||||||
|
help="When checked, channels are not created automatically"
|
||||||
|
)
|
||||||
webhook_user_id = fields.Many2one(
|
webhook_user_id = fields.Many2one(
|
||||||
"res.users", default=lambda self: self.env.user.id
|
"res.users", default=lambda self: self.env.user.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_sql_constraints = [
|
||||||
|
("mail_broker_token", "unique(token)", "Token must be unique"),
|
||||||
|
(
|
||||||
|
"mail_broker_webhook_key",
|
||||||
|
"unique(webhook_key)",
|
||||||
|
"Webhook Key must be unique",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
@api.depends("webhook_key")
|
||||||
|
def _compute_webhook_url(self):
|
||||||
|
for record in self:
|
||||||
|
record.webhook_url = record._get_webhook_url()
|
||||||
|
|
||||||
|
def _get_webhook_url(self):
|
||||||
|
return "%s/broker/%s/update" % (
|
||||||
|
self.webhook_url
|
||||||
|
or self.env["ir.config_parameter"].get_param("web.base.url"),
|
||||||
|
self.webhook_key,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _can_set_webhook(self):
|
||||||
|
return self.webhook_key and self.webhook_user_id
|
||||||
|
|
||||||
|
@api.depends("broker_type")
|
||||||
|
def _compute_webhook_checks(self):
|
||||||
|
for record in self:
|
||||||
|
record.can_set_webhook = record._can_set_webhook()
|
||||||
|
|
||||||
|
def set_webhook(self):
|
||||||
|
self.ensure_one()
|
||||||
|
if self.can_set_webhook:
|
||||||
|
self._set_webhook()
|
||||||
|
|
||||||
|
def remove_webhook(self):
|
||||||
|
self.ensure_one()
|
||||||
|
self._remove_webhook()
|
||||||
|
|
||||||
|
def update_webhook(self):
|
||||||
|
self.ensure_one()
|
||||||
|
self.remove_webhook()
|
||||||
|
self.set_webhook()
|
||||||
|
|
||||||
|
def _set_webhook(self):
|
||||||
|
self.integrated_webhook = True
|
||||||
|
|
||||||
|
def _remove_webhook(self):
|
||||||
|
self.integrated_webhook = False
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def broker_fetch_slot(self):
|
def broker_fetch_slot(self):
|
||||||
result = []
|
result = []
|
||||||
|
@ -46,3 +98,65 @@ class MailBroker(models.Model):
|
||||||
if name:
|
if name:
|
||||||
domain += [("name", "ilike", "%" + name + "%")]
|
domain += [("name", "ilike", "%" + name + "%")]
|
||||||
return self.env["mail.broker.channel"].search(domain).read(["name"])
|
return self.env["mail.broker.channel"].search(domain).read(["name"])
|
||||||
|
|
||||||
|
def _receive_update(self, update):
|
||||||
|
return getattr(self, "_receive_update_%s" % self.broker_type)(update)
|
||||||
|
|
||||||
|
def write(self, vals):
|
||||||
|
res = super(MailBroker, self).write(vals)
|
||||||
|
if "webhook_key" in vals:
|
||||||
|
self.clear_caches()
|
||||||
|
return res
|
||||||
|
|
||||||
|
@api.model_create_single
|
||||||
|
def create(self, vals):
|
||||||
|
res = super(MailBroker, self).create(vals)
|
||||||
|
if "webhook_key" in vals:
|
||||||
|
self.clear_caches()
|
||||||
|
return res
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
@tools.ormcache()
|
||||||
|
def _get_broker_map(self):
|
||||||
|
result = {}
|
||||||
|
for record in self.search([]):
|
||||||
|
result[record.webhook_key] = record.id
|
||||||
|
return result
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def _get_broker_id(self, key, **kwargs):
|
||||||
|
# We are using cache in order to avoid an exploit
|
||||||
|
if not key:
|
||||||
|
return False
|
||||||
|
return self._get_broker_map().get(key, False)
|
||||||
|
|
||||||
|
def _get_channel_id(self, chat_token):
|
||||||
|
return (
|
||||||
|
self.env["mail.broker.channel"]
|
||||||
|
.search(
|
||||||
|
[("token", "=", str(chat_token)), ("broker_id", "=", self.id)], limit=1
|
||||||
|
)
|
||||||
|
.id
|
||||||
|
)
|
||||||
|
|
||||||
|
def _get_channel(self, token, update, force_create=False):
|
||||||
|
chat_id = self._get_channel_id(token)
|
||||||
|
if chat_id:
|
||||||
|
return self.env["mail.broker.channel"].browse(chat_id)
|
||||||
|
if not force_create and self.has_new_channel_security:
|
||||||
|
return False
|
||||||
|
return self.env["mail.broker.channel"].create(
|
||||||
|
self._get_channel_vals(token, update)
|
||||||
|
)
|
||||||
|
|
||||||
|
def _get_channel_vals(self, token, update):
|
||||||
|
return {
|
||||||
|
"token": token,
|
||||||
|
"broker_id": self.id,
|
||||||
|
"show_on_app": self.show_on_app,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _verify_bot(self, **kwargs):
|
||||||
|
self.ensure_one()
|
||||||
|
# TODO: PASS IT TO WHATSAPP
|
||||||
|
return kwargs.get("hub.challenge")
|
||||||
|
|
|
@ -15,7 +15,9 @@ class MailMessage(models.Model):
|
||||||
store=True,
|
store=True,
|
||||||
)
|
)
|
||||||
broker_unread = fields.Boolean(default=False)
|
broker_unread = fields.Boolean(default=False)
|
||||||
broker_type = fields.Selection([("telegram", "Telegram")], required=True)
|
broker_type = fields.Selection(
|
||||||
|
selection=lambda r: r.env["mail.broker"]._fields["broker_type"].selection
|
||||||
|
)
|
||||||
broker_notification_ids = fields.One2many(
|
broker_notification_ids = fields.One2many(
|
||||||
"mail.message.broker", inverse_name="mail_message_id"
|
"mail.message.broker", inverse_name="mail_message_id"
|
||||||
)
|
)
|
||||||
|
|
|
@ -51,7 +51,7 @@ class MailMessageBroker(models.Model):
|
||||||
@api.model_create_multi
|
@api.model_create_multi
|
||||||
def create(self, vals_list):
|
def create(self, vals_list):
|
||||||
messages = super().create(vals_list)
|
messages = super().create(vals_list)
|
||||||
if self.env.context.get("notify_broker", True):
|
if self.env.context.get("notify_broker", False):
|
||||||
notifications = []
|
notifications = []
|
||||||
for message in messages:
|
for message in messages:
|
||||||
notifications.append(
|
notifications.append(
|
||||||
|
|
|
@ -9,17 +9,42 @@
|
||||||
<form>
|
<form>
|
||||||
<header />
|
<header />
|
||||||
<sheet>
|
<sheet>
|
||||||
<div class="oe_button_box" name="button_box" />
|
<div class="oe_button_box" name="button_box">
|
||||||
|
<button
|
||||||
|
type="object"
|
||||||
|
string="Integrate Webhook"
|
||||||
|
icon="fa-plug"
|
||||||
|
name="set_webhook"
|
||||||
|
attrs="{'invisible': ['|', ('can_set_webhook', '=', False), ('integrated_webhook', '=', True)]}"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="object"
|
||||||
|
string="Update Webhook"
|
||||||
|
name="update_webhook"
|
||||||
|
icon="fa-refresh"
|
||||||
|
attrs="{'invisible': ['|', ('can_set_webhook', '=', False), ('integrated_webhook', '=', False)]}"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="object"
|
||||||
|
string="Remove Webhook"
|
||||||
|
name="remove_webhook"
|
||||||
|
icon="fa-remove"
|
||||||
|
attrs="{'invisible': [('integrated_webhook', '=', False)]}"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<field name="can_set_webhook" invisible="1" />
|
||||||
|
<field name="integrated_webhook" invisible="1" />
|
||||||
<group>
|
<group>
|
||||||
<field name="name" />
|
<field name="name" />
|
||||||
<field name="show_on_app" />
|
<field name="show_on_app" />
|
||||||
<field name="token" />
|
<field name="token" />
|
||||||
<field name="broker_type" />
|
<field name="broker_type" />
|
||||||
<field name="webhook_url" />
|
<field name="webhook_url" groups="base.group_no_one" />
|
||||||
|
<field name="webhook_key" />
|
||||||
<field name="webhook_user_id" />
|
<field name="webhook_user_id" />
|
||||||
|
<field name="has_new_channel_security" />
|
||||||
</group>
|
</group>
|
||||||
</sheet>
|
</sheet>
|
||||||
<div class="oe_chatter" />
|
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
<field name="show_on_app" />
|
<field name="show_on_app" />
|
||||||
<field name="token" />
|
<field name="token" />
|
||||||
</field>
|
</field>
|
||||||
<xpath expr="//div[@name='button_box']" position="inside" />
|
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
<record model="ir.ui.view" id="mail_broker_channel_search_view">
|
<record model="ir.ui.view" id="mail_broker_channel_search_view">
|
||||||
|
@ -53,14 +52,14 @@
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
<record model="ir.actions.act_window" id="mail_broker_channel_act_window">
|
<record model="ir.actions.act_window" id="mail_broker_channel_act_window">
|
||||||
<field name="name">Mail Broken Channel</field>
|
<field name="name">Mail Broker Channel</field>
|
||||||
<field name="res_model">mail.broker.channel</field>
|
<field name="res_model">mail.broker.channel</field>
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
<field name="domain">[]</field>
|
<field name="domain">[]</field>
|
||||||
<field name="context">{}</field>
|
<field name="context">{}</field>
|
||||||
</record>
|
</record>
|
||||||
<record model="ir.ui.menu" id="mail_broker_channel_menu">
|
<record model="ir.ui.menu" id="mail_broker_channel_menu">
|
||||||
<field name="name">Mail Broken Channel</field>
|
<field name="name">Mail Broker Channel</field>
|
||||||
<field name="parent_id" ref="base.menu_email" />
|
<field name="parent_id" ref="base.menu_email" />
|
||||||
<field name="action" ref="mail_broker_channel_act_window" />
|
<field name="action" ref="mail_broker_channel_act_window" />
|
||||||
<field name="sequence" eval="16" />
|
<field name="sequence" eval="16" />
|
||||||
|
|
Loading…
Reference in New Issue