"use server"; import { encodedRedirect } from "@/utils/utils"; import { createClient } from "@/utils/supabase/server"; import { headers } from "next/headers"; import { redirect } from "next/navigation"; import { Provider } from "@supabase/supabase-js"; import { revalidatePath } from "next/cache"; import { ElevenLabsClient } from "elevenlabs"; import { Readable } from "stream"; export const signUpAction = async (formData: FormData) => { const email = formData.get("email")?.toString(); const password = formData.get("password")?.toString(); const supabase = await createClient(); const origin = (await headers()).get("origin"); if (!email || !password) { return encodedRedirect("error", "/login", "Email is required"); } const { error } = await supabase.auth.signUp({ email, password, options: { emailRedirectTo: `${origin}/auth/callback`, }, }); if (error) { console.error(error.code + " " + error.message); return encodedRedirect("error", "/sign-up", error.message); } else { return encodedRedirect( "success", "/sign-up", "Thanks for signing up! Please check your email for a verification link." ); } }; export const signInAction = async (formData: FormData) => { const email = formData.get("email") as string; const provider = formData.get("provider") as Provider; const supabase = await createClient(); if (email) { const { error } = await supabase.auth.signInWithOtp({ email, options: { emailRedirectTo: `${process.env.NEXT_PUBLIC_SITE_URL}/auth/callback`, }, }); if (error) { return encodedRedirect("error", "/login", error.message); } } else if (provider) { const { error, data } = await supabase.auth.signInWithOAuth({ provider, options: { redirectTo: `${process.env.NEXT_PUBLIC_SITE_URL}/auth/callback`, }, }); if (error) { return encodedRedirect("error", "/login", error.message); } if (data?.url) { return redirect(data.url); } else { return encodedRedirect("error", "/login", "Could not sign in"); } } revalidatePath("/", "layout"); redirect("/dashboard"); }; export const signOutAction = async () => { const supabase = await createClient(); await supabase.auth.signOut(); return redirect("/login"); }; const elevenLabs = new ElevenLabsClient({ apiKey: process.env.ELEVENLABS_API_KEY, }); export const synthesizeTTSAction = async (data: { text: string; previous_text: string; next_text: string; voice: string; index: number; }) => { const { text, voice, index } = data; console.log("Generating TTS for text:", text, "with voice:", voice); if (!text) { throw new Error("Text is required"); } try { // Call ElevenLabs API to generate the audio const audioStream = await elevenLabs.textToSpeech.convertAsStream( "gUABw7pXQjhjt0kNFBTF", { text, output_format: "mp3_44100_128", voice_settings: { stability: 0.75, speed: 1.0, similarity_boost: 0.75, }, previous_text: data.previous_text, next_text: data.next_text, model_id: "eleven_flash_v2_5", // use eleven_multilingual_v2 if this doesnt sound good } ); const chunks: Buffer[] = []; for await (const chunk of audioStream) { chunks.push(chunk); } const audioBuffer = Buffer.concat(chunks); // Create a Blob from the Buffer const audioBlob = new Blob([audioBuffer], { type: "audio/mpeg" }); return audioBlob; } catch (error) { console.error("Error generating TTS:", error); throw new Error("Failed to generate TTS audio stream"); } };