Code Gs 11
Code Gs 11
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index')
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL)
.addMetaTag('viewport', 'width=device-width, initial-scale=1');
}
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName("Data") || ss.insertSheet("Data");
// 2. Handle Timestamp
const timestamp = getValidTimestamp(data.timestamp);
const timestampStr = Utilities.formatDate(timestamp,
Session.getScriptTimeZone(), "yyyy-MM-dd HH:mm:ss");
const fileTimestamp = Utilities.formatDate(timestamp,
Session.getScriptTimeZone(), "yyyyMMdd_HHmmss");
// 5. Simpan ke Spreadsheet
if (sheet.getLastRow() === 0) {
sheet.appendRow([
"Timestamp", "Link Teks", "Link Foto", "Link Video", "Link Audio",
"Link Data Lokasi", "Link Google Maps", "Latitude", "Longitude",
"Akurasi (m)", "Teks di Foto", "Durasi Rekaman", "Perangkat", "Folder
Drive"
]);
}
sheet.appendRow([
timestampStr,
savedFiles.text.url || "-",
savedFiles.photo.url || "-",
savedFiles.video.url || "-",
savedFiles.audio.url || "-",
savedFiles.location.jsonUrl || "-",
savedFiles.location.mapUrl || "-",
locationInfo.lat || "-",
locationInfo.lng || "-",
locationInfo.accuracy || "-",
data.photoText || "-",
data.recordingDuration || "-",
JSON.stringify(data.deviceInfo || {}),
todayFolder.getUrl()
]);
return {
status: "success",
message: "✅ Data berhasil disimpan!",
links: {
spreadsheet: ss.getUrl(),
driveFolder: todayFolder.getUrl(),
...savedFiles
}
};
} catch (error) {
console.error("Error in processFormData:", error);
return {
status: "error",
message: "❌ Gagal menyimpan data: " + error.message
};
}
}
// =========================================
// FUNGSI BANTU UTAMA
// =========================================
return folders.hasNext()
? folders.next()
: (parentFolderId
? DriveApp.getFolderById(parentFolderId).createFolder(folderName)
: DriveApp.createFolder(folderName));
} catch (error) {
throw new Error(`Gagal membuat folder ${folderName}: ${error.message}`);
}
}
function getValidTimestamp(timestamp) {
try {
if (!timestamp) return new Date();
if (timestamp instanceof Date) return isNaN(timestamp.getTime()) ? new Date() :
timestamp;
try {
const lat = parseFloat(locationData.lat);
const lng = parseFloat(locationData.lng);
const accuracy = parseInt(locationData.accuracy);
return {
lat: isNaN(lat) ? null : lat,
lng: isNaN(lng) ? null : lng,
accuracy: isNaN(accuracy) ? null : accuracy,
timestamp: getValidTimestamp(locationData.timestamp).toISOString(),
mapUrl: (!isNaN(lat) && !isNaN(lng))
? `https://www.google.com/maps?q=${lat},${lng}`
: null
};
} catch (error) {
console.error("Error processing location data:", error);
return {
lat: null,
lng: null,
accuracy: null,
timestamp: fallbackTimestamp.toISOString(),
mapUrl: null
};
}
}
try {
const fileName = `teks_${timestamp}.txt`;
const file = folder.createFile(fileName, text, MimeType.PLAIN_TEXT);
return { url: file.getUrl() };
} catch (error) {
console.error("Error saving text:", error);
return { url: null };
}
}
try {
const base64Content = base64Data.split(",")[1] || base64Data;
const extension = mimeType === "image/jpeg" ? ".jpg" : ".webm";
const fileName = `${type}_${timestamp}${extension}`;
try {
const jsonContent = {
latitude: locationInfo.lat,
longitude: locationInfo.lng,
accuracy: locationInfo.accuracy,
timestamp: locationInfo.timestamp,
mapUrl: locationInfo.mapUrl
};
return {
jsonUrl: jsonFile.getUrl(),
mapUrl: locationInfo.mapUrl
};
} catch (error) {
console.error("Error saving location:", error);
return { jsonUrl: null, mapUrl: null };
}
}
// =========================================
// FUNGSI QR CODE (VERSI DISATUKAN)
// =========================================
function saveQRCodeData(qrData) {
try {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName("QR Codes") || ss.insertSheet("QR Codes");
return {
status: "success",
message: `QR Code (${dataType}) berhasil disimpan!`
};
} catch (error) {
console.error("Error saveQRCodeData:", error);
return {
status: "error",
message: `Gagal menyimpan QR: ${error.message}`
};
}
}
function classifyQRData(content) {
if (!content) return "EMPTY";
const patterns = {
URL: /^(http|https):\/\//,
EMAIL: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
PHONE: /^\+?[\d\s\-()]{8,}$/,
NUMERIC: /^\d{6,}$/,
WIFI: /^WIFI:/i
};