AIvoices/frontend-nextjs/lib/utils.ts
2025-04-08 14:05:27 +01:00

98 lines
3.2 KiB
TypeScript

import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
import {
defaultPersonalityId,
defaultToyId,
INITIAL_CREDITS,
SECONDS_PER_CREDIT,
} from "./data";
import crypto from "crypto";
import { createClient } from "@/utils/supabase/client";
export const getOpenGraphMetadata = (title: string) => {
return {
openGraph: {
title: `${title} | Elato AI`,
},
};
};
// code in the form: aabbccddeeff
export const isValidMacAddress = (macAddress: string): boolean => {
// Check if macAddress is a valid MAC address without separators
const macRegex = /^[0-9A-Fa-f]{12}$/;
return macRegex.test(macAddress);
};
export const getMacAddressFromDeviceCode = (deviceCode: string): string => {
// add colons to the device code
return deviceCode.substring(0, 2) + ":" + deviceCode.substring(2, 4) + ":" + deviceCode.substring(4, 6) + ":" + deviceCode.substring(6, 8) + ":" + deviceCode.substring(8, 10) + ":" + deviceCode.substring(10, 12);
};
export const getPersonalityImageSrc = (title: string) => {
return `/personality/${title.toLowerCase().replace(/\s+/g, "_")}.jpeg`;
};
export function removeEmojis(text: string): string {
const emojiPattern: RegExp =
/[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F1E0}-\u{1F1FF}\u{2702}-\u{27B0}\u{24C2}-\u{1F251}]/gu;
return text.replace(emojiPattern, "");
}
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
export const isDefaultPersonality = (personality: IPersonality) => {
return personality.personality_id === defaultPersonalityId;
};
export const getBaseUrl = () => {
return process.env.NEXT_PUBLIC_VERCEL_ENV === "production"
? "https://elatoai.com"
: "http://localhost:3000";
};
export const getUserAvatar = (avatar_url: string) => {
// return `/kidAvatar_boy_1.png`;
return avatar_url;
// get random number between 0 and 9
// const randomNum = Math.floor(Math.random() * 10);
// return `/user_avatar/user_avatar_${randomNum}.png`;
};
export const getAssistantAvatar = (imageSrc: string) => {
return "/" + imageSrc + ".png";
};
export const getCreditsRemaining = (user: IUser): number => {
const usedCredits = user.session_time / SECONDS_PER_CREDIT;
const remainingCredits = Math.round(INITIAL_CREDITS - usedCredits);
return Math.max(0, remainingCredits); // Ensure credits don't go below 0
};
export function encryptSecret(secret: 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.');
}
// Generate a 16-byte IV
const ivBuf = crypto.randomBytes(16);
// Use type assertion to string for algorithm and force the types for key and iv
const cipher = crypto.createCipheriv(
'aes-256-cbc' as string,
decodedKey as unknown as crypto.CipherKey,
ivBuf as unknown as crypto.BinaryLike
);
let encrypted = cipher.update(secret, 'utf8', 'base64');
encrypted += cipher.final('base64');
return {
iv: ivBuf.toString('base64'),
encryptedData: encrypted,
};
}