mirror of
https://github.com/lucasrcsantana/story-generator.git
synced 2025-12-17 05:47:52 +00:00
Some checks are pending
Docker Build and Push / build (push) Waiting to run
- Cria estrutura completa de banco de dados para exerc��cios f��nicos - Implementa tabelas para categorias, tipos, exerc��cios e palavras - Adiciona sistema de progresso e conquistas do estudante - Configura pol��ticas de seguran��a RLS para prote����o dos dados - Otimiza performance com ��ndices e relacionamentos apropriados BREAKING CHANGE: Nova estrutura de banco de dados para exerc��cios f��nicos
109 lines
3.0 KiB
TypeScript
109 lines
3.0 KiB
TypeScript
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
|
|
import { createClient } from "https://esm.sh/@supabase/supabase-js@2";
|
|
|
|
const corsHeaders = {
|
|
'Access-Control-Allow-Origin': '*',
|
|
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
|
|
};
|
|
|
|
serve(async (req) => {
|
|
if (req.method === 'OPTIONS') {
|
|
return new Response('ok', { headers: corsHeaders });
|
|
}
|
|
|
|
try {
|
|
const { word } = await req.json();
|
|
|
|
if (!word || typeof word !== 'string') {
|
|
throw new Error('Palavra inválida');
|
|
}
|
|
|
|
// Criar cliente Supabase
|
|
const supabaseClient = createClient(
|
|
Deno.env.get('SUPABASE_URL') ?? '',
|
|
Deno.env.get('SUPABASE_ANON_KEY') ?? ''
|
|
);
|
|
|
|
// Verificar se já existe áudio para esta palavra
|
|
const { data: existingAudio } = await supabaseClient
|
|
.from('phonics_word_audio')
|
|
.select('audio_url')
|
|
.eq('word', word.toLowerCase())
|
|
.single();
|
|
|
|
if (existingAudio?.audio_url) {
|
|
return new Response(
|
|
JSON.stringify({ audioUrl: existingAudio.audio_url }),
|
|
{ headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
);
|
|
}
|
|
|
|
// Gerar novo áudio usando Text-to-Speech
|
|
const response = await fetch('https://api.elevenlabs.io/v1/text-to-speech/21m00Tcm4TlvDq8ikWAM', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'xi-api-key': Deno.env.get('ELEVEN_LABS_API_KEY') ?? '',
|
|
},
|
|
body: JSON.stringify({
|
|
text: word,
|
|
model_id: "eleven_multilingual_v2",
|
|
voice_settings: {
|
|
stability: 0.75,
|
|
similarity_boost: 0.75,
|
|
style: 0.5,
|
|
use_speaker_boost: true
|
|
}
|
|
}),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
throw new Error('Erro ao gerar áudio');
|
|
}
|
|
|
|
const audioBuffer = await response.arrayBuffer();
|
|
const audioBase64 = btoa(String.fromCharCode(...new Uint8Array(audioBuffer)));
|
|
|
|
// Salvar áudio no storage
|
|
const fileName = `${word.toLowerCase()}_${Date.now()}.mp3`;
|
|
const { error: uploadError } = await supabaseClient.storage
|
|
.from('phonics-audio')
|
|
.upload(fileName, audioBuffer, {
|
|
contentType: 'audio/mpeg',
|
|
cacheControl: '31536000', // 1 ano
|
|
});
|
|
|
|
if (uploadError) {
|
|
throw uploadError;
|
|
}
|
|
|
|
// Obter URL pública
|
|
const { data: { publicUrl } } = supabaseClient.storage
|
|
.from('phonics-audio')
|
|
.getPublicUrl(fileName);
|
|
|
|
// Salvar referência no banco
|
|
await supabaseClient
|
|
.from('phonics_word_audio')
|
|
.insert({
|
|
word: word.toLowerCase(),
|
|
audio_url: publicUrl,
|
|
audio_path: fileName,
|
|
});
|
|
|
|
return new Response(
|
|
JSON.stringify({ audioUrl: publicUrl }),
|
|
{ headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
|
|
);
|
|
|
|
} catch (error) {
|
|
console.error('Error:', error);
|
|
return new Response(
|
|
JSON.stringify({ error: error.message }),
|
|
{
|
|
status: 400,
|
|
headers: { ...corsHeaders, 'Content-Type': 'application/json' }
|
|
}
|
|
);
|
|
}
|
|
});
|