mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-21 04:39:06 +00:00
format
This commit is contained in:
@@ -189,15 +189,19 @@ class MeetingController:
|
|||||||
|
|
||||||
class MeetingConsentController:
|
class MeetingConsentController:
|
||||||
async def get_by_meeting_id(self, meeting_id: str) -> list[MeetingConsent]:
|
async def get_by_meeting_id(self, meeting_id: str) -> list[MeetingConsent]:
|
||||||
query = meeting_consent.select().where(meeting_consent.c.meeting_id == meeting_id)
|
query = meeting_consent.select().where(
|
||||||
|
meeting_consent.c.meeting_id == meeting_id
|
||||||
|
)
|
||||||
results = await database.fetch_all(query)
|
results = await database.fetch_all(query)
|
||||||
return [MeetingConsent(**result) for result in results]
|
return [MeetingConsent(**result) for result in results]
|
||||||
|
|
||||||
async def get_by_meeting_and_user(self, meeting_id: str, user_id: str) -> MeetingConsent | None:
|
async def get_by_meeting_and_user(
|
||||||
|
self, meeting_id: str, user_id: str
|
||||||
|
) -> MeetingConsent | None:
|
||||||
"""Get existing consent for a specific user and meeting"""
|
"""Get existing consent for a specific user and meeting"""
|
||||||
query = meeting_consent.select().where(
|
query = meeting_consent.select().where(
|
||||||
meeting_consent.c.meeting_id == meeting_id,
|
meeting_consent.c.meeting_id == meeting_id,
|
||||||
meeting_consent.c.user_id == user_id
|
meeting_consent.c.user_id == user_id,
|
||||||
)
|
)
|
||||||
result = await database.fetch_one(query)
|
result = await database.fetch_one(query)
|
||||||
return MeetingConsent(**result) if result else None
|
return MeetingConsent(**result) if result else None
|
||||||
@@ -207,13 +211,17 @@ class MeetingConsentController:
|
|||||||
if consent.user_id:
|
if consent.user_id:
|
||||||
# For authenticated users, check if consent already exists
|
# For authenticated users, check if consent already exists
|
||||||
# not transactional but we're ok with that; the consents ain't deleted anyways
|
# not transactional but we're ok with that; the consents ain't deleted anyways
|
||||||
existing = await self.get_by_meeting_and_user(consent.meeting_id, consent.user_id)
|
existing = await self.get_by_meeting_and_user(
|
||||||
|
consent.meeting_id, consent.user_id
|
||||||
|
)
|
||||||
if existing:
|
if existing:
|
||||||
query = meeting_consent.update().where(
|
query = (
|
||||||
meeting_consent.c.id == existing.id
|
meeting_consent.update()
|
||||||
).values(
|
.where(meeting_consent.c.id == existing.id)
|
||||||
consent_given=consent.consent_given,
|
.values(
|
||||||
consent_timestamp=consent.consent_timestamp,
|
consent_given=consent.consent_given,
|
||||||
|
consent_timestamp=consent.consent_timestamp,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
await database.execute(query)
|
await database.execute(query)
|
||||||
|
|
||||||
@@ -229,7 +237,7 @@ class MeetingConsentController:
|
|||||||
"""Check if any participant denied consent for this meeting"""
|
"""Check if any participant denied consent for this meeting"""
|
||||||
query = meeting_consent.select().where(
|
query = meeting_consent.select().where(
|
||||||
meeting_consent.c.meeting_id == meeting_id,
|
meeting_consent.c.meeting_id == meeting_id,
|
||||||
meeting_consent.c.consent_given.is_(False)
|
meeting_consent.c.consent_given.is_(False),
|
||||||
)
|
)
|
||||||
result = await database.fetch_one(query)
|
result = await database.fetch_one(query)
|
||||||
return result is not None
|
return result is not None
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ recordings = sa.Table(
|
|||||||
sa.Column("meeting_id", sa.String),
|
sa.Column("meeting_id", sa.String),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Recording(BaseModel):
|
class Recording(BaseModel):
|
||||||
id: str = Field(default_factory=generate_uuid4)
|
id: str = Field(default_factory=generate_uuid4)
|
||||||
bucket_name: str
|
bucket_name: str
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ transcripts = sqlalchemy.Table(
|
|||||||
sqlalchemy.Column("audio_deleted", sqlalchemy.Boolean, nullable=True),
|
sqlalchemy.Column("audio_deleted", sqlalchemy.Boolean, nullable=True),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def generate_transcript_name() -> str:
|
def generate_transcript_name() -> str:
|
||||||
now = datetime.utcnow()
|
now = datetime.utcnow()
|
||||||
return f"Transcript {now.strftime('%Y-%m-%d %H:%M:%S')}"
|
return f"Transcript {now.strftime('%Y-%m-%d %H:%M:%S')}"
|
||||||
@@ -550,12 +551,16 @@ class TranscriptController:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if transcript.audio_deleted:
|
if transcript.audio_deleted:
|
||||||
raise FileNotFoundError(f"Invalid state of transcript {transcript.id}: audio_deleted mark is set true")
|
raise FileNotFoundError(
|
||||||
|
f"Invalid state of transcript {transcript.id}: audio_deleted mark is set true"
|
||||||
|
)
|
||||||
|
|
||||||
if transcript.audio_location == "local":
|
if transcript.audio_location == "local":
|
||||||
# store the audio on external storage if it's not already there
|
# store the audio on external storage if it's not already there
|
||||||
if not transcript.audio_mp3_filename.exists():
|
if not transcript.audio_mp3_filename.exists():
|
||||||
raise FileNotFoundError(f"Audio file not found: {transcript.audio_mp3_filename}")
|
raise FileNotFoundError(
|
||||||
|
f"Audio file not found: {transcript.audio_mp3_filename}"
|
||||||
|
)
|
||||||
|
|
||||||
await get_transcripts_storage().put_file(
|
await get_transcripts_storage().put_file(
|
||||||
transcript.storage_audio_path,
|
transcript.storage_audio_path,
|
||||||
|
|||||||
@@ -581,7 +581,9 @@ async def cleanup_consent(transcript: Transcript, logger: Logger):
|
|||||||
if recording and recording.meeting_id:
|
if recording and recording.meeting_id:
|
||||||
meeting = await meetings_controller.get_by_id(recording.meeting_id)
|
meeting = await meetings_controller.get_by_id(recording.meeting_id)
|
||||||
if meeting:
|
if meeting:
|
||||||
consent_denied = await meeting_consent_controller.has_any_denial(meeting.id)
|
consent_denied = await meeting_consent_controller.has_any_denial(
|
||||||
|
meeting.id
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Failed to get fetch consent: {e}")
|
logger.error(f"Failed to get fetch consent: {e}")
|
||||||
consent_denied = True
|
consent_denied = True
|
||||||
@@ -600,8 +602,12 @@ async def cleanup_consent(transcript: Transcript, logger: Logger):
|
|||||||
aws_secret_access_key=settings.AWS_WHEREBY_ACCESS_KEY_SECRET,
|
aws_secret_access_key=settings.AWS_WHEREBY_ACCESS_KEY_SECRET,
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
s3_whereby.delete_object(Bucket=recording.bucket_name, Key=recording.object_key)
|
s3_whereby.delete_object(
|
||||||
logger.info(f"Deleted original Whereby recording: {recording.bucket_name}/{recording.object_key}")
|
Bucket=recording.bucket_name, Key=recording.object_key
|
||||||
|
)
|
||||||
|
logger.info(
|
||||||
|
f"Deleted original Whereby recording: {recording.bucket_name}/{recording.object_key}"
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Failed to delete Whereby recording: {e}")
|
logger.error(f"Failed to delete Whereby recording: {e}")
|
||||||
|
|
||||||
@@ -613,15 +619,17 @@ async def cleanup_consent(transcript: Transcript, logger: Logger):
|
|||||||
storage = get_transcripts_storage()
|
storage = get_transcripts_storage()
|
||||||
try:
|
try:
|
||||||
await storage.delete_file(transcript.storage_audio_path)
|
await storage.delete_file(transcript.storage_audio_path)
|
||||||
logger.info(f"Deleted processed audio from storage: {transcript.storage_audio_path}")
|
logger.info(
|
||||||
|
f"Deleted processed audio from storage: {transcript.storage_audio_path}"
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Failed to delete processed audio: {e}")
|
logger.error(f"Failed to delete processed audio: {e}")
|
||||||
|
|
||||||
# 3. Delete local audio files
|
# 3. Delete local audio files
|
||||||
try:
|
try:
|
||||||
if hasattr(transcript, 'audio_mp3_filename') and transcript.audio_mp3_filename:
|
if hasattr(transcript, "audio_mp3_filename") and transcript.audio_mp3_filename:
|
||||||
transcript.audio_mp3_filename.unlink(missing_ok=True)
|
transcript.audio_mp3_filename.unlink(missing_ok=True)
|
||||||
if hasattr(transcript, 'audio_wav_filename') and transcript.audio_wav_filename:
|
if hasattr(transcript, "audio_wav_filename") and transcript.audio_wav_filename:
|
||||||
transcript.audio_wav_filename.unlink(missing_ok=True)
|
transcript.audio_wav_filename.unlink(missing_ok=True)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Failed to delete local audio files: {e}")
|
logger.error(f"Failed to delete local audio files: {e}")
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
from .base import Storage # noqa
|
from .base import Storage # noqa
|
||||||
|
|
||||||
|
|
||||||
def get_transcripts_storage() -> Storage:
|
def get_transcripts_storage() -> Storage:
|
||||||
from reflector.settings import settings
|
from reflector.settings import settings
|
||||||
|
|
||||||
return Storage.get_instance(
|
return Storage.get_instance(
|
||||||
name=settings.TRANSCRIPT_STORAGE_BACKEND,
|
name=settings.TRANSCRIPT_STORAGE_BACKEND,
|
||||||
settings_prefix="TRANSCRIPT_STORAGE_",
|
settings_prefix="TRANSCRIPT_STORAGE_",
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ def range_requests_response(
|
|||||||
|
|
||||||
if not os.path.exists(file_path):
|
if not os.path.exists(file_path):
|
||||||
from fastapi import HTTPException
|
from fastapi import HTTPException
|
||||||
|
|
||||||
raise HTTPException(status_code=404, detail="File not found")
|
raise HTTPException(status_code=404, detail="File not found")
|
||||||
|
|
||||||
file_size = os.stat(file_path).st_size
|
file_size = os.stat(file_path).st_size
|
||||||
|
|||||||
@@ -87,7 +87,9 @@ async def transcript_get_audio_mp3(
|
|||||||
)
|
)
|
||||||
|
|
||||||
if transcript.audio_deleted:
|
if transcript.audio_deleted:
|
||||||
raise HTTPException(status_code=404, detail="Audio unavailable due to privacy settings")
|
raise HTTPException(
|
||||||
|
status_code=404, detail="Audio unavailable due to privacy settings"
|
||||||
|
)
|
||||||
|
|
||||||
if not transcript.audio_mp3_filename.exists():
|
if not transcript.audio_mp3_filename.exists():
|
||||||
raise HTTPException(status_code=404, detail="Audio file not found")
|
raise HTTPException(status_code=404, detail="Audio file not found")
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ async def process_recording(bucket_name: str, object_key: str):
|
|||||||
|
|
||||||
task_pipeline_process.delay(transcript_id=transcript.id)
|
task_pipeline_process.delay(transcript_id=transcript.id)
|
||||||
|
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
@asynctask
|
@asynctask
|
||||||
async def process_meetings():
|
async def process_meetings():
|
||||||
|
|||||||
Reference in New Issue
Block a user