129 lines
4.9 KiB
TypeScript
129 lines
4.9 KiB
TypeScript
import { GlobalFunctions, TransferAreaProperties } from '@/GlobalFunctions';
|
|
import { apiService } from './api';
|
|
|
|
export interface TranscriptionResponse {
|
|
success: boolean;
|
|
transcription_id: string;
|
|
audio_url: string;
|
|
message: string;
|
|
}
|
|
|
|
export interface TranscriptionRecord {
|
|
id: string;
|
|
user_email: string;
|
|
estabelecimento_id: number;
|
|
audio_file_name: string;
|
|
audio_duration_seconds: number;
|
|
transcription_text: string;
|
|
model: string;
|
|
audio_url: string;
|
|
cost_usd: string;
|
|
created_at: string;
|
|
}
|
|
|
|
export interface TranscriptionRequest {
|
|
audioFile: File;
|
|
userEmail?: string;
|
|
estabelecimentoId?: number;
|
|
}
|
|
|
|
type ApiErrorShape = { message?: string; status?: number };
|
|
|
|
class TranscriptionService {
|
|
private readonly TRANSCRIPTION_ENDPOINT = '/webhook/codex/transcrever_audio';
|
|
private readonly GET_TRANSCRIPTIONS_ENDPOINT = '/webhook/fd073ec0-81ab-4681-8acd-b0da71f6ad30/codex/get_transcrever_audio';
|
|
private readonly DELETE_TRANSCRIPTION_ENDPOINT = '/webhook/fd073ec0-81ab-4681-8acd-b0da71f6ad30/codex/delete_transcrever_audio';
|
|
|
|
private readonly SUPPORTED_FORMATS = ['flac', 'm4a', 'mp3', 'mp4', 'mpeg', 'mpga', 'oga', 'ogg', 'wav', 'webm'];
|
|
|
|
private resolveEmail(userEmail?: string): string {
|
|
return userEmail || GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);
|
|
}
|
|
|
|
private toApiError(error: unknown, fallback: string): never {
|
|
const e = error as ApiErrorShape;
|
|
throw { success: false, message: e?.message || fallback, status: e?.status };
|
|
}
|
|
|
|
private extractArray<T>(data: unknown, keys: string[]): T[] {
|
|
if (Array.isArray(data)) return data as T[];
|
|
if (data && typeof data === 'object') {
|
|
for (const key of keys) {
|
|
const candidate = (data as Record<string, unknown>)[key];
|
|
if (Array.isArray(candidate)) return candidate as T[];
|
|
}
|
|
}
|
|
return [];
|
|
}
|
|
|
|
validateAudioFile(file: File, maxSizeMB = 25): { valid: boolean; error?: string } {
|
|
const maxBytes = maxSizeMB * 1024 * 1024;
|
|
if (file.size > maxBytes) {
|
|
return { valid: false, error: `Arquivo muito grande. Tamanho máximo: ${maxSizeMB}MB` };
|
|
}
|
|
const ext = file.name.split('.').pop()?.toLowerCase();
|
|
if (!ext || !this.SUPPORTED_FORMATS.includes(ext)) {
|
|
return { valid: false, error: `Formato não suportado. Formatos aceitos: ${this.SUPPORTED_FORMATS.join(', ')}` };
|
|
}
|
|
return { valid: true };
|
|
}
|
|
|
|
async transcribeAudio(request: TranscriptionRequest): Promise<TranscriptionResponse> {
|
|
const { audioFile } = request;
|
|
|
|
const email = GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);
|
|
const estabId = GlobalFunctions.getTransferProperty(TransferAreaProperties.EstabelecimentoCodigo);
|
|
|
|
const formData = new FormData();
|
|
formData.append('data', audioFile);
|
|
formData.append('user_email', email);
|
|
formData.append('estabelecimento_id', estabId.toString());
|
|
|
|
try {
|
|
const response = await apiService.postFormData<TranscriptionResponse>(
|
|
this.TRANSCRIPTION_ENDPOINT,
|
|
formData
|
|
);
|
|
return response.data;
|
|
} catch (error: unknown) {
|
|
console.error('Erro na transcrição:', error);
|
|
this.toApiError(error, 'Erro ao transcrever áudio');
|
|
}
|
|
}
|
|
|
|
async getTranscriptions(userEmail?: string, page = 1, perPage = 10): Promise<TranscriptionRecord[]> {
|
|
const email = this.resolveEmail(userEmail);
|
|
if (!email) throw { success: false, message: 'Email do usuário não fornecido' };
|
|
|
|
try {
|
|
const response = await apiService.get<unknown>(
|
|
`${this.GET_TRANSCRIPTIONS_ENDPOINT}/${email}`,
|
|
{ params: { page: page.toString(), per_page: perPage.toString() } }
|
|
);
|
|
return this.extractArray<TranscriptionRecord>(response.data, ['transcriptions', 'data']);
|
|
} catch (error: unknown) {
|
|
console.error('Erro ao buscar transcrições:', error);
|
|
this.toApiError(error, 'Erro ao buscar transcrições');
|
|
}
|
|
}
|
|
|
|
async deleteTranscription(transcriptionId: string, userEmail?: string): Promise<{ success: boolean; message?: string }> {
|
|
const email = this.resolveEmail(userEmail);
|
|
if (!email) throw { success: false, message: 'Email do usuário não fornecido' };
|
|
if (!transcriptionId) throw { success: false, message: 'ID da transcrição não fornecido' };
|
|
|
|
try {
|
|
const response = await apiService.delete<{ success: boolean; message?: string } | Array<{ success: boolean; message?: string }>>(
|
|
`${this.DELETE_TRANSCRIPTION_ENDPOINT}/${email}/${transcriptionId}`
|
|
);
|
|
const result = Array.isArray(response.data) ? response.data[0] : response.data;
|
|
return { success: result.success ?? true, message: result.message || 'Transcrição deletada com sucesso' };
|
|
} catch (error: unknown) {
|
|
console.error('Erro ao deletar transcrição:', error);
|
|
this.toApiError(error, 'Erro ao deletar transcrição');
|
|
}
|
|
}
|
|
}
|
|
|
|
export const transcriptionService = new TranscriptionService();
|