Compare commits
2 Commits
test
...
4372bcd160
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4372bcd160 | ||
|
|
da8b69577e |
164
test.txt
164
test.txt
@@ -1,164 +0,0 @@
|
||||
import { IExpenseRequest, IExpenseResponse } from "../types";
|
||||
import { API_BASE_URL, EXPENSE_WEBHOOK_ENDPOINT } from "../utils/constants";
|
||||
import * as FileSystem from "expo-file-system";
|
||||
|
||||
export class ExpenseService {
|
||||
private static readonly API_URL = `${API_BASE_URL}${EXPENSE_WEBHOOK_ENDPOINT}`;
|
||||
|
||||
static async sendExpenseData(
|
||||
data: IExpenseRequest
|
||||
): Promise<IExpenseResponse> {
|
||||
try {
|
||||
const response = await fetch(this.API_URL, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error("Error sending expense data:", error);
|
||||
throw new Error(
|
||||
error instanceof Error ? error.message : "Có lỗi xảy ra khi gửi dữ liệu"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static async sendAudioExpense(audioUri: string): Promise<IExpenseResponse> {
|
||||
try {
|
||||
// Send audio file as multipart/form-data for n8n workflow
|
||||
return await this.sendAudioToN8N(audioUri);
|
||||
} catch (error) {
|
||||
console.error("Error sending audio expense:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
static async sendTextExpense(text: string): Promise<IExpenseResponse> {
|
||||
try {
|
||||
const requestData: IExpenseRequest = {
|
||||
textInput: text,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
|
||||
return await this.sendExpenseData(requestData);
|
||||
} catch (error) {
|
||||
console.error("Error sending text expense:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private static async sendAudioToN8N(
|
||||
audioUri: string
|
||||
): Promise<IExpenseResponse> {
|
||||
try {
|
||||
const formData = new FormData();
|
||||
|
||||
// Get file info
|
||||
const fileInfo = await FileSystem.getInfoAsync(audioUri);
|
||||
if (!fileInfo.exists) {
|
||||
throw new Error("File audio không tồn tại");
|
||||
}
|
||||
|
||||
console.log("File info:", fileInfo);
|
||||
console.log("Audio URI:", audioUri);
|
||||
|
||||
// Extract file name and extension
|
||||
const fileName =
|
||||
audioUri.split("/").pop() || `recording_${Date.now()}.m4a`;
|
||||
const fileExtension = fileName.split(".").pop() || "m4a";
|
||||
const mimeType = "audio/x-m4a";
|
||||
const fileSizeBytes = fileInfo.size || 0;
|
||||
const fileSizeMB = (fileSizeBytes / (1024 * 1024)).toFixed(2);
|
||||
|
||||
// Try different approaches for React Native file upload
|
||||
let audioFile: any;
|
||||
|
||||
if (audioUri.startsWith("file://")) {
|
||||
// For local files, create proper file object
|
||||
audioFile = {
|
||||
uri: audioUri,
|
||||
type: mimeType,
|
||||
name: fileName,
|
||||
};
|
||||
} else {
|
||||
// Fallback: read as base64 and convert
|
||||
const base64Data = await FileSystem.readAsStringAsync(audioUri, {
|
||||
encoding: FileSystem.EncodingType.Base64,
|
||||
});
|
||||
|
||||
audioFile = {
|
||||
uri: `data:${mimeType};base64,${base64Data}`,
|
||||
type: mimeType,
|
||||
name: fileName,
|
||||
};
|
||||
}
|
||||
|
||||
// Append audio file to form data (n8n sẽ nhận như binary data)
|
||||
formData.append("audioFile", audioFile as any);
|
||||
|
||||
// Append metadata as separate fields
|
||||
formData.append("timestamp", new Date().toISOString());
|
||||
formData.append("fileName", fileName);
|
||||
formData.append("fileExtension", fileExtension);
|
||||
formData.append("mimeType", mimeType);
|
||||
formData.append("fileSizeBytes", fileSizeBytes.toString());
|
||||
formData.append("fileSizeMB", `${fileSizeMB} MB`);
|
||||
|
||||
console.log("File metadata:", {
|
||||
fileName,
|
||||
fileExtension,
|
||||
mimeType,
|
||||
fileSizeBytes,
|
||||
fileSizeMB: `${fileSizeMB} MB`,
|
||||
});
|
||||
|
||||
console.log("Sending FormData to:", this.API_URL);
|
||||
|
||||
const response = await fetch(this.API_URL, {
|
||||
method: "POST",
|
||||
// Không set Content-Type header - fetch sẽ tự động set với boundary
|
||||
body: formData,
|
||||
});
|
||||
|
||||
console.log("Response status:", response.status);
|
||||
console.log("Response headers:", response.headers);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error("Error response:", errorText);
|
||||
throw new Error(
|
||||
`HTTP error! status: ${response.status}, message: ${errorText}`
|
||||
);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error("Error sending audio to n8n:", error);
|
||||
throw new Error(
|
||||
error instanceof Error ? error.message : "Có lỗi xảy ra khi gửi audio"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static async convertAudioToBase64(audioUri: string): Promise<string> {
|
||||
try {
|
||||
const base64 = await FileSystem.readAsStringAsync(audioUri, {
|
||||
encoding: FileSystem.EncodingType.Base64,
|
||||
});
|
||||
return base64;
|
||||
} catch (error) {
|
||||
console.error("Error converting audio to base64:", error);
|
||||
throw new Error("Không thể chuyển đổi file audio");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user