98 lines
3.2 KiB
TypeScript
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,
|
|
};
|
|
}
|