138 lines
3.8 KiB
TypeScript
138 lines
3.8 KiB
TypeScript
"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");
|
|
}
|
|
};
|