Berikut adalah penjelasan terperinci tentang setiap baris kode dan langkah-langkah dalam membuat Google Apps Script untuk webhook bot Telegram ini:

1. Buat Proyek Google Apps Script

  1. Buka Google Drive.
  2. Klik tombol "New" atau "Baru", pilih "More" atau "Lainnya", dan pilih "Google Apps Script".
  3. Buat proyek baru dan beri nama yang sesuai.

2. Menyiapkan Token Bot dan ID Spreadsheet

const BOT_TOKEN = '<BOT_TOKEN>';
const SHEET_ID = '<SHEET_ID>';  // Ganti dengan ID Google Sheet Anda
const TELEGRAM_MAX_MESSAGE_LENGTH = 4096;

  • BOT_TOKEN: Token bot Telegram yang diperoleh dari BotFather.
  • SHEET_ID: ID dari Google Sheet yang akan digunakan untuk menyimpan log dan data.
  • TELEGRAM_MAX_MESSAGE_LENGTH: Batas panjang pesan Telegram (4096 karakter).

3. Fungsi untuk Mengirim Pesan

function sendMessage(chatId, text, replyMarkup = null, replyToMessageId = null) {
  const url = 'https://api.telegram.org/bot' + BOT_TOKEN + '/sendMessage';
  
  const chunks = splitMessage(text, TELEGRAM_MAX_MESSAGE_LENGTH);

  chunks.forEach((chunk, index) => {
    const data = {
      chat_id: chatId,
      text: chunk
    };
    if (replyMarkup && index === 0) {
      data.reply_markup = replyMarkup;
    }
    if (replyToMessageId && index === 0) {
      data.reply_to_message_id = replyToMessageId;
    }

    const options = {
      method: 'post',
      contentType: 'application/json',
      payload: JSON.stringify(data)
    };

    UrlFetchApp.fetch(url, options);
  });
}

  • Mengirim pesan ke Telegram.
  • Membagi pesan jika panjangnya melebihi batas maksimum.

4. Fungsi untuk Mengirim Audio

function sendAudio(chatId, audioFileId, caption = null, replyMarkup = null, replyToMessageId = null) {
  const url = 'https://api.telegram.org/bot' + BOT_TOKEN + '/sendAudio';
  const data = {
    chat_id: chatId,
    audio: audioFileId
  };
  if (caption) {
    data.caption = caption;
  }
  if (replyMarkup) {
    data.reply_markup = replyMarkup;
  }
  if (replyToMessageId) {
    data.reply_to_message_id = replyToMessageId;
  }

  const options = {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify(data)
  };

  UrlFetchApp.fetch(url, options);
}

  • Mengirim audio ke Telegram dengan keterangan (caption) opsional.

5. Fungsi untuk Memecah Pesan

function splitMessage(text, maxLength) {
  const result = [];
  for (let i = 0; i < text.length; i += maxLength) {
    result.push(text.substring(i, i + maxLength));
  }
  return result;
}

  • Membagi pesan yang terlalu panjang menjadi beberapa bagian.

6. Fungsi untuk Menyimpan Log ke Google Sheets

function saveLog(chatId, message) {
  const sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName('chat_quranbot');
  sheet.appendRow([new Date(), chatId, message]);
}

function saveErrorLog(chatId, error) {
  const sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName('error_log');
  sheet.appendRow([new Date(), chatId, error.toString()]);
}

  • Menyimpan log chat dan error ke Google Sheets.

7. Fungsi untuk Menangani Perintah

