forked from Mapan/odoo17e
108 lines
5.1 KiB
Python
108 lines
5.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import base64
|
|
import json
|
|
import logging
|
|
import requests
|
|
from werkzeug.urls import url_join
|
|
|
|
from odoo import _, api, fields, models, tools
|
|
from odoo.addons.iap.tools import iap_tools
|
|
from odoo.exceptions import UserError
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
try:
|
|
from google.oauth2 import service_account
|
|
from google.auth.transport import requests as google_requests
|
|
except ImportError:
|
|
service_account = None
|
|
|
|
|
|
class SocialAccountPushNotifications(models.Model):
|
|
_inherit = 'social.account'
|
|
|
|
website_id = fields.Many2one('website', string="Website",
|
|
help="This firebase configuration will only be used for the specified website", ondelete='cascade')
|
|
firebase_use_own_account = fields.Boolean('Use your own Firebase account', related='website_id.firebase_use_own_account')
|
|
firebase_project_id = fields.Char('Firebase Project ID', related='website_id.firebase_project_id')
|
|
firebase_web_api_key = fields.Char('Firebase Web API Key', related='website_id.firebase_web_api_key')
|
|
firebase_push_certificate_key = fields.Char('Firebase Push Certificate Key', related='website_id.firebase_push_certificate_key')
|
|
firebase_sender_id = fields.Char('Firebase Sender ID', related='website_id.firebase_sender_id')
|
|
firebase_admin_key_file = fields.Binary('Firebase Admin Key File', related='website_id.firebase_admin_key_file')
|
|
|
|
notification_request_title = fields.Char('Notification Request Title', related='website_id.notification_request_title')
|
|
notification_request_body = fields.Text('Notification Request Text', related='website_id.notification_request_body')
|
|
notification_request_delay = fields.Integer('Notification Request Delay (seconds)', related='website_id.notification_request_delay')
|
|
notification_request_icon = fields.Binary("Notification Request Icon", related='website_id.notification_request_icon')
|
|
|
|
_sql_constraints = [('website_unique', 'unique(website_id)', 'There is already a configuration for this website.')]
|
|
|
|
@api.ondelete(at_uninstall=False)
|
|
def _unlink_except_push_notification_account(self):
|
|
if not self.env.user.has_group('base.group_system') and any(account.website_id for account in self):
|
|
raise UserError(_("You can't delete a Push Notification account."))
|
|
|
|
def _firebase_send_message(self, data, visitors):
|
|
visitors = visitors.filtered(lambda visitor: visitor.push_subscription_ids)
|
|
if self.firebase_use_own_account:
|
|
self._firebase_send_message_from_configuration(data, visitors)
|
|
else:
|
|
self._firebase_send_message_from_iap(data, visitors)
|
|
|
|
def _firebase_send_message_from_configuration(self, data, visitors):
|
|
""" Sends messages one by one using the firebase REST API.
|
|
It requires a bearer token for authentication that we obtain using the google_auth library.
|
|
Returns he matched website.visitors (search_read records). """
|
|
|
|
if not visitors:
|
|
return [], []
|
|
|
|
if not self.firebase_admin_key_file:
|
|
raise UserError(_("Firebase Admin Key File is missing from the configuration."))
|
|
|
|
tokens = visitors.mapped('push_subscription_ids.push_token')
|
|
if service_account:
|
|
firebase_data = json.loads(
|
|
base64.b64decode(self.firebase_admin_key_file).decode())
|
|
firebase_credentials = service_account.Credentials.from_service_account_info(
|
|
firebase_data,
|
|
scopes=['https://www.googleapis.com/auth/firebase.messaging']
|
|
)
|
|
firebase_credentials.refresh(google_requests.Request())
|
|
auth_token = firebase_credentials.token
|
|
|
|
for token in tokens:
|
|
requests.post(
|
|
f'https://fcm.googleapis.com/v1/projects/{firebase_data["project_id"]}/messages:send',
|
|
json={
|
|
'message': {
|
|
'data': data,
|
|
'token': token
|
|
}
|
|
},
|
|
headers={'authorization': f'Bearer {auth_token}'},
|
|
timeout=5
|
|
)
|
|
else:
|
|
raise UserError(_('You have to install "google_auth>=1.18.0" to be able to send push notifications.'))
|
|
|
|
return tokens
|
|
|
|
def _firebase_send_message_from_iap(self, data, visitors):
|
|
social_iap_endpoint = self.env['ir.config_parameter'].sudo().get_param(
|
|
'social.social_iap_endpoint',
|
|
self.env['social.media']._DEFAULT_SOCIAL_IAP_ENDPOINT
|
|
)
|
|
batch_size = 100
|
|
|
|
tokens = visitors.mapped('push_subscription_ids.push_token')
|
|
data.update({'db_uuid': self.env['ir.config_parameter'].sudo().get_param('database.uuid')})
|
|
for tokens_batch in tools.split_every(batch_size, tokens, piece_maker=list):
|
|
batch_data = dict(data)
|
|
batch_data['tokens'] = tokens_batch
|
|
iap_tools.iap_jsonrpc(url_join(social_iap_endpoint, '/iap/social_push_notifications/firebase_send_message'), params=batch_data)
|
|
|
|
return []
|