Initial commit
This commit is contained in:
96
fusion_ringcentral/controllers/webhook.py
Normal file
96
fusion_ringcentral/controllers/webhook.py
Normal file
@@ -0,0 +1,96 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2026 Nexa Systems Inc.
|
||||
# License OPL-1 (Odoo Proprietary License v1.0)
|
||||
|
||||
import json
|
||||
import logging
|
||||
|
||||
from odoo import fields, http
|
||||
from odoo.http import request, Response
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RcWebhookController(http.Controller):
|
||||
|
||||
@http.route('/ringcentral/webhook', type='json', auth='none', csrf=False, methods=['POST'])
|
||||
def webhook_handler(self, **kw):
|
||||
"""Receive webhook events from RingCentral."""
|
||||
headers = request.httprequest.headers
|
||||
validation_token = headers.get('Validation-Token')
|
||||
if validation_token:
|
||||
return Response(
|
||||
status=200,
|
||||
headers={'Validation-Token': validation_token},
|
||||
)
|
||||
|
||||
try:
|
||||
body = json.loads(request.httprequest.get_data(as_text=True))
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
_logger.warning("RingCentral webhook: invalid JSON body")
|
||||
return {'status': 'error', 'message': 'Invalid JSON'}
|
||||
|
||||
event = body.get('event', '')
|
||||
_logger.info("RingCentral webhook event: %s", event)
|
||||
|
||||
if 'telephony/sessions' in event:
|
||||
self._handle_telephony_event(body)
|
||||
|
||||
return {'status': 'ok'}
|
||||
|
||||
def _handle_telephony_event(self, body):
|
||||
"""Process a telephony session event."""
|
||||
try:
|
||||
event_body = body.get('body', {})
|
||||
parties = event_body.get('parties', [])
|
||||
|
||||
for party in parties:
|
||||
status_code = party.get('status', {}).get('code', '')
|
||||
if status_code != 'Disconnected':
|
||||
continue
|
||||
|
||||
direction_raw = party.get('direction', '').lower()
|
||||
direction = 'inbound' if direction_raw == 'inbound' else 'outbound'
|
||||
|
||||
from_info = party.get('from', {})
|
||||
to_info = party.get('to', {})
|
||||
from_number = from_info.get('phoneNumber', '')
|
||||
to_number = to_info.get('phoneNumber', '')
|
||||
|
||||
session_id = event_body.get('sessionId', '')
|
||||
if not session_id:
|
||||
continue
|
||||
|
||||
env = request.env(su=True)
|
||||
existing = env['rc.call.history'].search_count([
|
||||
('rc_session_id', '=', str(session_id)),
|
||||
])
|
||||
if existing:
|
||||
continue
|
||||
|
||||
duration = party.get('duration', 0)
|
||||
result = party.get('status', {}).get('reason', 'Unknown')
|
||||
status_map = {
|
||||
'Answered': 'answered',
|
||||
'CallConnected': 'answered',
|
||||
'HangUp': 'answered',
|
||||
'Voicemail': 'voicemail',
|
||||
'Missed': 'missed',
|
||||
'NoAnswer': 'no_answer',
|
||||
'Busy': 'busy',
|
||||
'Rejected': 'rejected',
|
||||
}
|
||||
status = status_map.get(result, 'answered' if duration > 0 else 'missed')
|
||||
|
||||
env['rc.call.history'].create({
|
||||
'rc_session_id': str(session_id),
|
||||
'direction': direction,
|
||||
'from_number': from_number,
|
||||
'to_number': to_number,
|
||||
'start_time': fields.Datetime.now(),
|
||||
'duration': duration,
|
||||
'status': status,
|
||||
})
|
||||
|
||||
except Exception:
|
||||
_logger.exception("Error processing telephony webhook event")
|
||||
Reference in New Issue
Block a user