84 lines
2.7 KiB
TypeScript
84 lines
2.7 KiB
TypeScript
import * as jose from "https://deno.land/x/jose@v5.9.6/index.ts";
|
|
import { getUserByEmail } from "./supabase.ts";
|
|
import { SupabaseClient } from "@supabase/supabase-js";
|
|
import crypto from "node:crypto";
|
|
import { Buffer } from "node:buffer";
|
|
import { Encoder } from "@evan/opus";
|
|
|
|
export const defaultVolume = 50;
|
|
|
|
// Define your audio parameters
|
|
export const SAMPLE_RATE = 24000; // For example, 24000 Hz
|
|
const CHANNELS = 1; // Mono (set to 2 if you have stereo)
|
|
const FRAME_DURATION = 120; // Frame length in ms
|
|
const BYTES_PER_SAMPLE = 2; // 16-bit PCM: 2 bytes per sample
|
|
const FRAME_SIZE = (SAMPLE_RATE * FRAME_DURATION / 1000) * CHANNELS *
|
|
BYTES_PER_SAMPLE; // 960 bytes for 24000 Hz mono 16-bit
|
|
|
|
const encoder = new Encoder({
|
|
channels: CHANNELS,
|
|
sample_rate: SAMPLE_RATE,
|
|
application: "voip",
|
|
});
|
|
|
|
encoder.expert_frame_duration = FRAME_DURATION;
|
|
encoder.bitrate = 12000;
|
|
|
|
export const openaiApiKey = Deno.env.get("OPENAI_API_KEY");
|
|
export const geminiApiKey = Deno.env.get("GEMINI_API_KEY");
|
|
export const elevenLabsApiKey = Deno.env.get("ELEVENLABS_API_KEY");
|
|
|
|
export { encoder, FRAME_SIZE };
|
|
|
|
export const isDev = Deno.env.get("DEV_MODE") === "True";
|
|
|
|
export const authenticateUser = async (
|
|
supabaseClient: SupabaseClient,
|
|
authToken: string,
|
|
): Promise<IUser> => {
|
|
try {
|
|
const jwtSecret = Deno.env.get("JWT_SECRET_KEY");
|
|
|
|
if (!jwtSecret) throw new Error("JWT_SECRET_KEY not configured");
|
|
|
|
const secretBytes = new TextEncoder().encode(jwtSecret);
|
|
const payload = await jose.jwtVerify(authToken, secretBytes);
|
|
|
|
const { payload: { email } } = payload;
|
|
const user = await getUserByEmail(supabaseClient, email as string);
|
|
return user;
|
|
} catch (error: any) {
|
|
throw new Error(error.message || "Failed to authenticate user");
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Decrypts an encrypted secret with the same master encryption key.
|
|
* @param encryptedData - base64 string from the database
|
|
* @param iv - base64 IV from the database
|
|
* @param masterKey - 32-byte string or buffer
|
|
* @returns the original plaintext secret
|
|
*/
|
|
export function decryptSecret(
|
|
encryptedData: string,
|
|
iv: string,
|
|
masterKey: string,
|
|
) {
|
|
// Decode the base64 master key
|
|
const decodedKey = Buffer.from(masterKey, "base64");
|
|
if (decodedKey.length !== 32) {
|
|
throw new Error(
|
|
"ENCRYPTION_KEY must be 32 bytes when decoded from base64.",
|
|
);
|
|
}
|
|
|
|
const decipher = crypto.createDecipheriv(
|
|
"aes-256-cbc",
|
|
decodedKey, // Use the decoded key instead of raw masterKey
|
|
Buffer.from(iv, "base64"),
|
|
);
|
|
|
|
let decrypted = decipher.update(encryptedData, "base64", "utf8");
|
|
decrypted += decipher.final("utf8");
|
|
return decrypted;
|
|
}
|