function handleCommand(update) {
  const message = update.message;
  const chatId = message.chat.id;
  const text = message.text.toLowerCase();  // Mengonversi teks menjadi huruf kecil
  const messageId = message.message_id;

  try {
    saveLog(chatId, text);

    if (text === '/start') {
      const replyMarkup = JSON.stringify({
        keyboard: [
          ['listquran'],
          ['audio 1'],
          ['surah 1']
        ],
        resize_keyboard: true
      });
      sendMessage(chatId, 'Silakan pilih opsi di bawah ini:', replyMarkup, messageId);
    }    
    else if (text.startsWith('surah')) {  
      var surahNumber = parseInt(text.split(' ')[1]);
      var quranSheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName('ayatQuran');
      var ayatNumbers = quranSheet.getRange('A2:A7875').getValues().flat();
      var ayatTexts = quranSheet.getRange('B2:B7875').getValues().flat();
      var ayatTranslations = quranSheet.getRange('C2:C7875').getValues().flat();
      var ayatArabicTexts = quranSheet.getRange('D2:D7875').getValues().flat();
      var ayatDetails = quranSheet.getRange('E2:E7875').getValues().flat();
      var indices = [];
      for (var i = 0; i < ayatNumbers.length; i++) {
        if (ayatNumbers[i] === surahNumber) {
          indices.push(i);
        }
      }

      var quranSheet1 = SpreadsheetApp.openById(SHEET_ID).getSheetByName('SurahQuran');
      var surahNumbers = quranSheet1.getRange('A2:A115').getValues().flat();
      var surahNames = quranSheet1.getRange('C2:C115').getValues().flat();
      var surahTranslations = quranSheet1.getRange('M2:M115').getValues().flat();
      var surahArabicNames = quranSheet1.getRange('D2:D115').getValues().flat();
      var surahDetails = quranSheet1.getRange('K2:K115').getValues().flat();
      var index = surahNumbers.indexOf(surahNumber);

      if (indices.length === 0) {
        sendMessage(chatId, 'Ayat dengan nomor surah tersebut tidak ditemukan.', null, messageId);
      } else {
        var ayatDetailsList = indices.map(function(index) {
          return ayatNumbers[index] + ". " + ayatTexts[index] + " : " + ayatArabicTexts[index] + " : " + ayatTranslations[index] + "\n" + ayatDetails[index];
        });
        var allAyatDetails = ayatDetailsList.join('\n\n');
        var surahDetail = surahNumbers[index] + ". " + surahNames[index] + " : " + surahArabicNames[index] + " : " + surahTranslations[index];
        sendMessage(chatId, surahDetail, null, messageId);   
        sendMessage(chatId, allAyatDetails, null, messageId);
      }
    }
    else if (text.startsWith('audio')) {
      var surahNumber = parseInt(text.split(' ')[1]);
      var quranSheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName('SurahQuran');
      var surahNumbers = quranSheet.getRange('A2:A115').getValues().flat();
      var surahAudioLinks = quranSheet.getRange('N2:N115').getValues().flat();
      var surahNames = quranSheet.getRange('C2:C115').getValues().flat();
      var surahTranslations = quranSheet.getRange('M2:M115').getValues().flat();
      var surahArabicNames = quranSheet.getRange('D2:D115').getValues().flat();
      var surahDetails = quranSheet.getRange('K2:K115').getValues().flat();
      var index = surahNumbers.indexOf(surahNumber);

      if (index === -1) {
        sendMessage(chatId, 'Surah dengan nomor tersebut tidak ditemukan.', null, messageId);
      } else {
        var surahDetail = surahNumbers[index] + ". " + surahNames[index] + " : " + surahArabicNames[index] + " : " + surahTranslations[index];
        sendAudio(chatId, surahAudioLinks[index], surahDetail, null, messageId); 
      }
    }
    else if (text === 'listquran') {
      try {
        var quranSheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName('SurahQuran');
        if (!quranSheet) {
          throw new Error('Sheet "SurahQuran" tidak ditemukan');
        }
        
        var surahNumbers = quranSheet.getRange('A2:A115').getValues().flat();
        var surahNames = quranSheet.getRange('C2:C115').getValues().flat();
        var surahArabicNames = quranSheet.getRange('D2:D115').getValues().flat();
        var surahTranslations = quranSheet.getRange('M2:M115').getValues().flat();
        
        var surahList = "Quran 114 Surah:\n";
        for (var i = 0; i < surahNumbers.length; i++) {
          surahList += (i + 1) + ". " + surahNames[i] + " : " + surahTranslations[i] + " : " + surahArabicNames[i] + "\n";
        }
        
        sendMessage(chatId, surahList, null, messageId);
      } catch (error) {
        saveErrorLog(chatId, error);
        sendMessage(chatId, 'Maaf, terjadi kesalahan saat memproses permintaan Anda. Tim kami akan segera memperbaikinya.', null, messageId);
      }
    }   
  } catch (error) {
    saveErrorLog(chatId, error);
    sendMessage(chatId, 'Maaf, terjadi kesalahan saat memproses permintaan Anda. Tim kami akan segera memperbaikinya.', null, messageId);
  }
}

  • Menangani berbagai perintah dari pengguna.
  • Logika untuk perintah /start, surah, audio, dan listquran.

8. Fungsi Utama untuk Menangani Webhook

function doPost(e) {
  const update = JSON.parse(e.postData.contents);
  if (update) {
    handleCommand(update);
  }

  const sheet = SpreadsheetApp.openById(SHEET_ID).getSheetByName('telegram_log');
  sheet.appendRow([new Date(), JSON.stringify(update)]);
}

  • Fungsi ini akan dipanggil saat webhook menerima data dari Telegram.
  • Menangani update dan menyimpan log ke Google Sheets.

9. Mengatur Webhook

  • Publikasikan proyek sebagai aplikasi web (Deploy > New Deployment > Select "Web app").
  • Pastikan Anda mengatur izin untuk "Anyone" atau "Anyone, even anonymous".
  • Salin URL Web App dan gunakan untuk mengatur webhook bot Telegram dengan perintah berikut:
https://api.telegram.org/bot<BOT_TOKEN>/setWebhook?url=<URL_WEB_APP>

Gantilah <BOT_TOKEN> dengan token bot Anda dan <URL_WEB_APP> dengan URL Web App dari Google Apps Script.

10. Menambahkan Spreadsheet

  • Buat Google Sheet dengan ID yang Anda masukkan di variabel SHEET_ID.
  • Buat sheet di dalam Google Sheet dengan nama chat_quranbot, error_log, telegram_log, SurahQuran, dan ayatQuran.

Sekarang, bot Telegram Anda sudah siap dan akan merespons perintah yang diterima melalui webhook.