mirror of
https://github.com/lucasrcsantana/story-generator.git
synced 2025-12-17 22:07:52 +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 { OpenAI } from 'https://deno.land/x/openai@v4.20.1/mod.ts'
|
||||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
|
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
|
||||||
|
import { createLogger } from './logger.ts'
|
||||||
|
|
||||||
const openai = new OpenAI({
|
const openai = new OpenAI({
|
||||||
apiKey: Deno.env.get('OPENAI_API_KEY')
|
apiKey: Deno.env.get('OPENAI_API_KEY')
|
||||||
@ -22,10 +23,11 @@ interface ReadingAnalysis {
|
|||||||
|
|
||||||
export async function analyzeReading(
|
export async function analyzeReading(
|
||||||
transcription: string,
|
transcription: string,
|
||||||
storyId: string
|
storyId: string,
|
||||||
|
logger: Logger
|
||||||
): Promise<ReadingAnalysis> {
|
): Promise<ReadingAnalysis> {
|
||||||
try {
|
try {
|
||||||
console.log('Analisando leitura para story_id:', storyId)
|
logger.info('analysis_start', 'Iniciando análise', { storyId })
|
||||||
|
|
||||||
const supabase = createClient(
|
const supabase = createClient(
|
||||||
Deno.env.get('SUPABASE_URL') ?? '',
|
Deno.env.get('SUPABASE_URL') ?? '',
|
||||||
@ -40,10 +42,14 @@ export async function analyzeReading(
|
|||||||
.order('page_number', { ascending: true })
|
.order('page_number', { ascending: true })
|
||||||
|
|
||||||
if (storyError) {
|
if (storyError) {
|
||||||
console.error('Erro ao buscar história:', storyError)
|
logger.error('story_fetch', storyError)
|
||||||
throw storyError
|
throw storyError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.info('story_loaded', 'História carregada', {
|
||||||
|
pageCount: storyPages?.length
|
||||||
|
})
|
||||||
|
|
||||||
if (!storyPages || storyPages.length === 0) {
|
if (!storyPages || storyPages.length === 0) {
|
||||||
console.error('Dados da história inválidos:', storyPages)
|
console.error('Dados da história inválidos:', storyPages)
|
||||||
throw new Error('Texto da história não encontrado')
|
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 { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
|
||||||
import { processAudioWithWhisper } from './whisper.ts'
|
import { processAudioWithWhisper } from './whisper.ts'
|
||||||
import { analyzeReading } from './analyzer.ts'
|
import { analyzeReading } from './analyzer.ts'
|
||||||
|
import { createLogger } from './logger.ts'
|
||||||
|
|
||||||
const corsHeaders = {
|
const corsHeaders = {
|
||||||
'Access-Control-Allow-Origin': '*',
|
'Access-Control-Allow-Origin': '*',
|
||||||
@ -37,56 +38,44 @@ serve(async (req) => {
|
|||||||
return new Response('ok', { headers: corsHeaders })
|
return new Response('ok', { headers: corsHeaders })
|
||||||
}
|
}
|
||||||
|
|
||||||
let data: any = null
|
let logger: any = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Log dos headers para debug
|
const data = await req.json()
|
||||||
console.log('Headers:', Object.fromEntries(req.headers.entries()))
|
logger = createLogger(data?.record?.id || 'unknown')
|
||||||
|
|
||||||
// Validação inicial do body
|
logger.info('request_received', 'Iniciando processamento', {
|
||||||
const body = await req.text()
|
headers: Object.fromEntries(req.headers.entries())
|
||||||
console.log('Raw body:', body)
|
})
|
||||||
console.log('Body length:', body.length)
|
|
||||||
console.log('Body type:', typeof body)
|
|
||||||
|
|
||||||
data = JSON.parse(body)
|
// Validação
|
||||||
|
if (!data?.record?.id || !data?.record?.audio_url) {
|
||||||
// Validação do record
|
logger.error('validation', new Error('Payload inválido'))
|
||||||
if (!data.record || !data.record.id || !data.record.audio_url) {
|
throw new Error('Dados inválidos')
|
||||||
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' }
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(
|
const supabase = createClient(
|
||||||
Deno.env.get('SUPABASE_URL') ?? '',
|
Deno.env.get('SUPABASE_URL') ?? '',
|
||||||
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
|
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
|
||||||
)
|
)
|
||||||
|
|
||||||
const audioRecord = data.record as AudioRecord
|
|
||||||
console.log('AudioRecord', audioRecord)
|
|
||||||
|
|
||||||
// 1. Atualiza status para processing
|
// 1. Atualiza status para processing
|
||||||
await supabase
|
await supabase
|
||||||
.from('story_recordings')
|
.from('story_recordings')
|
||||||
.update({ status: 'processing' })
|
.update({ status: 'processing' })
|
||||||
.eq('id', audioRecord.id)
|
.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
|
// 4. Atualiza o registro com os resultados
|
||||||
const updateData = {
|
const updateData = {
|
||||||
status: 'completed',
|
status: 'completed',
|
||||||
@ -102,11 +91,11 @@ serve(async (req) => {
|
|||||||
self_corrections: analysis.self_corrections || 0,
|
self_corrections: analysis.self_corrections || 0,
|
||||||
strengths: Array.isArray(analysis.strengths) ? analysis.strengths : [],
|
strengths: Array.isArray(analysis.strengths) ? analysis.strengths : [],
|
||||||
improvements: Array.isArray(analysis.improvements) ? analysis.improvements : [],
|
improvements: Array.isArray(analysis.improvements) ? analysis.improvements : [],
|
||||||
suggestions: analysis.suggestions || '',
|
suggestions: analysis.suggestions || ''
|
||||||
analysis: JSON.stringify(analysis.raw_data)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Dados para atualização:', updateData)
|
console.log('Dados para atualização:', updateData)
|
||||||
|
console.log('AudioRecord', audioRecord)
|
||||||
|
|
||||||
const { error: updateError } = await supabase
|
const { error: updateError } = await supabase
|
||||||
.from('story_recordings')
|
.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 { OpenAI } from 'https://deno.land/x/openai@v4.20.1/mod.ts'
|
||||||
|
import { createLogger } from './logger.ts'
|
||||||
|
|
||||||
const openai = new OpenAI({
|
const openai = new OpenAI({
|
||||||
apiKey: Deno.env.get('OPENAI_API_KEY')
|
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 {
|
try {
|
||||||
// Download do áudio
|
logger.info('whisper_start', 'Iniciando download do áudio', { url: audioUrl })
|
||||||
|
|
||||||
const audioResponse = await fetch(audioUrl)
|
const audioResponse = await fetch(audioUrl)
|
||||||
if (!audioResponse.ok) {
|
if (!audioResponse.ok) {
|
||||||
|
logger.error('whisper_download', new Error(`HTTP ${audioResponse.status}`))
|
||||||
throw new Error('Falha ao baixar áudio')
|
throw new Error('Falha ao baixar áudio')
|
||||||
}
|
}
|
||||||
|
|
||||||
const audioBlob = await audioResponse.blob()
|
const audioBlob = await audioResponse.blob()
|
||||||
|
logger.info('whisper_download_complete', 'Download concluído', {
|
||||||
|
size: audioBlob.size,
|
||||||
|
type: audioBlob.type
|
||||||
|
})
|
||||||
|
|
||||||
// Debug do áudio
|
// Debug do áudio
|
||||||
console.log('Audio blob:', {
|
console.log('Audio blob:', {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user