Nova versao codex Parecer, atualizacao completa

This commit is contained in:
Vitex Tecnologia
2026-03-18 01:07:27 -03:00
parent 39032ea621
commit 6bf7e7d42e
49 changed files with 8003 additions and 2486 deletions
+58 -202
View File
@@ -1,9 +1,6 @@
import { GlobalFunctions, TransferAreaProperties } from '@/GlobalFunctions';
import { apiService } from './api';
/**
* Interface para a resposta da API de transcrição
*/
export interface TranscriptionResponse {
success: boolean;
transcription_id: string;
@@ -11,9 +8,6 @@ export interface TranscriptionResponse {
message: string;
}
/**
* Interface para uma transcrição armazenada no banco de dados
*/
export interface TranscriptionRecord {
id: string;
user_email: string;
@@ -27,246 +21,108 @@ export interface TranscriptionRecord {
created_at: string;
}
/**
* Interface para os dados necessários para transcrição
*/
export interface TranscriptionRequest {
audioFile: File;
userEmail?: string;
estabelecimentoId?: number;
}
/**
* Serviço de transcrição de áudio
*/
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';
/**
* Transcreve um arquivo de áudio
*
* @param request - Dados da requisição (arquivo, email, estabelecimento)
* @returns Promise com a resposta da API
*/
async transcribeAudio(request: TranscriptionRequest): Promise<TranscriptionResponse> {
const { audioFile, userEmail, estabelecimentoId } = request;
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);
// Cria FormData para envio multipart
const formData = new FormData();
formData.append('data', audioFile);
// Usa valores do .env se não forem fornecidos
const email = GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);//userEmail || import.meta.env.VITE_USER_EMAIL || '';
const estabId = GlobalFunctions.getTransferProperty(TransferAreaProperties.EstabelecimentoCodigo);//estabelecimentoId || import.meta.env.VITE_ESTABELECIMENTO_ID || '';
formData.append('user_email', email);
formData.append('estabelecimento_id', estabId.toString());
// Log para debug (remover em produção se necessário)
console.log('Enviando transcrição:', {
fileName: audioFile.name,
fileSize: audioFile.size,
fileType: audioFile.type,
userEmail: email,
estabelecimentoId: estabId,
});
try {
// Faz a requisição usando o serviço de API
const response = await apiService.postFormData<TranscriptionResponse>(
this.TRANSCRIPTION_ENDPOINT,
formData
);
return response.data;
} catch (error: any) {
// Trata erros específicos
} catch (error: unknown) {
console.error('Erro na transcrição:', error);
throw {
success: false,
message: error.message || 'Erro ao transcrever áudio',
status: error.status,
};
this.toApiError(error, 'Erro ao transcrever áudio');
}
}
/**
* Valida se o arquivo de áudio é suportado
*
* @param file - Arquivo a ser validado
* @param maxSizeMB - Tamanho máximo em MB (padrão: 25MB)
* @returns Objeto com resultado da validação
*/
validateAudioFile(file: File, maxSizeMB: number = 25): { valid: boolean; error?: string } {
const SUPPORTED_FORMATS = ['flac', 'm4a', 'mp3', 'mp4', 'mpeg', 'mpga', 'oga', 'ogg', 'wav', 'webm'];
const MAX_FILE_SIZE = maxSizeMB * 1024 * 1024;
// Valida tamanho
if (file.size > MAX_FILE_SIZE) {
return {
valid: false,
error: `Arquivo muito grande. Tamanho máximo: ${maxSizeMB}MB`,
};
}
// Valida formato
const fileExtension = file.name.split('.').pop()?.toLowerCase();
if (!fileExtension || !SUPPORTED_FORMATS.includes(fileExtension)) {
return {
valid: false,
error: `Formato não suportado. Formatos aceitos: ${SUPPORTED_FORMATS.join(', ')}`,
};
}
return { valid: true };
}
/**
* Lista transcrições do banco de dados com paginação
*
* @param userEmail - Email do usuário
* @param page - Número da página (padrão: 1)
* @param perPage - Quantidade de itens por página (padrão: 10)
* @returns Promise com o array de transcrições
*/
async getTranscriptions(
userEmail?: string,
page: number = 1,
perPage: number = 10
): Promise<TranscriptionRecord[]> {
// Usa valores do GlobalFunctions se não forem fornecidos
const email = userEmail || GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);
if (!email) {
throw {
success: false,
message: 'Email do usuário não fornecido',
};
}
console.log('Buscando transcrições:', {
userEmail: email,
page,
perPage,
});
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 {
// Faz a requisição GET com parâmetros na URL e query
const response = await apiService.get<TranscriptionRecord[]>(
const response = await apiService.get<unknown>(
`${this.GET_TRANSCRIPTIONS_ENDPOINT}/${email}`,
{
params: {
page: page.toString(),
per_page: perPage.toString(),
},
}
{ params: { page: page.toString(), per_page: perPage.toString() } }
);
console.log('Resposta completa da API:', response);
console.log('response.data:', response.data);
console.log('É array?:', Array.isArray(response.data));
// A API retorna diretamente o array de transcrições
// Garante que sempre retorna um array
if (Array.isArray(response.data)) {
return response.data;
} else if (response.data && typeof response.data === 'object') {
// Se a resposta for um objeto com uma propriedade 'transcriptions' ou similar
console.warn('API retornou objeto em vez de array:', response.data);
// Tenta encontrar o array dentro do objeto
if (Array.isArray((response.data as any).transcriptions)) {
return (response.data as any).transcriptions;
} else if (Array.isArray((response.data as any).data)) {
return (response.data as any).data;
}
}
// Se não conseguir extrair array, retorna vazio
console.warn('Não foi possível extrair array de transcrições da resposta');
return [];
} catch (error: any) {
return this.extractArray<TranscriptionRecord>(response.data, ['transcriptions', 'data']);
} catch (error: unknown) {
console.error('Erro ao buscar transcrições:', error);
throw {
success: false,
message: error.message || 'Erro ao buscar transcrições',
status: error.status,
};
this.toApiError(error, 'Erro ao buscar transcrições');
}
}
/**
* Deleta uma transcrição do banco de dados
*
* @param transcriptionId - ID da transcrição a ser deletada
* @param userEmail - Email do usuário (opcional)
* @returns Promise com sucesso ou erro
*/
async deleteTranscription(transcriptionId: string, userEmail?: string): Promise<{ success: boolean; message?: string }> {
// Usa valores do GlobalFunctions se não forem fornecidos
const email = userEmail || GlobalFunctions.getTransferProperty(TransferAreaProperties.UsuarioEmail);
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',
};
}
console.log('Deletando transcrição:', {
transcriptionId,
userEmail: email,
});
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 {
// Faz a requisição DELETE com parâmetros na URL
const response = await apiService.delete<{ success: boolean; message?: string } | Array<{ success: boolean; message?: string }>>(
`${this.DELETE_TRANSCRIPTION_ENDPOINT}/${email}/${transcriptionId}`
);
console.log('Resposta completa do DELETE:', response);
console.log('response.data:', response.data);
// A API retorna um array com um objeto: [{"success":true}]
let result: { success: boolean; message?: string };
if (Array.isArray(response.data)) {
// Se for array, pega o primeiro elemento
result = response.data[0];
console.log('API retornou array, usando primeiro elemento:', result);
} else {
// Se for objeto direto
result = response.data;
console.log('API retornou objeto direto:', result);
}
// Garante que tem a estrutura mínima
return {
success: result.success ?? true,
message: result.message || 'Transcrição deletada com sucesso',
};
} catch (error: any) {
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);
throw {
success: false,
message: error.message || 'Erro ao deletar transcrição',
status: error.status,
};
this.toApiError(error, 'Erro ao deletar transcrição');
}
}
}
// Exporta instância única (Singleton)
export const transcriptionService = new TranscriptionService();