You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

273 lines
12 KiB

# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2025-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
"""
This module defines HTTP controllers for handling transcription-related requests
in the Meeting Summarizer module, including interactions with the OpenAI API.
"""
import base64
import json
import openai
from odoo import _
from odoo import http
from odoo.exceptions import ValidationError
from odoo.http import request
class TranscriptionController(http.Controller):
"""Transcription controllers"""
@http.route('/get/transcription_data', type='json', auth='public')
def get_transcription_file(self, **kwargs):
"""Controller is used to store the transcription data"""
transcription_id = kwargs['id']
if not transcription_id:
return {'error': 'No ID provided'}
cache_key = f"transcription_id_{transcription_id}"
stored_data = request.env['ir.config_parameter'].sudo().get_param(
cache_key)
if stored_data:
transcription_list = json.loads(stored_data)
else:
transcription_list = []
transcription_list.append(kwargs)
request.env['ir.config_parameter'].sudo().set_param(cache_key,
json.dumps(
transcription_list))
return {'message': 'Data stored successfully', 'cache_key': cache_key}
@http.route('/create/transcription_file_summary', type='json', auth='user')
def get_cached_transcription_file(self, **kwargs):
"""Get the data from ir_config parameter and create
transcription file and summary file in ir_attachment"""
transcription_id = kwargs.get('kwargs', {}).get('id')
if not transcription_id:
return {'error': 'No ID provided'}
cache_key = f"transcription_id_{transcription_id}"
cached_data = request.env['ir.config_parameter'].sudo().get_param(
cache_key)
if not cached_data:
return {'error': 'No cached data found'}
cached_data = json.loads(cached_data)
text_content = "\n".join(item["data"] for item in cached_data)
api_key = request.env['ir.config_parameter'].sudo().get_param(
"meeting_summarizer.open_api_key")
if not api_key:
raise ValidationError(
_("Please Enter a valid api key in settings.."))
client = openai.OpenAI(api_key=api_key)
def create_summary(content):
response = client.chat.completions.create(
model="gpt-4-turbo",
messages=[
{"role": "system",
"content": "Summarize the following meeting transcript."},
{"role": "user", "content": content}
],
temperature=0.7,
max_tokens=500
)
return response
summary_data = create_summary(text_content)
summary_text = summary_data.choices[0].message.content # Corrected response extraction
file_data = base64.b64encode(summary_text.encode("utf-8"))
file_name = f"transcription_id_{transcription_id}.txt"
summary_file_name = f"summary_id_{transcription_id}.txt"
new_file_content = text_content.encode('utf-8')
new_file_base64 = base64.b64encode(new_file_content).decode('utf-8')
def get_attachment(attachment_name):
attachment_detail = request.env['ir.attachment'].sudo().search([
('name', '=', attachment_name),
('res_model', '=', 'ir.attachment'),
('res_id', '=', transcription_id)
], limit=1)
return attachment_detail
attachment = get_attachment(file_name)
summary_attachment = get_attachment(summary_file_name)
if attachment or summary_attachment:
existing_summary_content = (
base64.b64decode(summary_attachment.datas).decode('utf-8'))
updated_summary_content = (
existing_summary_content + "\n" + text_content) # Append new data
attachment.sudo().write({
'datas': base64.b64encode(
text_content.encode('utf-8')).decode('utf-8')
})
summary_data_update = (
create_summary(updated_summary_content))
summary_text = (
summary_data_update.choices[0].message.content) # Corrected response extraction
summary_attachment.sudo().write({
'datas': base64.b64encode(summary_text.encode('utf-8')).decode(
'utf-8')
})
else:
def create_attachment(filename, datas):
file = request.env['ir.attachment'].sudo().create({
'name': filename,
'datas': datas,
'res_model': 'ir.attachment',
'res_id': transcription_id,
'type': 'binary',
'mimetype': 'text/plain',
})
return file
attachment = create_attachment(file_name, new_file_base64)
summary_attachment = create_attachment(summary_file_name, file_data)
return {'success': True, 'attachment_id': attachment.id, 'summary': summary_attachment.id}
@http.route('/get/transcription_data/summary', type='json', auth='public')
def get_transcription_data_summary(self, **kwargs):
"""Controller for return the specific transcription and summary file"""
transcription_id = False
summary_id = False
channel_id = kwargs['kwargs'].get('channelId', False)
attachments = request.env['ir.attachment'].sudo().search(
[('res_id', '=', int(channel_id)),
('res_model', '=', 'ir.attachment')])
for attachment in attachments:
if attachment.name == f"transcription_id_{channel_id}.txt":
transcription_id = attachment.id
else:
summary_id = attachment.id
return {'transcriptionId': transcription_id,
'summaryId': summary_id}
@http.route('/create/send_transcription/record', type='json', auth='public')
def get_send_transcription_id(self, **kwargs):
"""create a record in send_mail_transcription using partner_ids,subject
email_body,transcription_attachment_ids, summary_attachment_ids and
return the corresponding record id"""
subject = kwargs['kwargs'].get('subject')
email_body = kwargs['kwargs'].get('email_body')
partner_ids = kwargs['kwargs'].get('partnerIds')
transcription_id = kwargs['kwargs'].get('transcriptionId')
summary_id = kwargs['kwargs'].get('summaryId')
transcription_id = request.env['ir.attachment'].browse(transcription_id)
summary_id = request.env['ir.attachment'].browse(summary_id)
send_mail_transcription_id = request.env['send.mail.transcription'].create(
{'partner_ids': partner_ids,
'subject': subject,
'email_body': email_body,
'transcription_attachment_ids': transcription_id,
'summary_attachment_ids': summary_id})
return send_mail_transcription_id.id
@http.route('/check/auto_mail_send', type='json', auth='public')
def check_auto_mail_send(self, **kwargs):
"""Here checking the configuration settings that auto_mail_send_option
enable or not and also get all the values from that and return the
specific participant details"""
channel_id = kwargs['kwargs'].get('channelId', False)
auto_mail_send = request.env['ir.config_parameter'].sudo().get_param(
"meeting_summarizer.auto_mail_send")
select_users = request.env['ir.config_parameter'].sudo().get_param(
"meeting_summarizer.select_user")
participants = []
if auto_mail_send and select_users:
partner_details = request.env['discuss.channel.member'].sudo().search(
[('channel_id', '=', channel_id)]
)
host = request.env['discuss.channel'].browse(channel_id)
for rec in partner_details:
user = request.env['res.users'].search(
[('partner_id', '=', rec.partner_id.id)]
)
if user:
if select_users == 'host':
participants.append({
'partner_id': host.create_uid.partner_id.id,
'email': host.create_uid.email
})
break # Exit the loop after adding the host, no need for further logic
if user.has_group('base.group_user'):
participants.append({
'partner_id': rec.partner_id.id,
'email': rec.partner_id.email
})
return participants
@http.route('/send/auto_email', type='json', auth='public')
def send_auto_mail(self, **kwargs):
"""Here sending automatic mail for selected users in settings."""
transcription_id = kwargs['kwargs'].get('transcriptionId')
summary_id = kwargs['kwargs'].get('summaryId')
email_body = kwargs['kwargs'].get('email_body')
subject = kwargs['kwargs'].get('subject')
partners_email = kwargs['kwargs'].get('partners_email',
[])
if not partners_email:
return {
'error': 'No valid email addresses found for the selected partners.'}
from_mail = request.env.user.email
attachment_ids = []
if transcription_id and summary_id:
attachment_ids.append((4, transcription_id))
attachment_ids.append((4, summary_id))
email_values = {
'email_from': from_mail,
'email_to': ','.join(partners_email), # Convert email list to string
'subject': subject,
'body_html': email_body,
'attachment_ids': attachment_ids, # Attach files if available
}
email = request.env['mail.mail'].sudo().create(email_values)
email.send()
return True
@http.route('/get/Meeting/creator', type='json', auth='public')
def get_meeting_creator(self, **kwargs):
"""Return the channel creator"""
channel_id = kwargs['kwargs'].get('channelId', False)
channel_details = request.env['discuss.channel'].sudo().browse(channel_id)
return channel_details.create_uid.id
@http.route('/attach/transcription_data/summary', type='json',
auth='public')
def attach_transcription_data_summary(self, **kwargs):
"""Controller for return the specific transcription and summary file"""
transcription_id = False
summary_id = False
channel_id = kwargs['kwargs'].get('channelId', False)
attachments = request.env['ir.attachment'].sudo().search(
[('res_id', '=', int(channel_id)),
('res_model', '=', 'ir.attachment')])
for attachment in attachments:
if attachment.name == f"transcription_id_{channel_id}.txt":
transcription_id = attachment.id
else:
summary_id = attachment.id
channel = request.env['discuss.channel'].sudo().browse(int(channel_id))
attachment_ids = list(filter(None, [transcription_id, summary_id]))
odoo_bot_user = request.env.ref('base.user_root')
channel.with_user(odoo_bot_user).message_post(
body="📝 Meeting transcription and summary are now available.",
message_type='comment',
subtype_xmlid='mail.mt_comment',
attachment_ids=attachment_ids
)
return True