Membuat API cuaca sendiri tanpa perlu hosting khusus atau infrastruktur kompleks
Dalam dunia pengembangan aplikasi modern, data cuaca merupakan salah satu informasi yang sering dibutuhkan. Banyak aplikasi memerlukan informasi cuaca, mulai dari aplikasi pertanian, transportasi, hingga aplikasi kesehatan dan olahraga.
Namun, sebagian besar layanan API cuaca komersial memiliki batasan penggunaan atau biaya yang cukup tinggi untuk penggunaan skala besar. Bagaimana jika kita bisa membuat layanan API cuaca sendiri yang gratis, mudah di-deploy, dan dilengkapi dengan sistem logging yang komprehensif?
Dalam artikel ini, saya akan membahas cara membuat layanan API cuaca menggunakan Google Apps Script yang memanfaatkan data dari wttr.in, dilengkapi dengan sistem pencatatan log dan notifikasi Telegram.
wttr.in adalah layanan cuaca berbasis konsol yang dikembangkan oleh Igor Chubin. Layanan ini menyajikan informasi cuaca dalam format text-based yang mudah dibaca dan kompatibel dengan terminal. Yang menarik, wttr.in juga menyediakan format JSON yang bisa diakses dengan menambahkan parameter ?format=j1
.
Google Apps Script adalah platform pengembangan yang dibangun di atas infrastruktur Google Cloud. Dengan Google Apps Script, kita bisa membuat aplikasi web tanpa perlu mengkhawatirkan hosting, domain, atau infrastruktur backend kompleks lainnya. Kelebihan utamanya adalah:
Kita akan membuat sebuah API yang:
Pertama, kita perlu menyiapkan konfigurasi dasar untuk layanan kita:
// KONFIGURASI
var CONFIG = {
SPREADSHEET_ID: "YOUR_SPREADSHEET_ID",
LOG_SHEET_NAME: "logAPI",
TELEGRAM_BOT_TOKEN: "YOUR_BOT_TOKEN",
TELEGRAM_CHAT_ID: "YOUR_CHAT_ID"
};
Ganti nilai-nilai di atas dengan:
SPREADSHEET_ID
: ID Google Spreadsheet untuk menyimpan logLOG_SHEET_NAME
: Nama sheet untuk log (default: "logAPI")TELEGRAM_BOT_TOKEN
: Token bot Telegram (buat melalui BotFather)TELEGRAM_CHAT_ID
: ID chat di mana notifikasi akan dikirimSelanjutnya, kita membuat fungsi doGet()
yang menangani semua request HTTP GET:
function doGet(e) {
var startTime = new Date();
var userIP = getIpAddress();
// Jika tidak ada parameter, tampilkan dokumentasi API
if (!e.parameter.loc) {
logAccess(startTime, new Date(), userIP, "/", "DOCS", "Success", 200, "Menampilkan dokumentasi API");
return serveApiDocs();
}
try {
// Ambil parameter lokasi
var location = e.parameter.loc;
// URL untuk wttr.in dengan format plain
var url = "https://wttr.in/" + location + "?format=j1";
// Lakukan request ke wttr.in
var response = UrlFetchApp.fetch(url);
var jsonData = JSON.parse(response.getContentText());
// Ekstrak data cuaca yang relevan
var weatherData = processWeatherData(jsonData, "", location);
// Log akses sukses
logAccess(startTime, new Date(), userIP, "/loc=" + location, "GET", "Success", 200, "Data cuaca berhasil diambil");
// Kembalikan data dalam format JSON
return ContentService.createTextOutput(JSON.stringify(weatherData))
.setMimeType(ContentService.MimeType.JSON);
} catch (error) {
// Log akses gagal
logAccess(startTime, new Date(), userIP, "/loc=" + location, "GET", "Error", 500, error.toString());
// Handling error
return ContentService.createTextOutput(JSON.stringify({
error: true,
message: "Error: " + error.toString()
})).setMimeType(ContentService.MimeType.JSON);
}
}
Kita perlu mengolah data dari wttr.in untuk mendapatkan format yang lebih terstruktur:
function processWeatherData(jsonData, htmlContent, location) {
// Ambil data saat ini
var current = jsonData.current_condition[0];
// Ambil ramalan 3 hari
var forecast = jsonData.weather.map(function(day) {
return {
date: day.date,
astronomy: day.astronomy[0],
maxTempC: day.maxtempC,
minTempC: day.mintempC,
hourly: day.hourly.map(function(hour) {
return {
time: hour.time,
tempC: hour.tempC,
weatherDesc: hour.weatherDesc[0].value,
precipMM: hour.precipMM,
humidity: hour.humidity,
windspeedKmph: hour.windspeedKmph,
winddir16Point: hour.winddir16Point
};
})
};
});
// Ekstrak informasi lokasi
var locationInfo = {
coordinates: location,
name: jsonData.nearest_area ? jsonData.nearest_area[0].areaName[0].value : "Unknown",
region: jsonData.nearest_area ? jsonData.nearest_area[0].region[0].value : "Unknown",
country: jsonData.nearest_area ? jsonData.nearest_area[0].country[0].value : "Unknown"
};
// Menggabungkan semua informasi
return {
location: locationInfo,
current: {
tempC: current.temp_C,
weatherDesc: current.weatherDesc[0].value,
windspeedKmph: current.windspeedKmph,
humidity: current.humidity,
precipMM: current.precipMM,
visibility: current.visibility,
pressure: current.pressure,
cloudcover: current.cloudcover,
feelsLikeC: current.FeelsLikeC,
uvIndex: current.uvIndex
},
forecast: forecast,
timestamp: new Date().toISOString(),
source: "wttr.in"
};
}
Sistem logging dan notifikasi adalah fitur penting dari API kita:
function logAccess(startTime, endTime, ip, endpoint, method, status, statusCode, message) {
try {
// Log ke spreadsheet
logToSpreadsheet(startTime, endTime, ip, endpoint, method, status, statusCode, message);
// Kirim notifikasi Telegram untuk error atau aktivitas penting
if (status === "Error" || endpoint.includes("new") || statusCode >= 400) {
sendTelegramNotification(startTime, ip, endpoint, method, status, statusCode, message);
}
} catch (error) {
console.error("Gagal mencatat log: " + error.toString());
}
}
function logToSpreadsheet(startTime, endTime, ip, endpoint, method, status, statusCode, message) {
try {
var ss = SpreadsheetApp.openById(CONFIG.SPREADSHEET_ID);
var sheet = ss.getSheetByName(CONFIG.LOG_SHEET_NAME);
// Buat sheet jika belum ada
if (!sheet) {
sheet = ss.insertSheet(CONFIG.LOG_SHEET_NAME);
sheet.appendRow([
"Timestamp",
"Durasi (ms)",
"IP",
"Endpoint",
"Method",
"Status",
"Status Code",
"Message"
]);
}
// Hitung durasi dalam milidetik
var duration = endTime.getTime() - startTime.getTime();
// Tambahkan log baru
sheet.appendRow([
new Date(),
duration,
ip,
endpoint,
method,
status,
statusCode,
message
]);
} catch (error) {
console.error("Gagal mencatat log ke spreadsheet: " + error.toString());
}
}
function sendTelegramNotification(startTime, ip, endpoint, method, status, statusCode, message) {
try {
var telegramApiUrl = "https://api.telegram.org/bot" + CONFIG.TELEGRAM_BOT_TOKEN + "/sendMessage";
// Format pesan
var formattedDate = Utilities.formatDate(startTime, "Asia/Jakarta", "dd-MM-yyyy HH:mm:ss");
var telegramMessage =
" *Weather API Alert*\n" +
" *Time:* " + formattedDate + "\n" +
" *IP:* " + ip + "\n" +
" *Endpoint:* " + endpoint + "\n" +
" *Method:* " + method + "\n" +
" *Status:* " + status + " (" + statusCode + ")\n" +
" *Message:* " + message;
// Kirim pesan ke Telegram
var payload = {
"chat_id": CONFIG.TELEGRAM_CHAT_ID,
"text": telegramMessage,
"parse_mode": "Markdown"
};
var options = {
"method": "post",
"contentType": "application/json",
"payload": JSON.stringify(payload)
};
UrlFetchApp.fetch(telegramApiUrl, options);
} catch (error) {
console.error("Gagal mengirim notifikasi Telegram: " + error.toString());
}
}
Untuk melengkapi log, kita perlu mendapatkan alamat IP:
function getIpAddress() {
var url = 'https://api.ipify.org';
var options = {
'method': 'GET',
'muteHttpExceptions': true
};
try {
var response = UrlFetchApp.fetch(url, options);
if (response.getResponseCode() === 200) {
return response.getContentText();
} else {
console.error('Error fetching IP address. Response code:', response.getResponseCode());
return 'Unknown';
}
} catch (e) {
console.error('Error fetching IP address:', e);
return 'Unknown';
}
}
Terakhir, kita perlu membuat dokumentasi yang informatif namun sederhana:
function serveApiDocs() {
var apiName = "Weather API Grabber";
var version = "v1.0";
var lastUpdate = new Date().toISOString().split('T')[0];
var html = `
<!DOCTYPE html>
<html>
<head>
<title>${apiName}</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
margin: 0;
padding: 20px;
color: #333;
background-color: #f9f9f9;
}
.container {
max-width: 700px;
margin: 0 auto;
background-color: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
color: #2c3e50;
margin-top: 0;
}
code {
background-color: #f0f0f0;
padding: 2px 6px;
border-radius: 3px;
font-family: monospace;
}
.example {
background-color: #f0f8ff;
padding: 15px;
border-radius: 5px;
margin: 15px 0;
border-left: 4px solid #3498db;
}
.endpoint {
font-weight: bold;
color: #2980b9;
}
</style>
</head>
<body>
<div class="container">
<h1>${apiName}</h1>
<p>Versi: ${version} | Terakhir Diperbarui: ${lastUpdate}</p>
<h2>Cara Penggunaan:</h2>
<p>Tambahkan parameter <code>loc</code> dengan nilai koordinat lokasi (latitude,longitude).</p>
<div class="example">
<p><span class="endpoint">GET</span> <code>${ScriptApp.getService().getUrl()}?loc=-7.8603934,112.0381211</code></p>
</div>
<h2>Contoh Respons:</h2>
<div class="example">
<code>
{<br>
"location": {<br>
"coordinates": "-7.8603934,112.0381211",<br>
"name": "Kediri"<br>
},<br>
"current": {<br>
"tempC": "24",<br>
"weatherDesc": "Cerah"<br>
},<br>
"forecast": [ ... ],<br>
"timestamp": "2025-04-04T08:30:45.123Z"<br>
}
</code>
</div>
<p><strong>Catatan:</strong> Data cuaca disediakan oleh wttr.in. Gunakan API ini dengan bijak.</p>
<footer style="margin-top: 30px; font-size: 12px; color: #777; text-align: center;">
<p>© ${new Date().getFullYear()} Weather API Grabber</p>
</footer>
</div>
</body>
</html>
`;
return HtmlService.createHtmlOutput(html);
}
Setelah semua kode ditulis, kita perlu men-deploy API kita:
Setelah di-deploy, API kita siap digunakan. Berikut cara mengaksesnya:
Melihat Dokumentasi
https://script.google.com/macros/s/YOUR_DEPLOYMENT_ID/exec
Mendapatkan Data Cuaca
https://script.google.com/macros/s/YOUR_DEPLOYMENT_ID/exec?loc=-7.8603934,112.0381211
Semua akses ke API akan dicatat dalam spreadsheet yang telah ditentukan. Untuk akses yang menghasilkan error atau aktivitas penting lainnya, notifikasi akan dikirim ke Telegram.
Dengan memanfaatkan Google Apps Script dan data dari wttr.in, kita telah berhasil membuat layanan API cuaca yang fungsional, mudah dipelihara, dan dilengkapi dengan fitur monitoring yang komprehensif.
API ini sangat berguna untuk:
API ini masih bisa dikembangkan lebih lanjut dengan menambahkan fitur-fitur seperti:
Mari eksplor kemungkinan ini di artikel selanjutnya!
Apakah artikel ini bermanfaat bagi Anda? Bagikan pengalaman atau pertanyaan Anda di kolom komentar di bawah. Jangan lupa untuk melihat kode lengkapnya di GitHub.
Tentang Penulis
Andri Wiratmono adalah seorang developer dan content creator yang berfokus pada teknologi web dan pengembangan API. Temukan lebih banyak tutorial dan proyek di GitHub