mirror of
https://github.com/lucasrcsantana/story-generator.git
synced 2025-12-16 21:37:51 +00:00
Erro ao salvar no supabase
This commit is contained in:
parent
6cf273126e
commit
c776efaec9
@ -1,5 +1,6 @@
|
||||
import { OpenAI } from 'https://deno.land/x/openai@v4.20.1/mod.ts'
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
|
||||
import { createLogger } from './logger.ts'
|
||||
|
||||
const openai = new OpenAI({
|
||||
apiKey: Deno.env.get('OPENAI_API_KEY')
|
||||
@ -22,10 +23,11 @@ interface ReadingAnalysis {
|
||||
|
||||
export async function analyzeReading(
|
||||
transcription: string,
|
||||
storyId: string
|
||||
storyId: string,
|
||||
logger: Logger
|
||||
): Promise<ReadingAnalysis> {
|
||||
try {
|
||||
console.log('Analisando leitura para story_id:', storyId)
|
||||
logger.info('analysis_start', 'Iniciando análise', { storyId })
|
||||
|
||||
const supabase = createClient(
|
||||
Deno.env.get('SUPABASE_URL') ?? '',
|
||||
@ -40,10 +42,14 @@ export async function analyzeReading(
|
||||
.order('page_number', { ascending: true })
|
||||
|
||||
if (storyError) {
|
||||
console.error('Erro ao buscar história:', storyError)
|
||||
logger.error('story_fetch', storyError)
|
||||
throw storyError
|
||||
}
|
||||
|
||||
logger.info('story_loaded', 'História carregada', {
|
||||
pageCount: storyPages?.length
|
||||
})
|
||||
|
||||
if (!storyPages || storyPages.length === 0) {
|
||||
console.error('Dados da história inválidos:', storyPages)
|
||||
throw new Error('Texto da história não encontrado')
|
||||
|
||||
@ -2,6 +2,7 @@ import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
|
||||
import { processAudioWithWhisper } from './whisper.ts'
|
||||
import { analyzeReading } from './analyzer.ts'
|
||||
import { createLogger } from './logger.ts'
|
||||
|
||||
const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
@ -37,56 +38,44 @@ serve(async (req) => {
|
||||
return new Response('ok', { headers: corsHeaders })
|
||||
}
|
||||
|
||||
let data: any = null
|
||||
|
||||
let logger: any = null
|
||||
|
||||
try {
|
||||
// Log dos headers para debug
|
||||
console.log('Headers:', Object.fromEntries(req.headers.entries()))
|
||||
const data = await req.json()
|
||||
logger = createLogger(data?.record?.id || 'unknown')
|
||||
|
||||
// Validação inicial do body
|
||||
const body = await req.text()
|
||||
console.log('Raw body:', body)
|
||||
console.log('Body length:', body.length)
|
||||
console.log('Body type:', typeof body)
|
||||
logger.info('request_received', 'Iniciando processamento', {
|
||||
headers: Object.fromEntries(req.headers.entries())
|
||||
})
|
||||
|
||||
data = JSON.parse(body)
|
||||
|
||||
// Validação do record
|
||||
if (!data.record || !data.record.id || !data.record.audio_url) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: 'Payload inválido',
|
||||
details: 'record, id e audio_url são obrigatórios',
|
||||
receivedData: data
|
||||
}),
|
||||
{
|
||||
status: 400,
|
||||
headers: { ...corsHeaders, 'Content-Type': 'application/json' }
|
||||
}
|
||||
)
|
||||
// Validação
|
||||
if (!data?.record?.id || !data?.record?.audio_url) {
|
||||
logger.error('validation', new Error('Payload inválido'))
|
||||
throw new Error('Dados inválidos')
|
||||
}
|
||||
|
||||
const audioRecord = data.record as AudioRecord
|
||||
logger.info('record_loaded', 'Registro carregado', audioRecord)
|
||||
|
||||
// Processamento
|
||||
logger.info('processing_start', 'Iniciando processamento do áudio')
|
||||
const transcription = await processAudioWithWhisper(audioRecord.audio_url, logger)
|
||||
logger.info('transcription_complete', 'Transcrição concluída', { length: transcription.length })
|
||||
|
||||
const analysis = await analyzeReading(transcription, audioRecord.story_id, logger)
|
||||
logger.info('analysis_complete', 'Análise concluída', { scores: analysis })
|
||||
|
||||
const supabase = createClient(
|
||||
Deno.env.get('SUPABASE_URL') ?? '',
|
||||
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
|
||||
)
|
||||
|
||||
const audioRecord = data.record as AudioRecord
|
||||
console.log('AudioRecord', audioRecord)
|
||||
|
||||
// 1. Atualiza status para processing
|
||||
await supabase
|
||||
.from('story_recordings')
|
||||
.update({ status: 'processing' })
|
||||
.eq('id', audioRecord.id)
|
||||
|
||||
// 2. Processa o áudio com Whisper
|
||||
const transcription = await processAudioWithWhisper(audioRecord.audio_url)
|
||||
|
||||
// 3. Analisa a leitura
|
||||
const analysis = await analyzeReading(transcription, audioRecord.story_id)
|
||||
console.log('Análise concluída', analysis)
|
||||
|
||||
// 4. Atualiza o registro com os resultados
|
||||
const updateData = {
|
||||
status: 'completed',
|
||||
@ -102,11 +91,11 @@ serve(async (req) => {
|
||||
self_corrections: analysis.self_corrections || 0,
|
||||
strengths: Array.isArray(analysis.strengths) ? analysis.strengths : [],
|
||||
improvements: Array.isArray(analysis.improvements) ? analysis.improvements : [],
|
||||
suggestions: analysis.suggestions || '',
|
||||
analysis: JSON.stringify(analysis.raw_data)
|
||||
suggestions: analysis.suggestions || ''
|
||||
}
|
||||
|
||||
console.log('Dados para atualização:', updateData)
|
||||
console.log('AudioRecord', audioRecord)
|
||||
|
||||
const { error: updateError } = await supabase
|
||||
.from('story_recordings')
|
||||
|
||||
37
supabase/functions/process-audio/logger.ts
Normal file
37
supabase/functions/process-audio/logger.ts
Normal file
@ -0,0 +1,37 @@
|
||||
export interface LogContext {
|
||||
requestId: string
|
||||
recordId: string
|
||||
step: string
|
||||
timestamp: string
|
||||
}
|
||||
|
||||
export function createLogger(recordId: string) {
|
||||
const requestId = crypto.randomUUID()
|
||||
|
||||
return {
|
||||
info: (step: string, message: string, data?: any) => {
|
||||
console.log(JSON.stringify({
|
||||
level: 'info',
|
||||
requestId,
|
||||
recordId,
|
||||
step,
|
||||
message,
|
||||
data,
|
||||
timestamp: new Date().toISOString()
|
||||
}))
|
||||
},
|
||||
|
||||
error: (step: string, error: Error, data?: any) => {
|
||||
console.error(JSON.stringify({
|
||||
level: 'error',
|
||||
requestId,
|
||||
recordId,
|
||||
step,
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
data,
|
||||
timestamp: new Date().toISOString()
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,17 +1,25 @@
|
||||
import { OpenAI } from 'https://deno.land/x/openai@v4.20.1/mod.ts'
|
||||
import { createLogger } from './logger.ts'
|
||||
|
||||
const openai = new OpenAI({
|
||||
apiKey: Deno.env.get('OPENAI_API_KEY')
|
||||
})
|
||||
|
||||
export async function processAudioWithWhisper(audioUrl: string): Promise<string> {
|
||||
export async function processAudioWithWhisper(audioUrl: string, logger: Logger): Promise<string> {
|
||||
try {
|
||||
// Download do áudio
|
||||
logger.info('whisper_start', 'Iniciando download do áudio', { url: audioUrl })
|
||||
|
||||
const audioResponse = await fetch(audioUrl)
|
||||
if (!audioResponse.ok) {
|
||||
logger.error('whisper_download', new Error(`HTTP ${audioResponse.status}`))
|
||||
throw new Error('Falha ao baixar áudio')
|
||||
}
|
||||
|
||||
const audioBlob = await audioResponse.blob()
|
||||
logger.info('whisper_download_complete', 'Download concluído', {
|
||||
size: audioBlob.size,
|
||||
type: audioBlob.type
|
||||
})
|
||||
|
||||
// Debug do áudio
|
||||
console.log('Audio blob:', {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user