89 lines
2.7 KiB
TypeScript
89 lines
2.7 KiB
TypeScript
// utils/normalizeQuestionMedia.ts
|
|
// Shared helper for normalizing media URLs in quiz questions.
|
|
// Call before saving to KV/SQL to ensure consistent data format.
|
|
|
|
import { hashText } from "../services/stateMiddleware.ts";
|
|
|
|
/**
|
|
* Question structure with media fields
|
|
*/
|
|
export interface QuizQuestion {
|
|
id: string;
|
|
text_1: string;
|
|
text_2: string;
|
|
background_file: string;
|
|
background_image_data: string;
|
|
audio_file_1: string;
|
|
audio_file_2: string;
|
|
}
|
|
|
|
/**
|
|
* Normalizes media URLs in a question to the expected local format.
|
|
* Call this BEFORE saving to KV/SQL to ensure consistent data.
|
|
*
|
|
* Expected output formats:
|
|
* - background_image_data: "/api/ai-images/file/{filename}" or "/api/image-blob/{hashName}" or base64
|
|
* (legacy http URLs are left unchanged - they'll be handled by the serving layer)
|
|
* - audio_file_1/2: "{hashName}" or "{hashName}.webm" (just the hash, not a URL)
|
|
*
|
|
* Note: background_file stores the user's description (not a filename).
|
|
* The actual filename is embedded in the background_image_data URL path.
|
|
*
|
|
* @param question - The question object to normalize (mutated in place)
|
|
* @returns true if any field was modified
|
|
*/
|
|
export async function normalizeQuestionMedia(
|
|
question: QuizQuestion | null | undefined,
|
|
): Promise<boolean> {
|
|
let changed = false;
|
|
|
|
if (!question) {
|
|
return false;
|
|
}
|
|
|
|
// Note: We no longer try to derive background_image_data from background_file
|
|
// because background_file now stores the user's description, not a filename.
|
|
// Legacy http URLs in background_image_data are left as-is.
|
|
// New images should already have correct /api/... URLs when saved.
|
|
|
|
// Normalize audio_file_1
|
|
if (question.text_1 && question.audio_file_1) {
|
|
if (question.audio_file_1.startsWith("http")) {
|
|
// Convert to hash-based local reference
|
|
const hash = await hashText(question.id + ":" + question.text_1);
|
|
question.audio_file_1 = hash + "";
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
// Normalize audio_file_2
|
|
if (question.text_2 && question.audio_file_2) {
|
|
if (question.audio_file_2.startsWith("http")) {
|
|
const hash = await hashText(question.id + ":" + question.text_2);
|
|
question.audio_file_2 = hash + "";
|
|
changed = true;
|
|
}
|
|
}
|
|
|
|
return changed;
|
|
}
|
|
|
|
/**
|
|
* Normalizes all questions in a quiz config.
|
|
* @param questions - Array of questions to normalize (mutated in place)
|
|
* @returns true if any question was modified
|
|
*/
|
|
export async function normalizeQuizMedia(
|
|
questions: Array<QuizQuestion | null | undefined>,
|
|
): Promise<boolean> {
|
|
let anyChanged = false;
|
|
|
|
for (const question of questions) {
|
|
if (!question) continue;
|
|
const changed = await normalizeQuestionMedia(question);
|
|
anyChanged = anyChanged || changed;
|
|
}
|
|
|
|
return anyChanged;
|
|
}
|