5. Part: App Script Bot-1 Telegram Saham Turun

/**************************************************** * RESET STATUS TURUN & NAIK SETIAP PAGI (Sheet1) ****************************************************/ function resetStatus() { const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1"); const lastRow = sheet.getLastRow(); // Kolom J & K → Status Turun & Status Naik sheet.getRange(2, 10, lastRow - 1, 2).clearContent(); Logger.log("Status Turun & Status Naik telah direset."); } /**************************************************** * PASANG SEMUA TRIGGER OTOMATIS SEKALI KLIK ****************************************************/ function createTriggers() { // Hapus semua trigger lama dulu biar bersih deleteAllTriggers(); // Update harga tiap 1 menit ScriptApp.newTrigger("updateHarga") .timeBased() .everyMinutes(1) .create(); // Cek alert tiap 1 menit ScriptApp.newTrigger("checkStockAlerts") .timeBased() .everyMinutes(1) .create(); // Reset status sekali sehari jam 06:00 ScriptApp.newTrigger("resetStatus") .timeBased() .atHour(6) .everyDays(1) .create(); Logger.log("Semua trigger berhasil dipasang!"); } /**************************************************** * HAPUS SEMUA TRIGGER (AMAN) ****************************************************/ function deleteAllTriggers() { const triggers = ScriptApp.getProjectTriggers(); triggers.forEach(trigger => { ScriptApp.deleteTrigger(trigger); }); Logger.log("Semua trigger lama telah dihapus."); } /**************************************************** * RESET STATUS SETIAP PAGI ****************************************************/ function resetStatus() { const sheet = SpreadsheetApp.getActive().getSheetByName("Sheet1"); const lastRow = sheet.getLastRow(); sheet.getRange(2, 10, lastRow - 1, 2).clearContent(); Logger.log("Status Turun & Status Naik telah direset."); } /**************************************************** * TRIGGER OTOMATIS — INSTAL SEMUA SEKALI (saja) KLIK ****************************************************/ function createTriggers() { deleteAllTriggers(); ScriptApp.newTrigger("updateHarga") .timeBased() .everyMinutes(1) .create(); ScriptApp.newTrigger("checkStockAlerts") .timeBased() .everyMinutes(1) .create(); ScriptApp.newTrigger("resetStatus") .timeBased() .atHour(6) .everyDays(1) .create(); Logger.log("Semua trigger berhasil dipasang."); } /**************************************************** * HAPUS SEMUA TRIGGER - Wajib sebelum memasang trigger baru. ****************************************************/ function deleteAllTriggers() { const triggers = ScriptApp.getProjectTriggers(); triggers.forEach(t => ScriptApp.deleteTrigger(t)); Logger.log("Semua trigger lama telah dihapus."); } /**************************************************** * Skip otomatis jika hari libur (pakai Google Calendar) - BB1? scheduler.gs ⭐ Auto ON jam 08:55 ⭐ Auto OFF jam 16:15 ⭐ Hanya Senin–Jumat ****************************************************/ function autoOnOffController() { const now = new Date(); const day = now.getDay(); // 1=Senin … 5=Jumat // Skip Sabtu Minggu if (day === 0 || day === 6) { SYSTEM_STATUS = false; return; } // Cek libur nasional (opsional) if (isHariLibur()) { SYSTEM_STATUS = false; return; } const hh = now.getHours().toString().padStart(2,"0"); const mm = now.getMinutes().toString().padStart(2,"0"); const currentTime = `${hh}:${mm}`; if (currentTime === MARKET_OPEN) { SYSTEM_STATUS = true; notifyAll("📈 *Bursa Dibuka*\nSistem otomatis *ON*"); } if (currentTime === MARKET_CLOSE) { SYSTEM_STATUS = false; notifyAll("📉 *Bursa Ditutup*\nSistem otomatis *OFF*"); } } /**************************************************** * calendar.gs — Skip hari libur nasional (opsional) - BB2? ****************************************************/ function isHariLibur() { const cal = CalendarApp.getCalendarById("id.indonesian#holiday@group.v.calendar.google.com"); const now = new Date(); const events = cal.getEventsForDay(now); return events.length > 0; // ada libur } /**************************************************** * main.gs – Hemat kuota, Cache Harga, Mini Sparkline ⭐ Harga hemat kuota (tidak memanggil semua tiap menit) GoogleFinance hanya di-refresh 1 menit sekali, tetapi row yang tidak berubah tidak di-tulis ulang. ****************************************************/ function updateHarga() { if (!SYSTEM_STATUS) return; const ss = SpreadsheetApp.getActive(); const sh = ss.getSheetByName(SHEET_NAME); const tickers = sh.getRange("B2:B").getValues().flat().filter(String); tickers.forEach((kode, i) => { const row = i + 2; const formula = `=GOOGLEFINANCE("${kode}","price")`; const existing = sh.getRange(row, 3).getFormula(); if (existing !== formula) { sh.getRange(row, 3).setFormula(formula); } }); } /**************************************************** * Mini Grafik (Sparkline) tiap baris ****************************************************/ function updateSparkline() { if (!SYSTEM_STATUS) return; const ss = SpreadsheetApp.getActive(); const sh = ss.getSheetByName(SHEET_NAME); const lastCol = sh.getLastColumn(); const tickers = sh.getRange("B2:B").getValues().flat().filter(String); tickers.forEach((kode, i) => { const row = i + 2; const spark = `=SPARKLINE(F${row}:Z${row}, {"charttype","line";"color","red"})`; sh.getRange(row, lastCol).setFormula(spark); }); } /**************************************************** * checkStockAlerts() – alert naik/turun + Broadcast multi-user - AA1? ****************************************************/ function checkStockAlerts() { if (!SYSTEM_STATUS) return; const ss = SpreadsheetApp.getActive(); const sh = ss.getSheetByName(SHEET_NAME); const tickers = sh.getRange("B2:B").getValues().flat().filter(String); tickers.forEach((kode, i) => { const row = i + 2; const harga = sh.getRange(row, 3).getValue(); const alertHigh = sh.getRange(row, 4).getValue(); const alertLow = sh.getRange(row, 5).getValue(); if (harga >= alertHigh && alertHigh) { notifyAll(`🚀 *${kode} naik!* Harga: ${harga}`); } if (harga <= alertLow && alertLow) { notifyAll(`📉 *${kode} turun!* Harga: ${harga}`); } }); } /**************************************************** * telegram.gs — Multi-user Broadcast - AA2? ****************************************************/ function notifyAll(text) { TELEGRAM_USERS.forEach(id => sendTelegram(id, text)); } function sendTelegram(chatId, text) { const url = `https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage`; const payload = { chat_id: chatId, text: text, parse_mode: "Markdown" }; UrlFetchApp.fetch(url, { method: "post", contentType: "application/json", payload: JSON.stringify(payload) }); } /**************************************************** * Broadcast dengan Mini Grafik Sparkline (emoji) - AA3? Ini contoh sesuai permintaan Anda untuk grafik mini di Telegram (karena Telegram tidak bisa SPARKLINE, jadi kita buat visual ASCII/emoji). Contoh grafik naik-turun (max 10 titik): ****************************************************/ function notifySparkline(symbol, pricesArray) { // pilih 10 titik terakhir const prices = pricesArray.slice(-10); const max = Math.max(...prices); const min = Math.min(...prices); // buat grafik mini const bars = prices.map(p => { const ratio = (p - min) / (max - min + 0.0001); const height = Math.round(ratio * 7); // 7 level grafik const levels = ["▁","▂","▃","▄","▅","▆","▇","█"]; return levels[height]; }).join(""); const message = `📊 *${symbol} Mini Chart*\n` + `\`${bars}\`\n` + `High: ${max}\nLow: ${min}`; TELEGRAM_USERS.forEach(id => sendTelegram(id, message)); } /**************************************************** * sendTelegram() versi paling stabil Tinggal dipake di bawah semua fungsi di atas: ****************************************************/ function sendTelegram(chatId, text) { const url = `https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage`; const payload = { chat_id: chatId, text: text, parse_mode: "Markdown" }; UrlFetchApp.fetch(url, { method: "post", contentType: "application/json", payload: JSON.stringify(payload) }); }

Comments

Popular posts from this blog

Analisis Potensi Rebound Saham (compose view): Kode Python & colab.research.google.com

Proyek Scraping Python

Adaptasi Integrasi Fitur Vault HTML CSS JS ke Python