Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Pendahuluan

Selamat datang di seri belajar bot Telegram lintas bahasa, sebuah perjalanan terstruktur namun santai untuk siapa saja yang ingin memadukan kreativitas dan teknologi.

Semua materi, tutorial dan buku di sini ditujukan bagi pembaca yang baru mulai maupun yang telah bertahun-tahun berkarya; fokusnya menguraikan konsep secara bertahap, memadukan praktik langsung, dan menghadirkan konteks nyata agar setiap episode terasa relevan.

Sharing is Caring

Meskipun kami bukan ahli dalam segala hal, semangat kami untuk berbagi dan membantu yang melatarbelakangi kami di sini.

Membuka Jendela Otomatisasi dengan Telegram

Ilmu itu tak mengenal satu pintu, melainkan banyak jendela

Kutipan di atas secara sempurna menangkap esensi dari dunia teknologi yang terus berkembang, termasuk dalam bidang otomasi. Jika kita ibaratkan otomasi sebagai sebuah ruangan besar yang penuh dengan solusi canggih, maka Telegram adalah salah satu jendela terluas untuk masuk dan menjelajahinya. Ia bukan sekadar aplikasi pengirim pesan, melainkan sebuah platform matang yang menawarkan ekosistem kaya untuk inovasi.

Dokumentasi ini hadir sebagai panduan untuk membuka berbagai “jendela” tersebut, menunjukkan betapa fleksibel dan kuatnya Telegram sebagai jembatan antara ide dan eksekusi otomasi.

Mengapa Telegram? Perspektif Akademis dan Praktis

Dari sudut pandang rekayasa perangkat lunak dan sistem informasi, pemilihan Telegram sebagai medium otomasi didasari oleh beberapa keunggulan fundamental:

  1. Aksesibilitas Universal dan Antarmuka yang Familiar: Telegram bersifat lintas platform (tersedia di mobile, desktop, dan web). Ini menjadikannya antarmuka pengguna (user interface) yang universal dan tidak memerlukan kurva belajar yang curam. Konsep ini, dalam studi Interaksi Manusia-Komputer (HCI), sangat penting untuk memastikan adopsi teknologi. Pengguna akhir—baik itu seorang admin sistem, manajer, atau bahkan anggota keluarga—sudah akrab dengan format percakapan, sehingga interaksi dengan sistem otomatis terasa alami.

  2. Ekosistem API yang Matang dan Terbuka: Kunci utama kekuatan Telegram adalah Bot API-nya. API ini merupakan contoh textbook dari arsitektur API-first, di mana fungsionalitas inti diekspos melalui endpoint yang terdefinisi dengan baik, stabil, dan terdokumentasi secara komprehensif. Ini memungkinkan developer untuk berinteraksi dengan layanan Telegram secara terprogram tanpa terikat pada satu bahasa atau platform tertentu. Sifatnya yang terbuka menciptakan ekosistem yang subur bagi library dan framework pendukung.

  3. Komunikasi Real-time Berbasis Peristiwa (Event-Driven): Bot Telegram tidak bekerja dengan model polling (bertanya secara berkala), melainkan model push atau webhook. Ketika sebuah peristiwa terjadi (misalnya, pesan masuk), Telegram secara proaktif mengirimkan data ke server bot. Dari perspektif arsitektur sistem, ini jauh lebih efisien dalam penggunaan sumber daya (resource) dan menyediakan komunikasi dengan latensi rendah, yang krusial untuk tugas-tugas yang memerlukan respons cepat.

Jendela Implementasi yang Beragam

Sesuai dengan kutipan pembuka, jalan menuju otomasi Telegram tidak tunggal. Setiap “jendela” menawarkan perspektif dan perangkat yang berbeda, sesuai dengan kebutuhan dan keahlian:

  • cURL & Bash Scripting: Ini adalah pendekatan paling fundamental, berinteraksi langsung dengan HTTP API Telegram. Meskipun terlihat sederhana, metode ini sangat efektif untuk tugas-tugas seperti notifikasi dari cron job, pemantauan status server, atau skrip otomasi sederhana di lingkungan Linux/Unix. Ia mengajarkan prinsip dasar cara kerja sebuah API web.

  • PHP: Sebagai salah satu bahasa pemrograman sisi server paling populer, PHP menawarkan jembatan yang mudah untuk mengintegrasikan otomasi Telegram ke dalam aplikasi web yang sudah ada. Contohnya, mengirim notifikasi pesanan dari situs e-commerce, konfirmasi pendaftaran pengguna, atau membuat dashboard internal yang bisa dikontrol via Telegram.

  • Google Apps Script (GAS): Ini adalah jendela unik menuju otomasi “nirserver” (serverless) dalam ekosistem Google. Tanpa perlu mengelola server sendiri, kita bisa membuat bot yang terintegrasi langsung dengan Google Sheets, Docs, Drive, atau Calendar. Ini membuka peluang otomasi perkantoran dan analisis data sederhana dengan biaya yang sangat rendah.

  • Bun / Node.js (JavaScript/TypeScript): Mewakili pendekatan modern yang berfokus pada performa tinggi dan operasi asinkron. Lingkungan JavaScript di sisi server ini sangat ideal untuk membangun bot yang kompleks, interaktif, dan perlu menangani banyak pengguna secara bersamaan. Model non-blocking I/O-nya sangat cocok untuk aplikasi berbasis jaringan seperti bot Telegram.

  • Python: Dikenal dengan sintaksisnya yang bersih dan ekosistem library yang sangat kaya, Python adalah salah satu pilihan paling populer untuk pengembangan bot Telegram. Framework seperti python-telegram-bot dan aiogram menyediakan abstraksi tingkat tinggi yang mempercepat pengembangan, ideal untuk proyek dari skala kecil hingga besar.

  • Go (Golang): Bahasa yang dikompilasi dari Google ini unggul dalam konkurensi dan performa. Pilihan tepat untuk membangun bot berkinerja tinggi yang perlu menangani ribuan permintaan per detik dengan penggunaan memori yang efisien.

  • Rust: Menawarkan keamanan memori (memory safety) tanpa garbage collector, Rust menjadi pilihan menarik untuk aplikasi yang membutuhkan keandalan dan efisiensi maksimal. Meskipun kurva belajarnya lebih curam, bot yang dibangun dengan Rust memiliki potensi performa setara C/C++ dengan jaminan keamanan yang lebih baik.

  • dan bahasa pemrograman lainnya,…

Dengan memahami berbagai pendekatan ini, kita tidak hanya belajar cara membuat bot, tetapi juga mengapresiasi prinsip-prinsip rekayasa perangkat lunak yang lebih luas. Selamat datang di dunia otomasi, mari kita buka jendelanya satu per satu.

Penting Sebelum Baca

Sebelum memulai perjalanan belajar membuat bot Telegram, ada beberapa hal penting yang perlu kita pahami dan persiapkan. Panduan ini akan membantu memaksimalkan proses pembelajaran dan menghindari kendala yang sering dialami pemula.


1. Mindset Eksperimen: Berani Mencoba dan Belajar dari Kesalahan

Dalam mempelajari pemrograman bot Telegram, sikap mental yang tepat adalah kunci kesuksesan. Anggaplah setiap latihan sebagai eksperimen yang menarik, bukan sebagai ujian yang harus sempurna.

Terutama buat adik-adik kita, jangan ragu untuk memulai dan mencoba yak.

Mengapa Mindset Ini Penting?

Setiap bahasa pemrograman memiliki cara penulisan dan pola pikir (idiom) yang unik. Apa yang mudah di satu bahasa, mungkin memerlukan pendekatan berbeda di bahasa lain. Dengan mindset eksperimen, kamu akan:

  • Lebih berani mencoba berbagai pendekatan tanpa takut salah
  • Belajar lebih cepat dari setiap kesalahan yang terjadi
  • Memahami lebih dalam mengapa suatu cara berhasil atau gagal

Tips Praktis

  • Catat setiap percobaan yang kamu lakukan, baik yang berhasil maupun yang gagal
  • Refleksikan perbedaan antara berbagai pendekatan yang kamu coba
  • Jangan menyerah ketika menemui error — ini adalah bagian normal dari proses belajar

Seperti yang dikatakan Thomas Edison: “Kegagalan hanya sinyal bahwa kita tengah mendekati jawaban.” Setiap error adalah petunjuk yang membawa kamu lebih dekat ke solusi.


2. Struktur Belajar: Ikuti Alur yang Sistematis

Materi dalam buku ini dirancang dengan pola pembelajaran yang terstruktur dan bertahap. Memahami struktur ini akan membantu kamu belajar lebih efektif.

Pola Pembelajaran: Konsep → Praktik → Studi Kasus

Setiap bab mengikuti alur berikut:

  1. Konsep — Penjelasan teori dan dasar-dasar yang perlu dipahami
  2. Praktik — Latihan langsung dengan kode yang bisa kamu coba sendiri
  3. Studi Kasus — Penerapan konsep dalam contoh nyata yang lebih kompleks

Mengapa Urutan Itu Penting?

Bab-bab disusun secara berurutan dan saling membangun. Materi di bab selanjutnya sering kali menggunakan konsep dari bab sebelumnya. Oleh karena itu:

  • Ikuti urutan bab dari awal hingga akhir untuk pengalaman belajar yang optimal
  • Jangan skip bab meskipun terlihat mudah — mungkin ada detail penting yang akan digunakan nanti
  • Ulangi bab sebelumnya jika merasa kesulitan memahami bab berikutnya

Dengan mengikuti alur naratif yang telah dirancang, kamu akan merasakan progres yang jelas dan terukur.


3. Prasyarat Teknis: Persiapan Lingkungan Pengembangan

Sebelum mulai coding, pastikan kamu telah menyiapkan lingkungan pengembangan yang diperlukan. Persiapan yang baik akan menghemat waktu dan menghindari frustrasi di tengah pembelajaran.

Apa Saja yang Perlu Disiapkan?

a. Editor Teks atau IDE (Integrated Development Environment)

Kamu memerlukan aplikasi untuk menulis kode. Beberapa pilihan yang direkomendasikan:

  • Visual Studio Code (gratis, populer, banyak ekstensi)
  • PyCharm (khusus untuk Python, ada versi gratis)
  • Sublime Text atau Notepad++ (ringan dan sederhana)

b. Runtime Bahasa Pemrograman

Pastikan bahasa pemrograman yang akan kamu gunakan sudah terinstal di komputer:

  • Python — jika menggunakan python-telegram-bot
  • Node.js — jika menggunakan Telegraf atau node-telegram-bot-api
  • PHP, Go, atau bahasa lain sesuai pilihanmu

c. Akun Telegram BotFather

BotFather adalah bot resmi Telegram untuk membuat dan mengelola bot. Kamu perlu:

  1. Membuka aplikasi Telegram
  2. Mencari @BotFather
  3. Membuat bot baru dan mendapatkan token API

Catatan Penting

Meskipun setiap bab dalam buku ini menjelaskan langkah instalasi secara detail, mempersiapkan semuanya di awal akan membuat proses belajar lebih lancar. Kamu bisa langsung fokus pada materi tanpa terganggu masalah teknis.


4. Catatan dan Dokumentasi: Jurnal Belajarmu

Salah satu kebiasaan terbaik yang bisa kamu kembangkan adalah mendokumentasikan proses belajar. Ini mungkin terdengar sepele, tetapi manfaatnya luar biasa besar.

Mengapa Perlu Membuat Catatan?

  • Referensi pribadi — kamu bisa kembali melihat solusi yang pernah berhasil
  • Mempercepat debugging — Ketika menemui masalah serupa, kamu sudah tahu cara mengatasinya
  • Memperkuat pemahaman — Menulis ulang dengan kata-kata sendiri membantu otak memproses informasi lebih baik
  • Portfolio belajar — Catatanmu bisa menjadi bukti progres dan kemampuan

Apa yang Perlu Dicatat?

Buatlah jurnal belajar yang mencakup:

  • Error yang pernah muncul dan bagaimana cara mengatasinya
  • Konsep yang sulit dipahami dengan penjelasan versi kamu sendiri
  • Kode-kode penting yang sering digunakan (snippet)
  • Ide-ide proyek yang muncul saat belajar

Kamu bisa menggunakan:

  • Aplikasi note (Notion, Evernote, Google Keep)
  • File markdown di komputer
  • Buku catatan fisik (jika lebih nyaman menulis tangan)

Dokumentasi kesalahan dan solusi akan menjadi referensi emas di proyek-proyek berikutnya.


5. Kolaborasi dan Komunitas: Belajar Bersama Lebih Menyenangkan

Belajar sendiri memang bisa, tetapi belajar bersama komunitas akan jauh lebih efektif dan menyenangkan.

Manfaat Bergabung dengan Komunitas

  • Mendapat bantuan ketika mengalami kesulitan
  • Berbagi pengalaman dan belajar dari pengalaman orang lain
  • Menemukan inspirasi untuk proyek-proyek baru
  • Memperluas jaringan dengan sesama developer
  • Tetap termotivasi melalui dukungan dan semangat bersama

Di Mana Bisa Bergabung?

  • Grup Telegram — Komunitas bot Indonesia dan developer Telegram
  • Forum daring — Stack Overflow, Reddit, atau forum lokal
  • GitHub — Ikuti repository terkait, baca kode orang lain, kontribusi ke open source
  • Discord/Slack — Banyak komunitas developer yang aktif di platform ini

Prinsip Berbagi Ilmu

Ingat pepatah populer: “Sharing is caring”ilmu akan berlipat ganda ketika dibagikan.

Ketika kita berbagi:

  • Orang lain mendapat manfaat dari pengetahuanmu
  • Kamu juga memperkuat pemahaman dengan menjelaskan ke orang lain
  • Komunitas menjadi lebih kuat dan saling mendukung

Jangan ragu yak untuk bertanya, tetapi juga jangan pelit berbagi ketika kamu sudah tahu jawabannya.


Siap Memulai?

Dengan persiapan yang tepat — mindset yang benar, pemahaman struktur belajar, lingkungan teknis yang siap, kebiasaan dokumentasi, dan dukungan komunitas — kamu sudah memiliki fondasi yang kuat untuk sukses dalam mempelajari pembuatan bot Telegram.

Selamat belajar, dan nikmati setiap prosesnya! 🚀

Memahami Konsep “Gratis” (Free) dalam Dunia Digital

Saat kita mendengar kata “gratis” atau “free”, pikiran kita seringkali langsung tertuju pada sesuatu yang bisa didapatkan tanpa mengeluarkan uang sepeser pun. Namun, dalam dunia teknologi dan pengembangan perangkat lunak, “gratis” memiliki makna yang lebih dalam dan beragam.

Untuk memahaminya, mari kita bedah dua konsep utama dari “gratis” yang sering dianalogikan sebagai:

  1. “Gratis seperti sampel produk” (free as in free samples): kamu mendapatkannya tanpa biaya.
  2. “Gratis seperti kebebasan berpendapat” (free as in free speech): kamu bebas menggunakannya sesuai keinginanmu.

1. Gratis sebagai “Tanpa Biaya”

Ini adalah konsep yang paling umum kita temui. Layanan atau produk diberikan tanpa biaya moneter langsung. Namun, penting untuk bertanya: Jika saya tidak membayar, lalu siapa yang membayar?

Biasanya, ada model bisnis di baliknya:

  • Model Freemium: Fitur dasar gratis, tetapi fitur premium atau lanjutan memerlukan pembayaran.

    • Contoh Nyata: Aplikasi Zoom memungkinkan rapat gratis hingga 40 menit, tetapi untuk waktu lebih lama atau peserta lebih banyak, kamu harus berlangganan. Hal yang sama berlaku untuk Spotify, yang gratis dengan iklan, tetapi berbayar untuk melewatinya.
  • Didukung Iklan (Ads-Supported): Layanan tetap gratis bagi pengguna karena biayanya ditutupi oleh pengiklan.

    • Contoh Nyata: Facebook dan Google Search adalah layanan gratis, tetapi mereka menghasilkan pendapatan dengan menampilkan iklan yang sangat tertarget berdasarkan data pengguna.
  • Monetisasi Data: Jika kamu tidak membayar untuk produknya, seringkali Kamulah produknya. Data aktivitasmu dikumpulkan dan dianalisis untuk berbagai keperluan.

    • Contoh Nyata: Banyak aplikasi gratis di ponsel yang meminta akses ke kontak atau lokasimu. Data ini bisa jadi diolah secara anonim dan dijual ke pihak ketiga untuk riset pasar.

Kaitan dengan Bot Telegram

Dalam panduan ini, kita akan menggunakan layanan seperti Google Apps Script (GAS) atau Laptop/Komputer Sendiri untuk menjalankan bot kita. Layanan ini gratis tanpa biaya, tetapi datang dengan batasan (kuota), seperti jumlah eksekusi harian atau bot yang akan “tidur” jika tidak aktif. Jika bot kita menjadi sangat populer, kita mungkin perlu membayar untuk meningkatkan kapasitas.


2. Gratis sebagai “Kebebasan” (Open Source)

Konsep ini lebih teknis namun sangat fundamental. Ini adalah inti dari Perangkat Lunak Bebas dan Sumber Terbuka (Free and Open Source Software - FOSS). Di sini, “gratis” berarti kebebasan, bukan hanya soal harga.

Ini mengacu pada kebebasan pengguna untuk:

  1. Menjalankan program untuk tujuan apa pun.
  2. Mempelajari cara kerja program dan mengubahnya sesuai kebutuhan (memerlukan akses ke kode sumber).
  3. Mendistribusikan kembali salinan agar dapat membantu orang lain.
  4. Mendistribusikan salinan dari versi yang telah kamu modifikasi.
  • Analogi Sederhana: Bayangkan kamu mendapatkan sebuah resep kue.
    • Resep Tertutup (Proprietary): kamu hanya diberi tahu cara memanggangnya. Kamu tidak tahu bahan-bahan rahasianya dan dilarang membagikan resep itu.
    • Resep Terbuka (Open Source): kamu mendapatkan daftar lengkap bahan, instruksi, dan izin untuk mengubah resep (misalnya, mengganti gula dengan madu) dan membagikan resep barumu kepada siapa pun.

Kaitan dengan Bot Telegram

Banyak library (pustaka kode) yang kita gunakan untuk membuat bot, seperti grammY (JavaScript) atau python-telegram-bot (Python), bersifat open source.

Ini artinya, kita punya kebebasan penuh untuk:

  • Melihat dan memeriksa kode mereka.
  • Memodifikasinya jika memang diperlukan.
  • Bahkan ikut berkontribusi dalam pengembangannya.

Kita tidak terjebak pada satu vendor saja dan punya kontrol penuh atas teknologi yang kita gunakan. Kita merasa nyaman karena bisa memastikan bahwa tidak ada spyware, backdoor atau hal berbahaya lainnya di dalam sistem.


Kesimpulan: Bijak dalam Menggunakan yang “Gratis”

Seperti yang disinggung di teks awal, tidak ada yang benar-benar 100% gratis. Bahkan ketika menggunakan layanan gratis tanpa biaya dan perangkat lunak yang bebas, kita tetap berinvestasi dalam bentuk:

  • Waktu dan Tenaga: Waktu yang kamu habiskan untuk belajar, mencoba, dan memperbaiki adalah biaya paling berharga.
  • Sumber Daya: Koneksi internet, listrik untuk perangkat, dan biaya perangkat itu sendiri.
  • Keterbatasan: Menerima batasan dari layanan gratis atau risiko bahwa layanan tersebut bisa berhenti kapan saja.

Memahami kedua sisi dari “gratis” ini membantu kita menjadi pengembang yang lebih bijak. Kita bisa memanfaatkan apa yang tersedia tanpa biaya untuk memulai, sambil menghargai kebebasan yang diberikan oleh komunitas open source untuk membangun teknologi yang lebih baik dan lebih transparan.

Donasi

Apabila kamu merasa mendapatkan manfaat yang signifikan dari suatu proyek atau layanan gratis, dengan rendah hati menyarankan kamu untuk mempertimbangkan donasi. Dukungan finansial dari pengguna yang puas—seperti kamu—merupakan energi utama bagi para pengembang untuk menjaga kelangsungan proyek, membantu menutup biaya operasional, dan terus berinovasi dalam menghadirkan fitur-fitur baru.

Note

Ini juga berlaku untuk Proyek Pembelajaran ini, yak 😍

Meski demikian, kami tegaskan bahwa memberikan donasi bukanlah suatu kewajiban bagimu.

Referensi untuk Bacaan Lebih Lanjut

Sebuah Kesepakatan

Tanggung Jawab Ada di Tanganmu

Selamat datang di ruang belajar kita bersama! Panduan dan materi di sini disusun dengan semangat kolaborasi untuk membantumu mencapai tujuan. Kami percaya pada kekuatan berbagi ilmu dan saling mendukung.

Namun, ada satu hal penting yang perlu kita sepakati bersama sejak awal:

🏃🏼‍♂️ Perjalanan Ini Milikmu

Anggaplah kami sebagai teman yang memberikan peta dan kompas. Kami menunjukkan jalan yang mungkin, memberikan tips, dan berbagi alat yang kami tahu. Namun, kamu adalah sang petualang yang menempuh perjalanan itu sendiri.

  • Setiap keputusan yang kamu ambil, mulai dari baris kode yang kamu tulis, layanan yang kamu gunakan, hingga cara kamu mengelola proyek, adalah sepenuhnya tanggung jawabmu.
  • Segala risiko, baik itu berupa tagihan tak terduga dari penyedia layanan, kesalahan pada bot, atau tantangan teknis lainnya, adalah bagian dari proses belajar yang kamu hadapi dan selesaikan sendiri.

Komunitas atau para kontributor tidak dapat dimintai pertanggungjawaban atas apa pun yang terjadi pada proyekmu.

😘 Nikmati Buah Jerih Payahmu

Di sisi lain, medali keberhasilannya juga sepenuhnya milikmu.

Ketika bot kamu berjalan lancar, memberikan manfaat, atau bahkan menjadi proyek besar, kamulah yang patut berbangga. Keberhasilan itu adalah hasil dari waktu, tenaga, dan kecerdasan yang kamu curahkan.

Dan kami? Tentu saja, kami akan menjadi pendukung paling antusias yang ikut berbahagia dan merayakan setiap pencapaianmu.

Selamat berkarya!

Membuka Jendela-Jendela Pengetahuan

Selamat datang, para pembelajar dan inovator masa depan!

Perjalananmu dalam dunia pembuatan bot Telegram adalah sebuah langkah untuk tidak hanya menguasai teknologi, tetapi juga untuk menciptakan solusi yang bermanfaat bagi banyak orang. Di era digital ini, kemampuan untuk membangun interaksi otomatis yang cerdas dan efisien adalah sebuah keterampilan yang sangat berharga.

Tentu, proses belajar terkadang terasa menantang. Mungkin ada kalanya kamu merasa buntu saat menghadapi bug yang sulit dipecahkan, atau merasa ragu dengan kompleksitas kode yang ada di depan mata. Namun, di saat-saat seperti itulah penting untuk mengingat sebuah prinsip fundamental:

“Ilmu itu tak mengenal satu pintu, melainkan banyak jendela.”

Filosofi ini mengingatkan kita bahwa jalan menuju pemahaman tidaklah tunggal. Jika satu pendekatan terasa buntu, selalu ada jendela lain yang bisa kita buka. Setiap kesalahan adalah kesempatan untuk belajar, setiap baris kode yang kita tulis adalah sebuah langkah maju, dan setiap diskusi dengan komunitas adalah cara untuk melihat dari perspektif baru.

Secara akademis, proses ini dikenal sebagai iterative learning dan collaborative problem-solving. Kamu tidak hanya sekadar “menulis kode”, tetapi kamu sedang terlibat dalam sebuah siklus:

  1. Konseptualisasi: Memahami masalah yang ingin diselesaikan.
  2. Implementasi: Menerjemahkan solusi ke dalam kode.
  3. Pengujian & Refleksi: Mengevaluasi hasilnya, menemukan kekurangan, dan belajar dari proses tersebut.

Buku dan materi di sini dirancang untuk menjadi salah satu dari banyak jendela tersebut. Manfaatkanlah sebagai pemantik rasa ingin tahumu. Jangan ragu untuk bereksperimen, memodifikasi contoh yang ada, dan bahkan “merusak” sesuatu untuk kemudian memperbaikinya. Karena di situlah letak pembelajaran yang sejati.

Selamat berkarya, dan selamat membuka jendela-jendela pengetahuan baru. Semoga perjalananmu menyenangkan dan membawa dampak positif.

Ruang Diskusi

Tip

Gabung Yuk, ke Grup Telegram Kite! 😁

Untuk memperkuat ekosistem belajar bersama, silakan bergabung dengan grup Telegram @botIndonesia

Di sana, kita bisa berdiskusi santai, bertukar pikiran, mengulas studi kasus, hingga membantu teman-teman yang baru memulai. Anggap saja ini seperti tongkrongan digital, karena obrolan di dalamnya ada juga bebas dan lepas.

Jika ada yang ingin ditanyakan atau didiskusikan terkait materi dan tutorial di sini, grup tersebut adalah jalur komunikasi utamanya. Dengan begitu, diskusi publik akan lebih bermanfaat bagi semua anggota.

Mohon dipahami bahwa ini adalah ruang komunitas untuk berbagi, bukan layanan tanya-jawab seperti Customer Service. Tidak semua pertanyaan kamu harus dan bisa terjawab. Mari kita ciptakan lingkungan belajar yang santai dan saling mendukung. be wise

🎯 Just Ask - Langsung ke Poin

Jika ada yang ingin ditanyakan, langsung saja tanyakan poinnya. Tidak perlu bertanya untuk bertanya, seperti “Boleh tanya?”, “Ada yang bisa bantu?”, atau “Permisi, mau tanya dong”.

Istilahnya “just ask” — langsung sampaikan pertanyaan atau masalah yang ingin didiskusikan. Ini akan membuat komunikasi lebih efisien dan memudahkan orang lain untuk langsung membantu.

👎🏾 Contoh kurang efektif

Warning

  • “Apakah saya boleh bertanya?”
  • “Permisi, boleh tanya tentang bot Telegram?”
  • “Apakah ada yang pakai Madelineproto?”
  • “Ada yang dari Bandung?”

🙅🏻‍♂️ Hindari itu yak!

👌🏽 Contoh Baik

Note

  • “Saya menemukan error saat menjalankan perintah ini [command line], menggunakan bot dengan Library xxx dengan pesan : '...', kira-kira kenapa ya, dan apa solusinya?”
  • “Bagaimana cara membuat inline keyboard di bot Telegram menggunakan python-telegram-bot?”
  • “Saya ingin belajar secara langsung tentang coding membuat bot telegram, atau ada proyek yang harus dikerjakan bersama… apakah ada yang dari Salatiga?”

Dengan bertanya langsung ke poin, kamu menghemat waktu semua orang dan meningkatkan peluang mendapat jawaban yang tepat.

🫥 Karena kami bukan dukun

Kami mohon maaf sebelumnya, karena kami bukan peramal yang bisa langsung tahu apa yang ada di pikiran atau apa yang sedang kamu hadapi.

Maka dari itu, kami sangat menghargai kalau kamu bisa memberikan penjelasan yang lebih detail, ya! Jangan ragu untuk menyertakan screenshot atau potongan kode (jika ada) agar kami bisa mengerti masalahmu dengan lebih baik dan cepat.

🤪 Dibikin Santai Saja

Sebagai informasi tambahan, sebagian besar dari kami adalah orang teknis yang sehari-hari bekerja di depan layar monitor. Ini berarti kami tidak selalu bisa merespons secepat kilat. Jadi, mari kita bawa santai saja proses ini.

Caution

Terima kasih atas pengertian dan kerja samanya!

Integrasi Bot Telegram

Apa Tujuan Bagian Ini?

Bagian ini adalah tempat untuk menyimpan berbagai skrip dan tutorial yang menghubungkan bot Telegram dengan aktivitas kita sehari-hari. Idenya adalah membuat “pembantu” digital kecil yang bisa memberikan informasi atau melakukan tugas-tugas ringan secara otomatis langsung ke akun Telegram kamu.

Fungsinya sengaja dibuat sederhana, tidak rumit, tapi sangat bermanfaat untuk mempermudah hidup dan memonitor berbagai hal.

Meski belum semuanya dibuat, tapi ide tetap harus ada dan berkembang :-)

Contoh-Contoh Kegunaan

Berikut adalah beberapa contoh nyata dari apa yang bisa kamu temukan atau buat di dalam folder ini:

  • Notifikasi Login Server (VPS)

    • Fungsi: Mendapatkan peringatan real-time setiap kali ada yang berhasil login ke server pribadi kamu.
    • Manfaat: Meningkatkan keamanan dengan memantau akses yang tidak dikenal.
    • Lihat tutorial Notifikasi Login VPS
  • Pengingat Cuaca Harian

    • Fungsi: Sebuah skrip yang berjalan setiap pagi untuk mengirimkan ramalan cuaca hari ini (misalnya, suhu, kemungkinan hujan) ke chat kamu.
    • Manfaat: Membantu kamu bersiap-siap sebelum berangkat kerja atau beraktivitas.
  • Pengecek Status Website

    • Fungsi: Skrip yang secara berkala memeriksa apakah blog atau website pribadi kamu sedang online. Jika website down, bot akan langsung mengirim notifikasi.
    • Manfaat: kamu bisa segera tahu jika ada masalah dengan website kamu dan bisa langsung menanganinya.
  • Bot Pencatat Ide Sederhana

    • Fungsi: kamu bisa mengirim pesan/ide apa pun ke bot, dan bot akan menyimpannya ke dalam satu file teks di server kamu.
    • Manfaat: Cara super cepat untuk mencatat ide yang tiba-tiba muncul tanpa perlu membuka aplikasi lain.
  • Notifikasi Jadwal Minum Obat atau Vitamin

    • Fungsi: Mengatur jadwal (misalnya via cron job) agar bot mengirim pengingat untuk minum obat atau vitamin pada jam-jam tertentu.
    • Manfaat: Sangat membantu untuk menjaga rutinitas kesehatan.
  • dan lain sebagainya yak..


Intinya, bagian ini didedikasikan untuk kreativitas dalam mengotomatisasi tugas-tugas kecil yang berguna.

Note

Jika kamu punya ide lain, jangan ragu untuk menambahkannya!

Notifikasi Login VPS ke Telegram dengan Bash dan cURL

Tutorial ini akan memandu kamu langkah demi langkah untuk membuat sebuah skrip sederhana yang akan mengirimkan notifikasi ke akun Telegram kamu setiap kali ada pengguna yang berhasil login ke server (VPS) melalui SSH. Ini adalah cara yang bagus untuk memonitor aktivitas login dan meningkatkan keamanan servermu.


Langkah 1: Membuat Bot Telegram

Untuk mengirim pesan melalui API Telegram, kita memerlukan sebuah bot.

  1. Buka aplikasi Telegram kamu, cari akun bernama BotFather (ada tanda centang biru).
  2. Mulai percakapan dengan BotFather dengan mengetik /start.
  3. Buat bot baru dengan mengetik perintah /newbot.
  4. BotFather akan meminta kamu untuk memberikan nama untuk bot kamu (misalnya: “VPS Monitor”).
  5. Selanjutnya, berikan username untuk bot kamu. Username harus unik dan diakhiri dengan kata bot (misalnya: vps_monitor_xyz_bot).
  6. Setelah berhasil, BotFather akan memberikan kamu sebuah Token API. Token ini sangat rahasia dan digunakan untuk mengontrol bot kamu.

Contoh Token dari BotFather

Salin dan simpan token ini di tempat yang aman. Kita akan menggunakannya di dalam skrip.

Warning

CATATAN PENTING: Jaga kerahasiaan Token API kamu. Siapa pun yang memilikinya dapat mengendalikan botmu.


Langkah 2: Mendapatkan Chat ID Kamu

Setelah bot dibuat, kita perlu tahu kemana pesan notifikasi akan dikirim. Setiap pengguna atau grup di Telegram memiliki Chat ID yang unik.

  1. Di aplikasi Telegram kamu, cari username bot yang baru saja kamu buat.

  2. Mulai percakapan dengan bot kamu dengan menekan tombol Start atau mengirim pesan apa pun (misalnya: “halo”).

  3. Sekarang, buka terminal di VPS kamu (atau komputer lokal yang memiliki curl) dan jalankan perintah berikut. Ganti <TOKEN_BOT_KAMU> dengan Token API yang kamu dapatkan dari BotFather.

    curl "https://api.telegram.org/bot<TOKEN_BOT_KAMU>/getUpdates"
    
  4. Kita akan melihat respons dalam format JSON. Cari bagian result -> message -> chat -> id. Itulah Chat ID kamu.

    {
      "ok": true,
      "result": [
        {
          "update_id": 834572275,
          "message": {
            "message_id": 1,
            "from": {
              "id": 123456789, // Ini adalah Chat ID kamu
              "is_bot": false,
              "first_name": "Nama",
              "last_name": "Kamu",
              "username": "usernamemu",
              "language_code": "en"
            },
            "chat": {
              "id": 123456789, // Pastikan untuk menyalin ID ini
              "first_name": "Nama",
              "last_name": "Kamu",
              "username": "usernamemu",
              "type": "private"
            },
            "date": 1672531200,
            "text": "halo"
          }
        }
      ]
    }
    

Atau bisa didapatkan di bot @strukturbot

Salin dan simpan ID / Chat ID kamu.


Langkah 3: Membuat Skrip Bash Notifikasi

Sekarang kita akan membuat skrip bash yang akan mengirim notifikasi.

  1. Buat file baru di direktori yang kamu inginkan, misalnya /usr/local/bin/notif-login.sh.

    sudo nano /usr/local/bin/notif-login.sh
    
  2. Salin dan tempel kode berikut ke dalam file tersebut.

    #!/bin/bash
    
    # --- KONFIGURASI ---
    # Ganti dengan Token API bot Telegram kamu
    TOKEN="<GANTI_DENGAN_TOKEN_KAMU>"
    # Ganti dengan Chat ID kamu
    CHAT_ID="<GANTI_DENGAN_CHAT_ID_KAMU>"
    # --- SELESAI KONFIGURASI ---
    
    # Mendapatkan informasi login
    # PAM_USER adalah username yang login
    # PAM_RHOST adalah alamat IP dari mana user login
    # PAM_TYPE adalah jenis sesi (misal: "sshd", "login")
    USER_LOGIN="${PAM_USER}"
    IP_ADDRESS="${PAM_RHOST}"
    LOGIN_TYPE="${PAM_TYPE}"
    HOSTNAME=$(hostname)
    
    # Format pesan notifikasi (menggunakan format Markdown)
    MESSAGE=$(printf "🚨 *Notifikasi Login SSH di %s*\n\n*Username:* \`%s\`\n*Dari IP:* \`%s\`\n*Jenis Sesi:* \`%s\`\n*Waktu:* \`%s\`" \
        "$HOSTNAME" \
        "$USER_LOGIN" \
        "$IP_ADDRESS" \
        "$LOGIN_TYPE" \
        "$(date '+%d-%m-%Y %H:%M:%S')")
    
    # URL API Telegram untuk mengirim pesan
    URL="https://api.telegram.org/bot${TOKEN}/sendMessage"
    
    # Mengirim notifikasi menggunakan curl
    # -s : silent mode, tidak menampilkan progress bar
    # -d : data yang dikirim (payload)
    # parse_mode=Markdown : agar format tebal, miring, dll bisa ditampilkan
    curl -s -d "chat_id=${CHAT_ID}&text=${MESSAGE}&parse_mode=Markdown" "${URL}" > /dev/null
    
  3. Penting: Ganti nilai TOKEN dan CHAT_ID dengan milikmu.

  4. Simpan file tersebut (di nano, tekan Ctrl+X, lalu Y, lalu Enter).


Langkah 4: Membuat Skrip Menjadi Executable

Agar skrip bisa dijalankan, kita perlu memberikan izin eksekusi.

sudo chmod +x /usr/local/bin/notif-login.sh

Langkah 5: Menjalankan Skrip Secara Otomatis Saat Login

Cara terbaik untuk memicu skrip ini saat ada login SSH adalah dengan menggunakan PAM (Pluggable Authentication Modules).

  1. Buka file konfigurasi PAM untuk SSH.

    sudo nano /etc/pam.d/sshd
    
  2. Tambahkan baris berikut di akhir file. Baris ini akan memberitahu PAM untuk menjalankan skrip kita setiap kali sesi SSH berhasil dibuka.

    # Menjalankan skrip notifikasi Telegram saat sesi login dibuka
    session    optional     pam_exec.so /usr/local/bin/notif-login.sh
    
    • session: Menandakan bahwa ini berjalan pada tahap sesi.
    • optional: Jika skrip gagal, proses login tetap diizinkan. Ini penting agar kamu tidak terkunci dari server jika ada kesalahan pada skrip.
    • pam_exec.so: Modul PAM yang digunakan untuk mengeksekusi perintah eksternal.
  3. Simpan dan tutup file.

    Tip

    tekan CTRL+O dan ENTER untuk menyimpannya.


Langkah 6: Uji Coba

Selesai! Sekarang mari kita uji.

  1. Logout dari sesi SSH kamu saat ini.
  2. Login kembali ke VPS-mu.
  3. Dalam beberapa detik, kamu akan menerima notifikasi di Telegram dari bot yang telah kamu buat!

Pesan notifikasinya akan terlihat seperti ini:

🚨 Notifikasi Login SSH di nama-vps-kamu

Username: root

Dari IP: 123.123.123.123

Jenis Sesi: sshd

Waktu: 29-11-2025 10:30:00

Selamat! Kamu telah berhasil meningkatkan keamanan server kamu dengan notifikasi login real-time!

Membuat Bot Telegram dengan PHP dan cURL

Metadata Penulis:

  • Penulis: Hasanudin H Syafaat (bangHasan)
  • Email: banghasan@gmail.com
  • Website: banghasan.com
  • Grup Diskusi Telegram: @botindonesia
  • Versi: 0.0.1

cover php cURL


Bagian I: Dasar-Dasar

Bab 1: Pengantar Bot Telegram dan PHP

1.1. Apa itu Bot Telegram?

Bot Telegram adalah akun khusus yang tidak memerlukan nomor telepon untuk mendaftar dan dioperasikan oleh perangkat lunak. Bot dapat melakukan berbagai tugas, mulai dari mengirimkan notifikasi, mengintegrasikan layanan lain, hingga menjadi alat bantu interaktif dalam obrolan. Bot berinteraksi dengan dunia luar melalui Telegram Bot API, sebuah antarmuka HTTP yang sederhana.

1.2. Mengapa Memilih PHP dan cURL?

PHP adalah bahasa pemrograman sisi server yang sangat populer untuk pengembangan web. Kombinasinya dengan cURL (Client URL Library) menjadikannya pilihan yang kuat dan fleksibel untuk berinteraksi dengan API eksternal, termasuk Telegram Bot API.

  • cURL adalah alat yang sangat efisien untuk membuat permintaan HTTP (GET, POST, dll.) dari skrip PHP. Ini memungkinkan kita untuk berkomunikasi langsung dengan API Telegram tanpa perlu menggunakan pustaka pihak ketiga yang kompleks.
  • Pendekatan ini memberikan pemahaman mendalam tentang bagaimana API bekerja, yang sangat penting saat merancang framework bot kustom.

1.3. Persiapan Lingkungan Pengembangan

Untuk memulai, kamu memerlukan lingkungan pengembangan yang mencakup:

  1. Web Server: Apache, Nginx, atau sejenisnya. Diperlukan hanya jika menggunakan metode webhook.
  2. PHP: Versi 7.4 ke atas direkomendasikan.
  3. Ekstensi cURL: Pastikan ekstensi php-curl1 telah diaktifkan di konfigurasi PHP kamu.

1.4. Mendapatkan Token Bot dari @BotFather

Setiap bot memerlukan token unik untuk otentikasi. Token ini didapatkan dari bot resmi Telegram, @BotFather.

  1. Buka aplikasi Telegram dan cari @BotFather.
  2. Ketik /newbot dan ikuti instruksi untuk memilih nama bot (misalnya, “Bot Buku PHP”) dan username (harus diakhiri dengan “bot”, misalnya, “BotBukuPHP_bot”).
  3. Setelah berhasil, @BotFather akan memberikan kamu HTTP API Token yang terlihat seperti 123456:ABC-DEF1234ghIkl-jkl-jkl-jkl-jkl. Jaga kerahasiaan token ini.

Bab 2: Interaksi Pertama dengan Telegram Bot API

2.1. Struktur Permintaan API

Semua interaksi dengan Telegram Bot API dilakukan melalui permintaan HTTP POST atau GET ke URL dasar berikut:

https://api.telegram.org/bot<TOKEN>/<METHOD>

Di mana:

  • <TOKEN> adalah token bot kamu.
  • <METHOD> adalah nama metode API yang ingin kamu panggil (misalnya, sendMessage).

2.2. Memahami Fungsi cURL di PHP

Fungsi inti untuk berinteraksi dengan API menggunakan cURL adalah:

Fungsi cURLDeskripsi
curl_init()Menginisialisasi sesi cURL.
curl_setopt()Mengatur opsi untuk transfer cURL.
curl_exec()Mengeksekusi sesi cURL.
curl_close()Menutup sesi cURL.

2.3. Contoh Dasar: Mengirim Pesan Teks (sendMessage)

Metode sendMessage digunakan untuk mengirim pesan teks ke pengguna atau grup. Parameter wajibnya adalah chat_id (ID obrolan tujuan) dan text (isi pesan).

Berikut adalah fungsi PHP yang mengimplementasikan permintaan cURL ke API Telegram:

<?php
// Ganti dengan token bot kamu
define('BOT_TOKEN', 'GANTI_DENGAN_TOKEN_BOT_KAMU');
define('API_URL', 'https://api.telegram.org/bot' . BOT_TOKEN . '/');

/**
 * Fungsi untuk memanggil metode API Telegram menggunakan cURL
 * @param string $method Nama metode API (misalnya, 'sendMessage')
 * @param array $params Parameter yang akan dikirimkan
 * @return array Hasil respons dari API
 */
function apiRequest($method, $params = []) {
    $url = API_URL . $method;
    $ch = curl_init();
    
    // Mengatur opsi cURL
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Mengembalikan hasil transfer sebagai string
    curl_setopt($ch, CURLOPT_POST, true); // Menggunakan metode POST
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params)); // Mengirim parameter sebagai query string
    
    // Eksekusi permintaan
    $response = curl_exec($ch);
    
    // Cek error
    if (curl_error($ch)) {
        throw new \Exception(curl_error($ch));
    }
    
    // Tutup sesi cURL
    curl_close($ch);
    
    // Mengembalikan respons dalam bentuk array PHP
    return json_decode($response, true);
}

// Contoh penggunaan: Mengirim pesan ke chat ID tertentu
$chat_id = 'GANTI_DENGAN_CHAT_ID_KAMU'; // kamu bisa mendapatkan ini dari update pertama atau di @strukturbot
$text = 'Halo! Ini adalah pesan pertama dari bot PHP cURL saya.';

$result = apiRequest('sendMessage', [
    'chat_id' => $chat_id,
    'text' => $text,
    'parse_mode' => 'Markdown'
]);

// Tampilkan hasil
print_r($result);
?>

2.4. Contoh Dasar: Mendapatkan Informasi Bot (getMe)

Metode getMe adalah cara termudah untuk menguji koneksi dan memverifikasi token bot kamu.

// ... (gunakan fungsi apiRequest dari contoh sebelumnya)

$bot_info = apiRequest('getMe');

if ($bot_info['ok']) {
    echo "Bot berhasil terhubung!\n";
    echo "Username Bot: @" . $bot_info['result']['username'] . "\n";
    echo "ID Bot: " . $bot_info['result']['id'] . "\n";
} else {
    echo "Gagal terhubung ke API Telegram: " . $bot_info['description'] . "\n";
}

2.5. Menjalankan Skrip Melalui Command Line (CLI)

Menjalankan skrip langsung dari command line memudahkan pengujian tanpa harus menyiapkan server web terlebih dahulu. Berikut langkah yang bisa diikuti secara berurutan:

  1. Pastikan PHP terpasang dengan benar. Buka Terminal (macOS/Linux) atau Command Prompt/PowerShell (Windows), lalu jalankan:

    php -v
    

    Jika versi PHP muncul, berarti PHP siap digunakan.

    Contoh hasilnya:

    $ php -v
    PHP 8.3.6 (cli) (built: Jul 14 2025 18:30:55) (NTS)
    Copyright (c) The PHP Group
    Zend Engine v4.3.6, Copyright (c) Zend Technologies
        with Zend OPcache v8.3.6, Copyright (c), by Zend Technologies
    

    Bila muncul pesan error, instal PHP terlebih dahulu atau pastikan path PHP sudah ditambahkan ke PATH.

  2. Simpan kode PHP kamu ke dalam sebuah berkas. Misalnya send_message.php atau get_me.php. Gunakan editor teks apa pun (Notepad, VS Code, atau nano) dan pastikan token bot sudah diganti dengan milikmu.

  3. Masuk ke folder tempat berkas disimpan. Gunakan perintah cd (change directory). Contoh:

    cd /home/user/proyek-bot
    

    Di Windows, sesuaikan dengan drive yang tepat, misalnya cd C:\Users\nama\proyek-bot.

  4. Jalankan skrip dengan perintah php nama_berkas.php. Contoh:

    php send_message.php
    

    Terminal akan menampilkan hasil print_r($result) atau pesan lain yang kamu buat di skrip. Jika permintaan berhasil, status ok bernilai true dan pesan akan terkirim ke Telegram.

  5. Baca pesan atau error yang muncul. Pesan sukses berarti skrip berjalan sesuai harapan. Jika ada error (misalnya {"ok":false,...}), catat keterangannya, periksa ulang token, koneksi internet, atau parameter yang dikirim.

Dengan alur di atas, siapapun dapat menguji bot kecil secara mandiri hanya bermodalkan PHP CLI dan koneksi internet, tanpa harus memahami konfigurasi server web yang lebih kompleks.

Melihat Detail Permintaan dengan cURL Verbose

Kadang perlu melihat detail lalu lintas HTTP (header permintaan, header respons, status koneksi) untuk memastikan permintaan benar. PHP menyediakan opsi CURLOPT_VERBOSE agar cURL mengeluarkan log proses secara mendetail.

  • Fungsi utama: Menampilkan informasi debug yang mencakup bagaimana cURL membuka koneksi, header yang dikirim, respon yang diterima, hingga informasi SSL.
  • Cara mengaktifkan: Setel CURLOPT_VERBOSE ke true. Agar log rapi, arahkan output-nya ke berkas atau php://stdout.

Contoh menyalakan verbose dan menyimpan log ke berkas curl_debug.log:

$ch = curl_init();
$verbose = fopen('curl_debug.log', 'w'); // log akan ditulis ke file

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
curl_setopt($ch, CURLOPT_VERBOSE, true); // aktifkan verbose
curl_setopt($ch, CURLOPT_STDERR, $verbose); // arahkan output verbose

$response = curl_exec($ch);

if (curl_error($ch)) {
    throw new \Exception(curl_error($ch));
}

curl_close($ch);
fclose($verbose);

Setelah skrip dijalankan lewat command line, buka curl_debug.log untuk melihat seluruh detail komunikasi. Ketika terjadi error (contoh: token salah atau koneksi ditolak), informasi verbose biasanya memberi petunjuk jelas soal penyebabnya.

Bab 3: Menerima Pembaruan (Updates) dari Pengguna

Bot perlu menerima pesan atau interaksi dari pengguna, yang disebut Updates. Ada dua cara utama untuk menerima Updates: Polling dan Webhook.

3.1. Metode Polling (Long Polling)

Polling adalah metode di mana bot secara berkala (misalnya, setiap beberapa detik) bertanya kepada server Telegram, “Apakah ada pesan baru untuk saya?”.

  • Cara Kerja getUpdates: Bot memanggil metode getUpdates secara berulang. Telegram menggunakan Long Polling, yang berarti server akan menahan koneksi hingga ada pembaruan baru atau batas waktu tercapai.
  • Kelebihan: Sangat mudah diimplementasikan, tidak memerlukan domain publik atau sertifikat SSL.
  • Kekurangan: Boros sumber daya server (harus terus-menerus membuat koneksi), ada jeda waktu (latency) antara pesan dikirim dan diterima bot, tidak cocok untuk bot dengan volume tinggi.

3.2. Metode Webhook (Direkomendasikan)

Webhook adalah mekanisme di mana server Telegram yang akan menghubungi (memanggil) skrip PHP kamu secara instan setiap kali ada pembaruan baru.

  • Cara Kerja Webhook: kamu memberikan URL publik (misalnya, https://domainmu.com/webhook.php) kepada Telegram. Ketika ada pesan baru, Telegram mengirimkan permintaan HTTP POST berisi data pembaruan (dalam format JSON) ke URL tersebut.
  • Mendaftarkan Webhook (setWebhook):
// ... (gunakan fungsi apiRequest)

$webhook_url = 'https://domainmu.com/webhook.php'; // Ganti dengan URL publik kamu

$result = apiRequest('setWebhook', [
    'url' => $webhook_url
]);

if ($result['ok']) {
    echo "Webhook berhasil diatur ke: " . $webhook_url . "\n";
} else {
    echo "Gagal mengatur Webhook: " . $result['description'] . "\n";
}
  • Menangani Data JSON dari Webhook di PHP: Skrip webhook.php kamu hanya perlu membaca input mentah dari permintaan POST dan memprosesnya.
<?php
// webhook.php
// Baca input mentah dari permintaan POST
$content = file_get_contents("php://input");
$update = json_decode($content, true);

// Log data untuk debugging
file_put_contents('update_log.txt', date('Y-m-d H:i:s') . "\n" . $content . "\n\n", FILE_APPEND);

if (isset($update['message'])) {
    $chat_id = $update['message']['chat']['id'];
    $text = $update['message']['text'];
    
    // Lakukan aksi balasan (misalnya, echo)
    apiRequest('sendMessage', [
        'chat_id' => $chat_id,
        'text' => "Kamu mengirim: " . $text
    ]);
}

// Penting: Telegram mengharapkan respons HTTP 200 OK secepat mungkin
// Skrip harus selesai dieksekusi tanpa output tambahan
?>
  • Kelebihan: Instan, efisien, dan skalabel.
  • Kekurangan: Membutuhkan domain publik dan sertifikat SSL (walaupun Telegram menerima sertifikat yang ditandatangani sendiri, HTTPS tetap wajib).

Bagian II: Fitur Interaktif Bot

Bab 4: Keyboard Balasan (Reply Keyboard)

Keyboard Balasan (Reply Keyboard) adalah keyboard kustom yang muncul di atas kolom input pesan pengguna. Keyboard ini dirancang untuk menggantikan keyboard standar perangkat, membatasi input pengguna ke pilihan yang telah ditentukan.

4.1. Pengenalan ReplyKeyboardMarkup

Untuk menampilkan keyboard ini, kamu perlu mengirimkan objek JSON ReplyKeyboardMarkup sebagai nilai dari parameter reply_markup dalam metode seperti sendMessage.

{
    "keyboard": [
        ["Tombol 1", "Tombol 2"],
        ["Tombol Baris Baru"]
    ],
    "resize_keyboard": true,
    "one_time_keyboard": false
}

4.2. Membuat Keyboard Kustom Sederhana

Dalam PHP, kita akan membuat struktur array yang kemudian di-encode menjadi JSON.

$keyboard = [
    'keyboard' => [
        ['Pesan Saya', 'Bantuan'],
        ['Tentang Bot']
    ],
    'resize_keyboard' => true, // Agar keyboard menyesuaikan ukuran layar
    'one_time_keyboard' => false // Keyboard tetap muncul setelah digunakan
];

$reply_markup = json_encode($keyboard);

// Contoh pengiriman pesan dengan keyboard
apiRequest('sendMessage', [
    'chat_id' => $chat_id,
    'text' => 'Silakan pilih menu di bawah:',
    'reply_markup' => $reply_markup
]);

4.3. Opsi Keyboard Lanjutan

  • resize_keyboard: (Boolean) Jika true, keyboard akan dibuat lebih kecil.
  • one_time_keyboard: (Boolean) Jika true, keyboard akan disembunyikan setelah pengguna menekan tombol.
  • remove_keyboard: (Objek JSON) Digunakan untuk menghapus keyboard balasan yang sedang aktif.
// Menghapus keyboard balasan
$remove_keyboard = json_encode(['remove_keyboard' => true]);

apiRequest('sendMessage', [
    'chat_id' => $chat_id,
    'text' => 'Keyboard telah dihapus.',
    'reply_markup' => $remove_keyboard
]);

4.4. Menangani Input Teks dari Keyboard

Ketika pengguna menekan tombol Reply Keyboard, teks pada tombol tersebut akan dikirimkan ke bot sebagai pesan teks biasa. Bot kamu perlu memproses teks ini seperti perintah atau pesan biasa.

// Dalam skrip webhook.php
if (isset($update['message'])) {
    $chat_id = $update['message']['chat']['id'];
    $text = $update['message']['text'];
    
    switch ($text) {
        case 'Pesan Saya':
            $response = 'Ini adalah pesan dari menu "Pesan Saya".';
            break;
        case 'Bantuan':
            $response = 'Silakan hubungi admin untuk bantuan.';
            break;
        default:
            $response = 'Perintah tidak dikenal.';
            break;
    }
    
    apiRequest('sendMessage', [
        'chat_id' => $chat_id,
        'text' => $response
    ]);
}

Bab 5: Keyboard Inline (Inline Keyboard)

Keyboard Inline adalah tombol-tombol kecil yang melekat langsung pada pesan tertentu. Berbeda dengan Reply Keyboard, tombol Inline tidak mengirimkan teks ke obrolan, melainkan mengirimkan data tersembunyi yang disebut Callback Query.

5.1. Pengenalan InlineKeyboardMarkup

Keyboard Inline dikirim melalui parameter reply_markup dengan objek JSON InlineKeyboardMarkup.

{
    "inline_keyboard": [
        [
            {"text": "Opsi A", "callback_data": "opsi_a"},
            {"text": "Kunjungi", "url": "https://telegram.org"}
        ]
    ]
}

5.2. Perbedaan Utama dengan Reply Keyboard

FiturReply KeyboardInline Keyboard
PosisiDi bawah kolom input pesanMelekat pada pesan
AksiMengirim pesan teks ke obrolanMengirim callback_query tersembunyi
DataTeks tombol terlihat di obrolanData tersembunyi (callback_data)
PenggunaanMenu utama, input terbatasInteraksi spesifik pesan (voting, navigasi)

5.3. Membuat Tombol Inline dengan callback_data

Tombol Inline yang paling umum adalah tombol callback_data. Ketika ditekan, tombol ini mengirimkan callback_query ke bot.

$keyboard = [
    'inline_keyboard' => [
        [
            ['text' => 'Ya, Setuju', 'callback_data' => 'vote_yes'],
            ['text' => 'Tidak Setuju', 'callback_data' => 'vote_no']
        ],
        [
            ['text' => 'Baca Lebih Lanjut', 'url' => 'https://banghasan.com']
        ]
    ]
];

$reply_markup = json_encode($keyboard);

apiRequest('sendMessage', [
    'chat_id' => $chat_id,
    'text' => 'Apakah kamu setuju dengan kebijakan ini?',
    'reply_markup' => $reply_markup
]);

5.4. Menangani callback_query

Data callback_query diterima oleh bot sebagai jenis pembaruan yang berbeda dari pesan biasa.

  1. Mendeteksi callback_query: Periksa apakah array $update memiliki kunci callback_query.
  2. Mengambil Data: Ambil callback_data dan id dari callback_query.
  3. Menjawab Query: Setelah memproses, kamu harus memanggil metode answerCallbackQuery untuk menghilangkan status “loading” pada tombol pengguna.
// Dalam skrip webhook.php
// ...
if (isset($update['callback_query'])) {
    $callback_query_id = $update['callback_query']['id'];
    $callback_data = $update['callback_query']['data'];
    $chat_id = $update['callback_query']['message']['chat']['id'];
    $message_id = $update['callback_query']['message']['message_id'];
    
    $alert_text = '';
    
    switch ($callback_data) {
        case 'vote_yes':
            $alert_text = 'Kamu memilih Ya!';
            $new_text = 'Kamu telah memilih: **Ya**';
            break;
        case 'vote_no':
            $alert_text = 'Kamu memilih Tidak!';
            $new_text = 'Kamu telah memilih: **Tidak**';
            break;
    }
    
    // 1. Menjawab Callback Query (menampilkan notifikasi pop-up)
    apiRequest('answerCallbackQuery', [
        'callback_query_id' => $callback_query_id,
        'text' => $alert_text,
        'show_alert' => false // Jika true, akan muncul pop-up besar
    ]);
    
    // 2. Mengedit Pesan (opsional, untuk menunjukkan perubahan status)
    apiRequest('editMessageText', [
        'chat_id' => $chat_id,
        'message_id' => $message_id,
        'text' => $new_text,
        'parse_mode' => 'Markdown',
        // Hapus reply_markup agar tombol tidak bisa ditekan lagi
    ]);
}
// ...
?>

Bab 6: Bot Inline (Inline Mode)

Bot Inline memungkinkan pengguna untuk berinteraksi dengan bot kamu langsung dari kolom input pesan di obrolan mana pun, tanpa perlu menambahkan bot ke grup atau mengirim pesan langsung. Pengguna hanya perlu mengetik @usernamebot diikuti dengan kueri mereka.

6.1. Mengaktifkan Inline Mode pada Bot

Inline Mode harus diaktifkan melalui @BotFather:

  1. Ketik /setinline dan pilih bot kamu.
  2. Pilih teks placeholder yang akan muncul di kolom input pengguna (misalnya, “Cari di bot ini…”).

6.2. Memahami inline_query

Ketika pengguna mengetik @usernamebot kueri, bot kamu akan menerima pembaruan jenis inline_query. Pembaruan ini berisi:

  • id: ID unik dari kueri inline.
  • query: Teks yang diketik pengguna setelah username bot.
  • from: Informasi pengguna yang membuat kueri.

6.3. Mengirim Hasil Pencarian dengan answerInlineQuery

Untuk merespons inline_query, kamu harus memanggil metode answerInlineQuery. Metode ini memerlukan dua parameter utama:

  1. inline_query_id: ID kueri yang diterima.
  2. results: Array JSON dari hasil yang akan ditampilkan kepada pengguna.

Setiap hasil dalam array results harus memiliki:

  • type: Jenis hasil (misalnya, article, photo, gif).
  • id: ID unik untuk hasil tersebut (harus berupa string).
  • input_message_content: Konten pesan yang akan dikirim ke obrolan jika pengguna memilih hasil ini.

6.4. Tipe-tipe Hasil Inline

Telegram mendukung berbagai jenis hasil inline. Yang paling umum adalah:

Tipe HasilDeskripsiParameter Wajib
articlePesan teks sederhana.title, input_message_content
photoGambar.photo_url, thumb_url
gifAnimasi GIF.gif_url, thumb_url

Contoh Implementasi Inline Query Handler:

// Dalam skrip webhook.php
// ...
if (isset($update['inline_query'])) {
    $inline_query_id = $update['inline_query']['id'];
    $query_text = $update['inline_query']['query'];
    
    // Logika sederhana: Balas dengan hasil artikel
    $results = [];
    
    // Hasil 1: Echo Teks
    $results[] = [
        'type' => 'article',
        'id' => '1',
        'title' => 'Echo: ' . $query_text,
        'input_message_content' => [
            'message_text' => 'Kamu mengetik: *' . $query_text . '*',
            'parse_mode' => 'Markdown'
        ]
    ];
    
    // Hasil 2: Informasi Penulis
    $results[] = [
        'type' => 'article',
        'id' => '2',
        'title' => 'Tentang Penulis',
        'input_message_content' => [
            'message_text' => "Penulis: Hasanudin H Syafaat\nEmail: banghasan@gmail.com",
            'parse_mode' => 'Markdown'
        ]
    ];
    
    apiRequest('answerInlineQuery', [
        'inline_query_id' => $inline_query_id,
        'results' => json_encode($results), // Array hasil harus di-encode ke JSON
        'cache_time' => 0 // Jangan cache hasil (untuk pengembangan)
    ]);
}
// ...

Bagian III: Membangun Framework Bot Sederhana

Meskipun fungsi apiRequest kita sudah berfungsi, kode bot akan menjadi berantakan dan sulit dikelola seiring bertambahnya fitur. Kita akan menerapkan konsep Pemrograman Berorientasi Objek (OOP) untuk membuat framework sederhana.

Bab 7: Merancang Kelas Bot Sederhana (Simple Framework)

7.1. Konsep Dasar OOP untuk Bot

OOP memungkinkan kita untuk mengelompokkan data (properti) dan fungsi (metode) yang terkait ke dalam sebuah objek (kelas). Dalam kasus bot, kita akan memiliki satu kelas utama yang menangani semua komunikasi dengan Telegram API dan pemrosesan pembaruan.

7.2. Struktur Kelas Utama (SimpleTelegramBot)

Kita akan membuat kelas SimpleTelegramBot yang akan menjadi inti dari bot kita.

<?php
class SimpleTelegramBot {
    protected $token;
    protected $api_url;
    protected $update;

    /**
     * Konstruktor: Inisialisasi token dan URL API
     * @param string $token Token bot dari @BotFather
     */
    public function __construct($token) {
        $this->token = $token;
        $this->api_url = 'https://api.telegram.org/bot' . $this->token . '/';
    }

    /**
     * Metode untuk mendapatkan data pembaruan (Update) dari Webhook
     */
    public function getUpdate() {
        $content = file_get_contents("php://input");
        $this->update = json_decode($content, true);
        return $this->update;
    }

    // ... Metode lain akan ditambahkan di Bab 8
}
?>

7.3. Metode Inti: Wrapper cURL

Kita akan memindahkan fungsi apiRequest ke dalam kelas sebagai metode _request (dengan underscore untuk menandakan bahwa ini adalah metode internal/protected).

    /**
     * Wrapper cURL untuk memanggil metode API Telegram
     * @param string $method Nama metode API
     * @param array $params Parameter yang akan dikirimkan
     * @return array Hasil respons dari API
     */
    protected function _request($method, $params = []) {
        $url = $this->api_url . $method;
        $ch = curl_init();
        
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
        
        $response = curl_exec($ch);
        curl_close($ch);
        
        return json_decode($response, true);
    }

Bab 8: Implementasi Update Handler dan Metode Utama

8.1. Metode isCommand($command) dan getCommand()

Untuk mempermudah penanganan perintah (misalnya, /start, /help), kita tambahkan metode utilitas.

    /**
     * Memeriksa apakah pembaruan saat ini adalah pesan dan dimulai dengan perintah
     * @param string $command Perintah yang dicari (tanpa '/')
     * @return bool
     */
    public function isCommand($command) {
        if (isset($this->update['message']['text'])) {
            $text = $this->update['message']['text'];
            return strtolower($text) === '/' . strtolower($command);
        }
        return false;
    }

    /**
     * Mendapatkan ID Obrolan (Chat ID) dari pembaruan
     * @return int|null
     */
    public function getChatId() {
        if (isset($this->update['message']['chat']['id'])) {
            return $this->update['message']['chat']['id'];
        }
        if (isset($this->update['callback_query']['message']['chat']['id'])) {
            return $this->update['callback_query']['message']['chat']['id'];
        }
        return null;
    }

8.2. Metode Aksi Cepat

Kita buat metode publik yang lebih mudah dibaca untuk fungsi-fungsi API yang sering digunakan.

    /**
     * Mengirim pesan teks
     * @param int $chat_id ID Obrolan tujuan
     * @param string $text Isi pesan
     * @param array $options Opsi tambahan (reply_markup, parse_mode, dll.)
     * @return array Hasil respons API
     */
    public function sendMessage($chat_id, $text, $options = []) {
        $params = array_merge([
            'chat_id' => $chat_id,
            'text' => $text,
            'parse_mode' => 'Markdown'
        ], $options);
        
        return $this->_request('sendMessage', $params);
    }

    /**
     * Mengirim foto
     * @param int $chat_id ID Obrolan tujuan
     * @param string $photo URL atau path file foto
     * @param array $options Opsi tambahan
     * @return array Hasil respons API
     */
    public function sendPhoto($chat_id, $photo, $options = []) {
        $params = array_merge([
            'chat_id' => $chat_id,
            'photo' => $photo
        ], $options);
        
        // Catatan: Untuk upload file lokal, cURL memerlukan penanganan multipart/form-data
        // Untuk framework sederhana ini, kita asumsikan $photo adalah URL atau file_id
        return $this->_request('sendPhoto', $params);
    }
}

8.3. Contoh Penggunaan Framework: Bot Echo dan Perintah Sederhana

Berikut adalah contoh skrip webhook.php yang menggunakan kelas SimpleTelegramBot.

<?php
// File: SimpleTelegramBot.php (berisi definisi kelas di atas)
require_once 'SimpleTelegramBot.php';

// Ganti dengan token bot kamu
$bot_token = 'GANTI_DENGAN_TOKEN_BOT_KAMU';
$bot = new SimpleTelegramBot($bot_token);

// 1. Dapatkan pembaruan
$update = $bot->getUpdate();

// 2. Logika Penanganan Perintah
$chat_id = $bot->getChatId();

if ($chat_id) {
    if ($bot->isCommand('start')) {
        $bot->sendMessage($chat_id, "Selamat datang di Bot Sederhana!\nKetik /echo [pesan] untuk mengulang pesan kamu.");
    } elseif (isset($update['message']['text'])) {
        $text = $update['message']['text'];
        
        // Penanganan perintah /echo
        if (strpos($text, '/echo') === 0) {
            $echo_text = trim(substr($text, 5));
            $bot->sendMessage($chat_id, "Echo: " . $echo_text);
        } else {
            // Echo default
            $bot->sendMessage($chat_id, "Kamu mengirim: " . $text);
        }
    }
}

// 3. Penanganan Callback Query (jika ada)
if (isset($update['callback_query'])) {
    // Logika penanganan callback query di sini
    // ...
}

// Penting: Pastikan skrip selesai tanpa output tambahan
?>

Bab 9: Penutup

9.1. Ringkasan Materi

Ebook ini telah memandu kamu dari dasar-dasar interaksi dengan Telegram Bot API menggunakan PHP dan cURL hingga implementasi fitur-fitur lanjutan seperti Inline Keyboard dan Inline Mode. Puncak dari pembelajaran ini adalah perancangan dan penggunaan kelas SimpleTelegramBot yang menyederhanakan komunikasi API, meletakkan fondasi untuk pengembangan bot yang lebih terstruktur dan mudah dikelola.

9.2. Langkah Selanjutnya

Untuk mengembangkan bot kamu lebih jauh, pertimbangkan langkah-langkah berikut:

  • Database: Integrasikan database (misalnya, MySQL atau PostgreSQL) untuk menyimpan data pengguna, sesi, dan konfigurasi bot.
  • Hosting: Pindahkan bot kamu ke server hosting yang mendukung Webhook (memiliki domain publik dan SSL).
  • Skalabilitas: Untuk bot dengan volume tinggi, pertimbangkan untuk menggunakan queue (antrian) seperti Redis atau RabbitMQ untuk memproses pembaruan secara asinkron.

9.3. Informasi Penulis dan Diskusi

Terima kasih telah membaca ebook ini. Semoga panduan ini bermanfaat dalam perjalanan kamu membangun bot Telegram.

  • Penulis: Hasanudin H Syafaat
  • Email: banghasan@gmail.com
  • Diskusi: Bergabunglah dengan komunitas di @botindonesia untuk berbagi pengetahuan dan mendapatkan bantuan.

Lampiran A: Daftar Metode API Telegram yang Sering Digunakan

MetodeDeskripsiKategori
getMeMenguji token bot dan mendapatkan informasi dasar.Dasar
sendMessageMengirim pesan teks.Pesan
sendPhotoMengirim foto.Pesan
setWebhookMendaftarkan URL Webhook.Updates
deleteWebhookMenghapus Webhook yang terdaftar.Updates
getUpdatesMengambil pembaruan menggunakan Polling.Updates
answerCallbackQueryMenanggapi Callback Query dari Inline Keyboard.Interaktif
editMessageTextMengedit pesan teks yang sudah terkirim.Interaktif
answerInlineQueryMenanggapi kueri dari Inline Mode.Inline

Lampiran B: Contoh Lengkap Kode Webhook Handler

Lihat file SimpleTelegramBot.php dan contoh penggunaan di Bab 8 untuk implementasi Webhook Handler yang lengkap dan terstruktur.


 /**
 * SimpleTelegramBot Class
 * Framework sederhana untuk berinteraksi dengan Telegram Bot API menggunakan cURL.
 * Penulis: Hasanudin H Syafaat
 */

 <?php /**
  * SimpleTelegramBot Class
  * Framework sederhana untuk berinteraksi dengan Telegram Bot API menggunakan cURL.
  * Penulis: Hasanudin H Syafaat
  */
 class SimpleTelegramBot
 {
     protected $token;
     protected $api_url;
     protected $update;

     /**
      * Konstruktor: Inisialisasi token dan URL API
      * @param string $token Token bot dari @BotFather
      */
     public function __construct($token)
     {
         $this->token = $token;
         $this->api_url = "https://api.telegram.org/bot" . $this->token . "/";
     }

     /**
      * Metode untuk mendapatkan data pembaruan (Update) dari Webhook
      */
     public function getUpdate()
     {
         $content = file_get_contents("php://input");
         $this->update = json_decode($content, true);
         return $this->update;
     }

     /**
      * Wrapper cURL untuk memanggil metode API Telegram
      * @param string $method Nama metode API
      * @param array $params Parameter yang akan dikirimkan
      * @return array Hasil respons dari API
      */
     protected function _request($method, $params = [])
     {
         $url = $this->api_url . $method;
         $ch = curl_init();

         curl_setopt($ch, CURLOPT_URL, $url);
         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
         curl_setopt($ch, CURLOPT_POST, true);
         curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));

         $response = curl_exec($ch);
         curl_close($ch);

         return json_decode($response, true);
     }

     /**
      * Memeriksa apakah pembaruan saat ini adalah pesan dan dimulai dengan perintah
      * @param string $command Perintah yang dicari (tanpa '/')
      * @return bool
      */
     public function isCommand($command)
     {
         if (isset($this->update["message"]["text"])) {
             $text = $this->update["message"]["text"];
             return strtolower($text) === "/" . strtolower($command);
         }
         return false;
     }

     /**
      * Mendapatkan ID Obrolan (Chat ID) dari pembaruan
      * @return int|null
      */
     public function getChatId()
     {
         if (isset($this->update["message"]["chat"]["id"])) {
             return $this->update["message"]["chat"]["id"];
         }
         if (isset($this->update["callback_query"]["message"]["chat"]["id"])) {
             return $this->update["callback_query"]["message"]["chat"]["id"];
         }
         return null;
     }

     /**
      * Mengirim pesan teks
      * @param int $chat_id ID Obrolan tujuan
      * @param string $text Isi pesan
      * @param array $options Opsi tambahan (reply_markup, parse_mode, dll.)
      * @return array Hasil respons API
      */
     public function sendMessage($chat_id, $text, $options = [])
     {
         $params = array_merge(
             [
                 "chat_id" => $chat_id,
                 "text" => $text,
                 "parse_mode" => "Markdown",
             ],
             $options,
         );

         return $this->_request("sendMessage", $params);
     }

     /**
      * Mengirim foto
      * @param int $chat_id ID Obrolan tujuan
      * @param string $photo URL atau path file foto
      * @param array $options Opsi tambahan
      * @return array Hasil respons API
      */
     public function sendPhoto($chat_id, $photo, $options = [])
     {
         $params = array_merge(
             [
                 "chat_id" => $chat_id,
                 "photo" => $photo,
             ],
             $options,
         );

         // Catatan: Untuk upload file lokal, cURL memerlukan penanganan multipart/form-data
         // Untuk framework sederhana ini, kita asumsikan $photo adalah URL atau file_id
         return $this->_request("sendPhoto", $params);
     }
 }
?>

  1. PHP Curl dokumentasi resmi PHP Curl

Tutorial PHPTelebot - Panduan Lengkap untuk Pemula

Panduan lengkap ini akan membantumu membuat bot Telegram menggunakan framework PHPTelebot. Tutorial ini dirancang khusus untuk pemula yang baru belajar membuat bot Telegram dengan PHP.

Radyakaze

Daftar Isi


Apa itu PHPTelebot?

PHPTelebot adalah framework PHP yang mempermudah pembuatan bot Telegram. Framework ini menyediakan fungsi-fungsi siap pakai untuk berinteraksi dengan Telegram Bot API, sehingga kamu tidak perlu menulis kode dari nol.

Sejarah

Sejarah-nya euy.. PHPTelebot ini awalnya dibuat pertama kali oleh admin grup Bot PHP Indonesia Sdr. @Radyakaze1

Namun, karena lain satu hal.. repository-nya tidak pernah diupdate, dan dilanjutkan oleh pengembang luar GrayHoax dan sampai tulisan ini dibuat, masih uptodate untuk dipakai di tahun 2025 dan masih aktif.

GrayHoax

Sehingga pada tutorial ini, akan menggunakan repository dari GrayHoax yang merupakan forknya. Lantaran ini juga, kita akan menggunakan metode langsung (tidak pakai composer).

Fitur Utama

  • Mudah digunakan, cocok untuk pemula
  • Mendukung long polling dan webhook
  • Penanganan command yang simpel
  • Dukungan untuk inline keyboard, callback query, dan fitur Telegram lainnya

Mengapa Menggunakan Framework?

🚀 Mengapa Menggunakan Framework daripada Coding Biasa?

Menggunakan framework adalah praktik standar dalam pengembangan perangkat lunak modern karena menawarkan berbagai keuntungan signifikan dibandingkan menulis kode dari nol (vanilla coding). Alasan-alasan ini berpusat pada efisiensi, kualitas, dan pemeliharaan.


1. Peningkatan Produktivitas dan Kecepatan Pengembangan

  • Fungsi Siap Pakai: Frameworks menyediakan komponen dan library yang sudah teruji untuk tugas-tugas umum (misalnya, routing, koneksi database, autentikasi, manajemen session). Ini berarti pengembang tidak perlu “menciptakan kembali roda” dan bisa fokus langsung pada fitur unik aplikasi.
  • Pengembangan Cepat (Rapid Development): Dengan adanya alat bantu bawaan, waktu yang dibutuhkan untuk membuat aplikasi fungsional pertama jauh lebih singkat, memungkinkan Time-to-Market yang lebih cepat.

2. Struktur, Konsistensi, dan Pemeliharaan

  • Struktur Proyek Terstandardisasi: Frameworks memaksakan pola desain tertentu (seperti MVC - Model-View-Controller). Struktur ini membuat proyek terorganisir, konsisten, dan mudah dipahami oleh pengembang mana pun yang familiar dengan framework tersebut.
  • Kemudahan Pemeliharaan (Maintainability): Karena kode mengikuti konvensi framework, menemukan, memperbaiki bug, atau menambahkan fitur baru menjadi lebih mudah. Ini sangat penting untuk proyek jangka panjang.
  • Skalabilitas: Framework sering dirancang dengan mempertimbangkan skalabilitas, menyediakan mekanisme yang lebih baik untuk menangani pertumbuhan aplikasi dan peningkatan beban pengguna.

3. Keamanan dan Keandalan

  • Perlindungan Keamanan Bawaan: Frameworks yang populer terus diperbarui dan menyediakan mitigasi terhadap kerentanan keamanan web yang umum, seperti:
    • SQL Injection
    • Cross-Site Scripting (XSS)
    • Cross-Site Request Forgery (CSRF)
    • Mengimplementasikan perlindungan ini sendiri secara manual sangat kompleks dan rawan kesalahan.
  • Kode yang Teruji: Kode inti framework telah diuji secara ekstensif dan diperbaiki bug-nya oleh komunitas pengembang global, membuatnya jauh lebih andal daripada kode yang ditulis pengembang tunggal dari awal.

4. Dukungan Komunitas dan Ekosistem

  • Dokumentasi dan Bantuan: Frameworks besar (seperti Laravel, React, Django) memiliki dokumentasi yang lengkap dan komunitas pengguna yang besar. Jika Anda menemui masalah, solusinya kemungkinan besar sudah dibahas di forum atau Stack Overflow.
  • Ekosistem yang Kaya: Ada banyak library, plugin, dan tool pihak ketiga yang secara khusus dibuat untuk memperluas fungsionalitas framework, sehingga memudahkan integrasi fitur tambahan.
AspekFrameworkCoding Biasa (Vanilla)
KecepatanCepat, menggunakan fungsionalitas siap pakaiLambat, harus membangun dasar dari nol
Keamanan**Bawaan

Tanpa Framework (PHP + cURL Murni)

Jika kamu menulis bot tanpa framework, kamu harus menulis kode seperti ini setiap kali ingin mengirim pesan:

<?php
$token = "YOUR_BOT_TOKEN";
$chatId = "USER_CHAT_ID";
$message = "Halo dari bot!";

$url = "https://api.telegram.org/bot{$token}/sendMessage";
$data = [
    'chat_id' => $chatId,
    'text' => $message
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

Masalah dengan pendekatan ini:

  • ❌ Kode berulang-ulang (repetitif)
  • ❌ Sulit dibaca dan dipelihara
  • ❌ Rawan error (typo URL, parameter salah, dll)
  • ❌ Harus menulis ulang untuk setiap fitur (keyboard, foto, dokumen, dll)
  • ❌ Tidak ada struktur yang jelas untuk menangani command

Dengan Framework PHPTelebot

Dengan framework, kode yang sama menjadi jauh lebih sederhana:

<?php
require_once 'phptelebot/src/PHPTelebot.php';

$bot = new PHPTelebot('YOUR_BOT_TOKEN');

$bot->cmd('/start', function() {
    return Bot::sendMessage('Halo dari bot!');
});

$bot->run();

Keuntungan menggunakan framework:

  • ✅ Kode lebih ringkas dan mudah dibaca
  • ✅ Fokus pada logika bisnis, bukan detail teknis
  • ✅ Penanganan error sudah diatur oleh framework
  • ✅ Struktur kode lebih terorganisir
  • ✅ Lebih cepat dalam pengembangan
  • ✅ Mudah ditambahkan fitur baru

Prasyarat

Sebelum memulai, pastikan sudah memiliki:

  1. PHP 7.4 atau lebih baru (disarankan PHP 8.0+)

    php -v  # Cek versi PHP
    
  2. Ekstensi cURL aktif

    php -m | grep curl  # Cek apakah cURL sudah aktif
    
  3. Git (untuk mengambil kode dari GitHub)

    git --version  # Cek apakah Git sudah terinstal
    
  4. Token Bot dari BotFather

    • Buka Telegram dan cari @BotFather
    • Kirim perintah /newbot
    • Ikuti instruksi untuk membuat bot baru
    • Simpan token yang diberikan (format: 123456789:ABCdefGHIjklMNOpqrsTUVwxyz)

Instalasi

Langkah 1: Clone Repository

Buka terminal dan jalankan perintah berikut:

# Clone repository PHPTelebot
git clone https://github.com/GrayHoax/phptelebot.git

# Masuk ke folder phptelebot
cd phptelebot

Langkah 2: Struktur Folder

Setelah clone, struktur folder akan seperti ini:

phptelebot/
├── src/
│   └── PHPTelebot.php    # File utama framework
├── examples/              # Contoh-contoh penggunaan
├── README.md
└── ...

File utama yang kita butuhkan ada di src/PHPTelebot.php.


Membuat Bot Sederhana

Langkah 1: Buat File Bot

Buat file baru bernama bot.php di folder yang sama dengan folder phptelebot:

project/
├── phptelebot/           # Folder hasil clone
└── bot.php               # File bot kamu (buat file ini)

Langkah 2: Tulis Kode Bot

Buka bot.php dan tulis kode berikut:

<?php
// Sertakan library PHPTelebot
require_once __DIR__ . '/phptelebot/src/PHPTelebot.php';

// Ganti dengan token bot kamu
$token = 'ISI_TOKEN_BOT_KAMU_DISINI';
$username = 'NamaBotKamu';  // Opsional

// Inisialisasi bot
$bot = new PHPTelebot($token, $username);

// Command /start - Pesan sambutan
$bot->cmd('/start', function () {
    $nama = Bot::$user['first_name'];
    $pesan = "Halo {$nama}! 👋\n\n";
    $pesan .= "Selamat datang di bot saya.\n";
    $pesan .= "Gunakan /help untuk melihat daftar perintah.";
    
    return Bot::sendMessage($pesan);
});

// Command /help - Daftar perintah
$bot->cmd('/help', function () {
    $pesan = "📋 *Daftar Perintah:*\n\n";
    $pesan .= "/start - Mulai bot\n";
    $pesan .= "/help - Tampilkan bantuan\n";
    $pesan .= "/echo [teks] - Ulangi teks yang kamu kirim\n";
    $pesan .= "/info - Informasi tentang kamu";
    
    return Bot::sendMessage($pesan, ['parse' => 'markdown']);
});

// Command /echo - Mengulangi teks
$bot->cmd('/echo|/say', function ($text = '') {
    if (empty($text)) {
        return Bot::sendMessage('❌ Gunakan: /echo [teks yang ingin diulangi]');
    }
    return Bot::sendMessage("🔊 Kamu berkata: {$text}");
});

// Command /info - Informasi user
$bot->cmd('/info', function () {
    $user = Bot::$user;
    $pesan = "👤 *Informasi Kamu:*\n\n";
    $pesan .= "Nama: {$user['first_name']}\n";
    $pesan .= "ID: {$user['id']}\n";
    $pesan .= "Username: @{$user['username']}\n";
    
    return Bot::sendMessage($pesan, ['parse' => 'markdown']);
});

// Handler untuk semua pesan yang tidak cocok dengan command
$bot->cmd('*', function () {
    return Bot::sendMessage("Maaf, saya tidak mengerti perintah itu. Gunakan /help untuk bantuan.");
});

// Jalankan bot
$bot->run();

Langkah 3: Penjelasan Kode

Mari kita pahami setiap bagian kode:

  1. require_once: Memasukkan file library PHPTelebot
  2. new PHPTelebot($token, $username): Membuat instance bot dengan tokenmu
  3. $bot->cmd('/start', function() {...}): Mendefinisikan apa yang terjadi ketika user mengirim /start
  4. Bot::sendMessage($pesan): Mengirim pesan ke user
  5. Bot::$user: Array yang berisi informasi user yang mengirim pesan
  6. $bot->run(): Menjalankan bot (long polling)

Menggunakan Inline Keyboard

Inline keyboard adalah tombol-tombol yang muncul di bawah pesan. Sangat berguna untuk membuat menu interaktif.

Contoh 1: Keyboard Sederhana

<?php
require_once __DIR__ . '/phptelebot/src/PHPTelebot.php';

$token = 'ISI_TOKEN_BOT_KAMU';
$bot = new PHPTelebot($token);

// Command dengan inline keyboard
$bot->cmd('/menu', function () {
    $pesan = "Pilih menu yang kamu inginkan:";
    
    // Membuat inline keyboard
    $keyboard = [
        [
            ['text' => '📰 Berita', 'callback_data' => 'menu_berita'],
            ['text' => '🎵 Musik', 'callback_data' => 'menu_musik']
        ],
        [
            ['text' => '🎮 Game', 'callback_data' => 'menu_game'],
            ['text' => '⚙️ Pengaturan', 'callback_data' => 'menu_setting']
        ]
    ];
    
    return Bot::sendMessage($pesan, [
        'reply_markup' => [
            'inline_keyboard' => $keyboard
        ]
    ]);
});

// Menangani callback dari inline keyboard
$bot->on('callback', function ($data) {
    // $data berisi callback_data yang dikirim
    switch ($data) {
        case 'menu_berita':
            $response = "📰 Kamu memilih menu Berita";
            break;
        case 'menu_musik':
            $response = "🎵 Kamu memilih menu Musik";
            break;
        case 'menu_game':
            $response = "🎮 Kamu memilih menu Game";
            break;
        case 'menu_setting':
            $response = "⚙️ Kamu memilih menu Pengaturan";
            break;
        default:
            $response = "Menu tidak dikenal";
    }
    
    // Kirim notifikasi ke user
    Bot::answerCallback($response, true);
    
    // Update pesan dengan pilihan user
    return Bot::editText($response);
});

$bot->run();

Contoh 2: Keyboard dengan URL

$bot->cmd('/sosmed', function () {
    $pesan = "Kunjungi media sosial kami:";
    
    $keyboard = [
        [
            ['text' => '🌐 Website', 'url' => 'https://example.com']
        ],
        [
            ['text' => '📱 Telegram Channel', 'url' => 'https://t.me/channel']
        ],
        [
            ['text' => '🐦 Twitter', 'url' => 'https://twitter.com/username'],
            ['text' => '📘 Facebook', 'url' => 'https://facebook.com/page']
        ]
    ];
    
    return Bot::sendMessage($pesan, [
        'reply_markup' => [
            'inline_keyboard' => $keyboard
        ]
    ]);
});

Contoh 3: Keyboard Dinamis dengan Pagination

$bot->cmd('/list', function () {
    $items = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5'];
    $page = 1;
    $perPage = 2;
    
    $keyboard = [];
    $start = ($page - 1) * $perPage;
    $end = min($start + $perPage, count($items));
    
    // Tambahkan item ke keyboard
    for ($i = $start; $i < $end; $i++) {
        $keyboard[] = [
            ['text' => $items[$i], 'callback_data' => "item_{$i}"]
        ];
    }
    
    // Tambahkan tombol navigasi
    $navButtons = [];
    if ($page > 1) {
        $navButtons[] = ['text' => '⬅️ Prev', 'callback_data' => 'page_' . ($page - 1)];
    }
    if ($end < count($items)) {
        $navButtons[] = ['text' => 'Next ➡️', 'callback_data' => 'page_' . ($page + 1)];
    }
    if (!empty($navButtons)) {
        $keyboard[] = $navButtons;
    }
    
    return Bot::sendMessage("Daftar Item (Halaman {$page}):", [
        'reply_markup' => [
            'inline_keyboard' => $keyboard
        ]
    ]);
});

Penjelasan Inline Keyboard

  • text: Teks yang ditampilkan pada tombol
  • callback_data: Data yang dikirim ketika tombol ditekan (maksimal 64 byte)
  • url: Link yang akan dibuka ketika tombol ditekan
  • $bot->on('callback', function($data) {...}): Menangani event ketika tombol ditekan
  • Bot::answerCallback(): Mengirim notifikasi popup ke user
  • Bot::editText(): Mengubah teks pesan yang sudah dikirim

Metode Long Polling

Long polling adalah metode di mana bot kamu terus-menerus “bertanya” ke server Telegram apakah ada pesan baru.

Cara Kerja Long Polling

Bot Kamu  →  "Ada pesan baru?"  →  Telegram Server
          ←  "Tidak ada"         ←
          →  "Ada pesan baru?"  →
          ←  "Ya, ada!"         ←
          →  Proses pesan       →
          →  "Ada pesan baru?"  →

Menjalankan Long Polling

# Jalankan bot dengan long polling
php bot.php

Bot akan terus berjalan dan menunggu pesan. Untuk menghentikan, tekan Ctrl+C.

Menjalankan di Background (Linux)

Jika kamu ingin bot tetap berjalan meskipun terminal ditutup:

# Menggunakan nohup
nohup php bot.php > bot.log 2>&1 &

# Atau menggunakan screen
screen -S mybot
php bot.php
# Tekan Ctrl+A lalu D untuk detach

# Kembali ke screen
screen -r mybot

Tutorial penggunaan Screen ada di Setup VPS

Kelebihan dan Kekurangan Long Polling

Kelebihan:

  • ✅ Mudah digunakan, tidak perlu server web
  • ✅ Cocok untuk development dan testing
  • ✅ Tidak perlu SSL certificate

Kekurangan:

  • ❌ Harus selalu running (konsumsi resource)
  • ❌ Tidak cocok untuk production dengan traffic tinggi
  • ❌ Jika script crash, bot akan mati

Metode Webhook

Webhook adalah metode di mana Telegram mengirim pesan langsung ke server Anda setiap kali ada update.

Cara Kerja Webhook

User mengirim pesan  →  Telegram Server  →  Kirim ke URL webhook Anda
                                          →  Bot Anda memproses
                                          ←  Kirim response

Persyaratan Webhook

  1. Server web (Apache/Nginx)
  2. SSL Certificate (HTTPS wajib)
  3. URL publik yang bisa diakses Telegram
  4. PHP dengan cURL

Contoh Kode Webhook

Buat file webhook.php:

<?php
require_once __DIR__ . '/phptelebot/src/PHPTelebot.php';

$token = 'ISI_TOKEN_BOT_ANDA';
$bot = new PHPTelebot($token);

// Definisikan command seperti biasa
$bot->cmd('/start', function () {
    return Bot::sendMessage('Halo! Bot berjalan dengan webhook.');
});

$bot->cmd('/help', function () {
    return Bot::sendMessage('Ini adalah bot dengan webhook.');
});

// Untuk webhook, gunakan method webhook() bukan run()
$bot->webhook();

Set Webhook

Buat file set_webhook.php:

<?php
$token = 'ISI_TOKEN_BOT_ANDA';
$webhookUrl = 'https://domain-anda.com/webhook.php';

$url = "https://api.telegram.org/bot{$token}/setWebhook?url={$webhookUrl}";
$response = file_get_contents($url);

echo $response;

Jalankan sekali:

php set_webhook.php

Cek Status Webhook

<?php
$token = 'ISI_TOKEN_BOT_ANDA';
$url = "https://api.telegram.org/bot{$token}/getWebhookInfo";
$response = file_get_contents($url);

echo $response;

Hapus Webhook

<?php
$token = 'ISI_TOKEN_BOT_ANDA';
$url = "https://api.telegram.org/bot{$token}/deleteWebhook";
$response = file_get_contents($url);

echo $response;

Webhook dengan Ngrok

Ngrok adalah tool yang membuat tunnel dari internet ke localhost Anda. Sangat berguna untuk testing webhook tanpa perlu deploy ke server.

Langkah 1: Install Ngrok

Linux/Mac:

# Download ngrok
wget https://bin.equinox.io/c/bNyj1mQVY4c/ngrok-v3-stable-linux-amd64.tgz

# Extract
tar -xvzf ngrok-v3-stable-linux-amd64.tgz

# Pindahkan ke /usr/local/bin agar bisa diakses global
sudo mv ngrok /usr/local/bin/

Windows:

  1. Download dari https://ngrok.com/download
  2. Extract file ZIP
  3. Jalankan ngrok.exe

Langkah 2: Daftar Akun Ngrok (Gratis)

  1. Buka https://dashboard.ngrok.com/signup
  2. Daftar akun gratis
  3. Dapatkan authtoken dari dashboard
  4. Jalankan:
ngrok config add-authtoken YOUR_AUTHTOKEN

Langkah 3: Setup Server Lokal

Buat file webhook.php di folder web server lokal Anda (misalnya di /var/www/html/ atau htdocs/):

<?php
require_once __DIR__ . '/phptelebot/src/PHPTelebot.php';

$token = 'ISI_TOKEN_BOT_ANDA';
$bot = new PHPTelebot($token);

$bot->cmd('/start', function () {
    return Bot::sendMessage('Halo! Bot berjalan dengan Ngrok webhook.');
});

$bot->cmd('/test', function () {
    $pesan = "✅ Webhook berfungsi dengan baik!\n";
    $pesan .= "Server: " . $_SERVER['HTTP_HOST'];
    return Bot::sendMessage($pesan);
});

// Gunakan webhook() untuk mode webhook
$bot->webhook();

Langkah 4: Jalankan Web Server Lokal

Menggunakan PHP Built-in Server:

# Masuk ke folder project
cd /path/to/project

# Jalankan server di port 8000
php -S localhost:8000

Atau menggunakan Apache/Nginx:

Pastikan web server Anda sudah running dan file webhook.php bisa diakses.

Langkah 5: Jalankan Ngrok

Buka terminal baru dan jalankan:

# Untuk PHP built-in server (port 8000)
ngrok http 8000

# Untuk Apache/Nginx (biasanya port 80)
ngrok http 80

Anda akan melihat output seperti ini:

ngrok

Session Status                online
Account                       your@email.com
Version                       3.x.x
Region                        Asia Pacific (ap)
Latency                       -
Web Interface                 http://127.0.0.1:4040
Forwarding                    https://abc123.ngrok.io -> http://localhost:8000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00

Penting: Salin URL HTTPS (misalnya https://abc123.ngrok.io)

Langkah 6: Set Webhook ke Telegram

Buat file set_webhook_ngrok.php:

<?php
$token = 'ISI_TOKEN_BOT_ANDA';

// Ganti dengan URL ngrok Anda (HARUS HTTPS)
$ngrokUrl = 'https://abc123.ngrok.io';
$webhookUrl = $ngrokUrl . '/webhook.php';

$url = "https://api.telegram.org/bot{$token}/setWebhook?url=" . urlencode($webhookUrl);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);

if ($result['ok']) {
    echo "✅ Webhook berhasil diset!\n";
    echo "URL: {$webhookUrl}\n";
} else {
    echo "❌ Gagal set webhook:\n";
    echo $response . "\n";
}

Jalankan:

php set_webhook_ngrok.php

Langkah 7: Test Bot

  1. Buka Telegram dan cari bot Anda
  2. Kirim /start atau /test
  3. Bot akan merespons melalui webhook

Langkah 8: Monitor Request (Opsional)

Ngrok menyediakan web interface untuk melihat semua request:

  1. Buka browser
  2. Akses http://127.0.0.1:4040
  3. Anda bisa melihat semua request yang masuk dari Telegram

Troubleshooting Ngrok

Bot tidak merespons:

  1. Cek apakah ngrok masih running
  2. Cek apakah PHP server masih running
  3. Cek webhook info:
curl https://api.telegram.org/botYOUR_TOKEN/getWebhookInfo
  1. Lihat error di ngrok web interface (http://127.0.0.1:4040)

URL ngrok berubah:

  • URL ngrok gratis akan berubah setiap kali Anda restart
  • Anda harus set webhook ulang dengan URL baru
  • Untuk URL tetap, upgrade ke ngrok berbayar

Webhook tidak menerima update:

# Hapus webhook
curl https://api.telegram.org/botYOUR_TOKEN/deleteWebhook

# Set ulang
php set_webhook_ngrok.php

Tips Ngrok

  1. Jangan tutup terminal ngrok - Jika ditutup, tunnel akan mati
  2. URL berubah setiap restart - Catat URL baru dan set webhook ulang
  3. Gunakan HTTPS - Telegram hanya menerima webhook HTTPS
  4. Monitor di web interface - Sangat membantu untuk debugging

Tips dan Troubleshooting

Tips Umum

  1. Simpan token dengan aman

    • Jangan commit token ke Git
    • Gunakan file .env atau config terpisah
    // config.php
    <?php
    return [
        'token' => 'YOUR_BOT_TOKEN'
    ];
    
    // bot.php
    $config = require 'config.php';
    $bot = new PHPTelebot($config['token']);
    
  2. Logging untuk debugging

    // Tambahkan logging
    file_put_contents('bot.log', date('Y-m-d H:i:s') . " - " . json_encode(Bot::$update) . "\n", FILE_APPEND);
    
  3. Gunakan try-catch

    $bot->cmd('/start', function () {
        try {
            // Kode Anda
            return Bot::sendMessage('Halo!');
        } catch (Exception $e) {
            error_log($e->getMessage());
            return Bot::sendMessage('Terjadi kesalahan.');
        }
    });
    

Troubleshooting

Bot tidak merespons:

  1. Cek token sudah benar
  2. Cek koneksi internet
  3. Cek apakah script berjalan tanpa error
  4. Untuk webhook: cek apakah URL bisa diakses dari luar

Error “Call to undefined function curl_init”:

# Ubuntu/Debian
sudo apt install php-curl

# CentOS/RHEL
sudo yum install php-curl

# Restart web server
sudo service apache2 restart

Webhook tidak berfungsi:

# Cek status webhook
curl https://api.telegram.org/botYOUR_TOKEN/getWebhookInfo

# Hapus webhook jika ada masalah
curl https://api.telegram.org/botYOUR_TOKEN/deleteWebhook

# Set ulang
curl -X POST https://api.telegram.org/botYOUR_TOKEN/setWebhook?url=YOUR_WEBHOOK_URL

Long polling error “Conflict: terminated by other getUpdates”:

  • Ada instance lain yang running
  • Atau webhook masih aktif
  • Solusi: Hapus webhook dengan deleteWebhook

Referensi

Dokumentasi Telegram

  1. Telegram Bot API Official

  2. Telegram Bot Features

  3. Telegram Bot Tutorial

  4. Inline Keyboards

  5. Webhooks Guide

Dokumentasi PHP

  1. PHP cURL

  2. PHP JSON

  3. PHP File Handling

Framework PHPTelebot

  1. PHPTelebot GitHub

  2. PHPTelebot Examples

Tools Pendukung

  1. Ngrok

  2. BotFather

    • @BotFather
    • Bot untuk membuat dan manage bot Telegram
  3. Telegram API Testing

Komunitas dan Bantuan

  1. Telegram Bot Indonesia

  2. Stack Overflow

  3. PHP Indonesia

    • @phpid
    • Komunitas PHP Indonesia

Penutup

Selamat! Kita telah mempelajari cara membuat bot Telegram menggunakan PHPTelebot. Mulai dari instalasi, membuat bot sederhana, menggunakan inline keyboard, hingga setup webhook dengan Ngrok.

Langkah selanjutnya:

  • Eksplorasi fitur-fitur lain di dokumentasi Telegram Bot API
  • Pelajari cara mengirim foto, video, dan dokumen
  • Implementasikan database untuk menyimpan data user
  • Buat bot yang lebih kompleks dengan state management

Jika ada pertanyaan atau menemui masalah, jangan ragu untuk bertanya di komunitas atau membuka issue di repository PHPTelebot.

Selamat coding! 🚀


  1. https://github.com/radyakaze/ yakni Sdr. Pringgo Radianto alias Radyakaze, merupakan developer PHP untuk PHPTelebot pertama.

Membangun Bot Telegram dengan Google Apps Script dan Lumpia Framework

Dari Pemula Hingga Lanjutan

MetadataDetail
Penulis (Author)Hasanudin H Syafaat
Emailbanghasan@gmail.com
Diskusi (Discussion)@botIndonesia
Tanggal Publikasi29 November 2025

Cover GAS Ebook

Bab 1: Pendahuluan - Mengapa GAS dan Lumpia?

Selamat datang di panduan komprehensif untuk membangun bot Telegram yang kuat dan fungsional menggunakan Google Apps Script (GAS) dan Lumpia Framework (dikenal juga sebagai TelegramBotIndonesia Library v3) 1. Tulisan ini dirancang untuk membawamu dari nol, bahkan jika kamu belum pernah menyentuh kode sebelumnya, hingga mampu menciptakan bot dengan fitur-fitur canggih.

1.1 Latar Belakang

Di era digital saat ini, otomasi dan interaksi berbasis chat menjadi semakin penting. Bot Telegram telah menjadi solusi populer untuk berbagai kebutuhan, mulai dari layanan pelanggan, notifikasi otomatis, hingga sistem informasi interaktif. Namun, banyak pengembang pemula menghadapi kendala dalam membangun bot karena:

  1. Biaya Hosting: Kebanyakan tutorial bot memerlukan server berbayar atau VPS yang tidak terjangkau untuk pemula atau proyek skala kecil.
  2. Kompleksitas Teknis: Berinteraksi langsung dengan Telegram Bot API 2 memerlukan pemahaman mendalam tentang HTTP requests, webhook, dan penanganan JSON yang rumit.
  3. Keterbatasan Sumber Daya: Tidak semua orang memiliki akses ke infrastruktur cloud atau pengetahuan DevOps untuk deployment.

Google Apps Script hadir sebagai solusi yang mengatasi semua kendala tersebut. Dengan infrastruktur Google yang gratis dan andal, serta Lumpia Framework yang menyederhanakan kompleksitas API, siapa pun dapat membangun bot Telegram profesional tanpa biaya hosting dan dengan kurva pembelajaran yang lebih landai.

1.2 Untuk Siapa Buku Ini?

Buku ini dirancang dengan pendekatan bertahap untuk mengakomodasi berbagai tingkat keahlian:

🎯 Pemula Absolut (Belum Pernah Coding)

Jika kamu belum pernah menulis kode sebelumnya, jangan khawatir! Buku ini akan memandu kamu langkah demi langkah, dimulai dari konsep paling dasar.

Kamu akan belajar:

Tip

  • Cara mendapatkan token bot dari BotFather
  • Memahami struktur kode JavaScript sederhana
  • Membuat bot pertama yang dapat merespons perintah dasar
  • Konsep fundamental seperti variabel, fungsi, dan objek

💡 Pemula dengan Pengetahuan Dasar Programming

Jika kamu sudah familiar dengan konsep dasar programming (variabel, fungsi, kondisional).

Note

  • Bisa melewati penjelasan konsep dasar dan fokus pada implementasi
  • Langsung memahami struktur handler dan middleware
  • Mengeksplorasi fitur-fitur menengah seperti keyboard interaktif dan manajemen sesi

🚀 Developer Berpengalaman

Bagi kamu yang sudah terbiasa dengan JavaScript atau framework bot lain (seperti Telegraf, python-telegram-bot), buku ini akan membantumu:

Important

  • Memahami perbedaan dan keunikan Google Apps Script
  • Memanfaatkan integrasi ekosistem Google (Sheets, Drive, Gmail)
  • Mengoptimalkan bot dengan middleware dan arsitektur yang scalable
  • Mengatasi limitasi GAS dengan teknik-teknik advanced

1.3 Apa Itu Bot Telegram?

Bot Telegram adalah akun khusus yang tidak memerlukan nomor telepon tambahan untuk disiapkan. Bot ini berfungsi sebagai antarmuka terprogram yang memungkinkan pengguna berinteraksi dengan layanan eksternal melalui aplikasi Telegram. Bot dapat melakukan berbagai tugas, seperti mengirim pesan, gambar, dan file, mengelola grup, hingga berintegrasi dengan database atau layanan web lainnya.

1.4 Mengapa Google Apps Script (GAS)?

Google Apps Script adalah platform pengembangan berbasis JavaScript yang memungkinkan kamu mengotomatisasi, mengintegrasikan, dan memperluas produk Google seperti Google Sheets, Docs, dan Drive.

Ada beberapa alasan kuat mengapa GAS menjadi pilihan ideal untuk hosting bot Telegram, terutama bagi pemula:

  1. Gratis dan Tanpa Server: kamu tidak perlu menyewa Virtual Private Server (VPS) atau layanan cloud berbayar. GAS berjalan di infrastruktur Google secara gratis (dengan batasan harian yang sangat besar untuk penggunaan pribadi).
  2. Integrasi Google yang Mudah: Botmu dapat dengan mudah membaca dan menulis data ke Google Sheets, mengirim email melalui Gmail, atau mengelola file di Google Drive.
  3. Kemudahan Deployment: Proses deployment bot Telegram di GAS sangat sederhana, hanya dengan mempublikasikan skrip sebagai aplikasi web (Web App).

Limitasi Penggunaan Google Apps Script

Di balik kemudahannya, GAS memiliki kuota dan batas teknis yang perlu diingat agar bot tetap andal:

  • Durasi Eksekusi: Setiap pemanggilan fungsi (termasuk doPost) dibatasi sekitar 6 menit untuk akun individu; jika logika bot terlalu berat, eksekusi akan dihentikan otomatis.
  • Total Waktu Harian: Jumlah total runtime skrip dibatasi ±90 menit per hari untuk akun standar, sehingga lonjakan trafik dapat menghentikan bot hingga kuota direset.
  • Permintaan Eksternal: Kuota UrlFetchApp (metode yang digunakan Lumpia untuk memanggil Telegram API) sekitar 20.000 permintaan per hari; melebihi angka ini akan menimbulkan error Exception: Service invoked too many times.
  • Respon dan Payload: Ukuran respons Web App dibatasi ±50 MB dan ukuran request POST dibatasi agar server GAS tetap stabil; kiriman file besar tidak akan diterima.

Jika kebutuhan proyek melampaui batas tersebut, pertimbangkan untuk memecah beban kerja, menggunakan cache, atau memigrasikan bot ke platform serverless lain. Detail kuota selalu diperbarui dalam dokumentasi resmi Google Apps Script 3.

1.5 Mengenal Lumpia Framework (TelegramBotIndonesia Library)

Meskipun Telegram menyediakan API yang kuat, berinteraksi langsung dengannya menggunakan GAS bisa menjadi rumit. Di sinilah Lumpia Framework berperan.

Lumpia Framework adalah wrapper atau pustaka pihak ketiga yang dibuat khusus untuk Google Apps Script, menyederhanakan interaksi dengan Telegram Bot API. Dengan Lumpia, kamu dapat menulis kode bot yang lebih bersih, terstruktur, dan mudah dipelihara, mirip dengan framework bot populer lainnya seperti Telegraf atau Node-Telegram-Bot-API.

Keunggulan Utama Lumpia:

  • Penanganan Update yang Mudah: Lumpia menyediakan middleware dan handler yang intuitif untuk merespons berbagai jenis pesan (perintah, teks, gambar, dll.).
  • Context Object (ctx): Setiap pembaruan pesan dibungkus dalam objek ctx yang kaya informasi, memungkinkan kamu merespons dengan cepat dan mengakses data pesan dengan mudah.
  • Dukungan Penuh Fitur Telegram: Mulai dari Inline Keyboard, Reply Keyboard, hingga manajemen sesi, semua didukung dengan baik.

Materi lengkap dan videonya tersedia pada situs Lumpia Framework

1.6 Apa yang Perlu Dipersiapkan?

Sebelum memulai perjalanan membangun bot Telegram, pastikan kamu telah menyiapkan hal-hal berikut:

✅ Akun dan Akses

  1. Akun Telegram Aktif

    • Pastikan kamu memiliki aplikasi Telegram yang terinstal di smartphone atau desktop
    • Akun harus dapat mengakses @BotFather untuk membuat bot baru
  2. Akun Google

    • Diperlukan untuk mengakses Google Apps Script
    • Pastikan kamu dapat login ke Google Drive
    • Tidak memerlukan akun berbayar, akun Gmail gratis sudah cukup

🛠️ Pengetahuan Dasar

Opsional tapi Direkomendasikan

  1. Pemahaman JavaScript Dasar

    • Variabel dan tipe data
    • Fungsi dan arrow function (=>)
    • Objek dan array
    • Jika belum familiar, jangan khawatir! Buku ini akan menjelaskan setiap konsep yang digunakan.
  2. Konsep HTTP dan API (Akan Dipelajari)

    • kamu tidak perlu memahami ini sebelumnya
    • Buku ini akan menjelaskan konsep webhook dan API secara bertahap

📋 Checklist Persiapan Teknis

Sebelum masuk ke Bab 2, pastikan kamu sudah:

  • Memiliki akses ke aplikasi Telegram
  • Dapat login ke Google Drive dengan akun Google kamu
  • Memiliki koneksi internet yang stabil
  • Menyiapkan browser modern (Chrome, Firefox, Edge, atau Safari)
  • Menyiapkan text editor atau notepad untuk mencatat token dan URL (opsional)

💡 Tips Sebelum Memulai

Untuk Pemula Jangan terburu-buru. Ikuti setiap langkah dengan teliti dan jangan ragu untuk mencoba kode berkali-kali. Kesalahan adalah bagian dari proses belajar!

Untuk Developer Berpengalaman Meskipun kamu familiar dengan JavaScript, perhatikan perbedaan dan limitasi Google Apps Script dibandingkan dengan Node.js atau environment JavaScript lainnya.

Untuk Semua Simpan token bot kamu dengan aman dan jangan pernah membagikannya di tempat publik (GitHub, forum, dll). Token adalah kunci penuh kontrol atas botmu.


Bab 2: Persiapan Awal - BotFather dan GAS

Sebelum menulis kode, ada dua hal penting yang harus kamu siapkan: token bot dari Telegram dan proyek Google Apps Script.

2.1 Langkah 1: Mendapatkan Token Bot dari BotFather

BotFather adalah bot resmi Telegram yang digunakan untuk membuat dan mengelola bot-bot lainnya.

  1. Buka aplikasi Telegram kamu dan cari @BotFather.
  2. Ketik perintah /newbot dan ikuti instruksi.
  3. Pilih nama untuk bot kamu (misalnya, “Bot Ebook Saya”).
  4. Pilih username untuk bot kamu (harus diakhiri dengan “bot”, misalnya, “ebook_bot_saya_bot”).
  5. Setelah berhasil, BotFather akan memberikan kamu HTTP API Token. Simpan token ini dengan aman, karena ini adalah kunci untuk mengontrol bot kamu.

Caution

Penting: Token bot kamu akan terlihat seperti ini: 123456789:ABC-DEF1234ghIkl-Jkl-Lmn-Opq-Rst-Uvwxyz. JANGAN pernah membagikan token ini kepada siapapun.

2.2 Langkah 2: Membuat Proyek Google Apps Script

  1. Buka Google Drive kamu.
  2. Klik Baru -> Lainnya -> Google Apps Script. Ini akan membuka editor GAS baru.
  3. Beri nama proyeknya (misal: “TelegramBotLumpia”).

2.3 Langkah 3: Menambahkan Lumpia Framework (Library)

Lumpia Framework ditambahkan ke proyek GAS kamu sebagai Library eksternal.

  1. Di editor GAS, klik ikon Libraries (biasanya ikon buku di panel kiri).
  2. Di bagian “Add a library”, masukkan ID Library Lumpia Framework: 1Yo6vQRwjG5Gl9jeEF0g2tBTUa0XN5MyT4G_HeDpRr9DvabxhRcSdhPNj4
  3. Klik Look up.
  4. Pilih versi terbaru (disarankan versi stabil, biasanya angka terbesar).
  5. Pastikan Identifier adalah lumpia (ini adalah nama variabel yang akan kamu gunakan dalam kode).
  6. Klik Add.

Sekarang, proyek kamu sudah siap untuk menerima kode bot.


Bab 3: Bot Pertamamu - Hello World

Di bab ini, kita akan membuat bot paling dasar yang dapat merespons perintah /start dan /ping.

3.1 Struktur Kode Dasar

Setiap bot Telegram yang di-host di Google Apps Script harus memiliki dua komponen utama: fungsi doPost(e) dan inisiasi bot.

3.1.1 Fungsi doPost(e)

Fungsi ini adalah entry point (titik masuk) untuk semua komunikasi dari Telegram ke bot kamu. Ketika pengguna mengirim pesan, Telegram akan mengirimkan data pesan tersebut ke URL Web App kamu melalui metode HTTP POST. Data ini diterima oleh GAS dalam parameter e.

// handle komunikasi via POST dari Telegram ke (webhook) GAS
function doPost(e) {
  bot.doPost(e);
}

3.1.2 Inisiasi Bot

Kamu perlu menginisiasi Lumpia Framework dengan token bot kamu.

// Ganti dengan token bot kamu yang sebenarnya
const token = "TOKEN_BOT_KAMU_DI_SINI";

// Inisiasi Lumpia Framework
const bot = new lumpia.init(token);

3.2 Menambahkan Handler Perintah

Lumpia Framework menggunakan konsep handler untuk merespons berbagai jenis pesan.

Metode HandlerDeskripsiContoh Penggunaan
bot.start(callback)Merespons perintah /start.bot.start(ctx => ctx.reply('Selamat datang!'));
bot.cmd(command, callback)Merespons perintah kustom (misalnya, /ping).bot.cmd('ping', ctx => ctx.replyIt('Pong!'));
bot.hears(regex, callback)Merespons pesan teks yang cocok dengan pola regular expression.bot.hears(/halo/i, ctx => ctx.reply('Halo juga!'));

Kode Lengkap Bot Pertama

// Ganti dengan token bot kamu yang sebenarnya
const token = "TOKEN_BOT_KAMU_DI_SINI";

// Inisiasi Lumpia Framework
const bot = new lumpia.init(token);

// 1. Handler untuk perintah /start
bot.start((ctx) => {
  // ctx.reply() adalah metode cepat untuk membalas pesan
  ctx.reply(
    "Halo! Saya adalah bot pertama kamu yang dibuat dengan Lumpia Framework.",
  );
});

// 2. Handler untuk perintah /ping
bot.cmd("ping", (ctx) => {
  // ctx.replyIt() adalah alias untuk ctx.reply()
  ctx.replyIt("Pong!");
});

// 3. Handler untuk pesan teks "apa kabar" (case insensitive)
bot.hears(/apa kabar/i, (ctx) => {
  ctx.reply("Saya baik, terima kasih sudah bertanya!");
});

// handle komunikasi via POST dari Telegram ke (webhook) GAS
function doPost(e) {
  bot.doPost(e);
}

3.3 Deployment dan Webhook

Setelah kode selesai, kamu perlu mendeploy skrip sebagai Aplikasi Web dan mengatur webhook agar Telegram tahu ke mana harus mengirim pesan.

3.3.1 Deployment (Penerbitan)

  1. Di editor GAS, klik Deploy -> New deployment.
  2. Pilih Type sebagai Web app.
  3. Isi deskripsi (misalnya, “Versi 1.0”).
  4. Pada bagian Execute as, pilih Me (akun kamu).
  5. Pada bagian Who has access, pilih Anyone.
  6. Klik Deploy.
  7. GAS akan memberikan kamu Web app URL. Salin URL ini.

Important

Penting: Saat pertama kali menjalankan fungsi yang mengakses layanan Google (seperti SpreadsheetApp), GAS akan meminta kamu untuk memberikan izin (Authorization). Kamu harus menyetujui izin ini agar bot dapat berfungsi.

Petunjuk dalam gambar:

3.3.2 Set Webhook

Webhook adalah mekanisme di mana Telegram akan “memanggil” URL Web App kamu setiap kali ada pesan baru.

Buat fungsi baru di GAS untuk mengatur webhook:

function setWebHook() {
  // Ganti dengan URL Web App yang kamu dapatkan dari langkah deployment
  const webAppUrl = "URL_WEB_APP_KAMU_DI_SINI";

  // Lumpia menyediakan metode setWebhook yang mudah
  let result = bot.telegram.setWebhook(webAppUrl);

  // Tampilkan hasil di log untuk memastikan berhasil
  Logger.log(result);
}
  1. Ganti URL_WEB_APP_KAMU_DI_SINI dengan URL Web App kamu.
  2. Pilih fungsi setWebHook di menu dropdown di atas editor kode.
  3. Klik Run.
  4. Periksa Execution log (Log Eksekusi) untuk memastikan hasilnya sukses.

Bot kamu sekarang sudah aktif! Coba kirim /start atau /ping di Telegram.


Bab 4: Fitur Menengah - Context dan Keyboard

Setelah bot dasar kamu berjalan, mari kita jelajahi fitur-fitur Lumpia yang lebih canggih.

4.1 Objek Context (ctx)

Setiap handler (seperti bot.cmd atau bot.hears) menerima objek ctx (Context) sebagai argumen. Objek ini adalah jantung dari Lumpia Framework, berisi semua informasi tentang pesan yang masuk dan menyediakan metode cepat untuk merespons.

Properti/Metode ctxDeskripsi
ctx.updateObjek mentah dari Telegram API yang berisi seluruh data pesan.
ctx.messageObjek pesan yang masuk.
ctx.fromObjek pengguna yang mengirim pesan.
ctx.chat.idID unik dari obrolan (penting untuk mengirim balasan).
ctx.reply(text)Metode cepat untuk membalas pesan.
ctx.replyIt(text)Alias dari ctx.reply(text).
ctx.matchHasil pencocokan dari bot.hears (jika menggunakan regex).

Contoh Penggunaan ctx

bot.cmd("siapa", (ctx) => {
  const namaPengirim = ctx.from.first_name;
  const chatId = ctx.chat.id;

  ctx.reply(`Halo ${namaPengirim}! ID Chat kamu adalah ${chatId}.`);
});

// Contoh menangkap teks setelah perintah /say
bot.hears(/^\/say (.*)/i, (ctx) => {
  // ctx.match[1] berisi teks yang ditangkap oleh regex group pertama
  const teksYangDiucapkan = ctx.match[1];
  ctx.reply(`Kamu mengatakan: ${teksYangDiucapkan}`);
});

4.2 Keyboard Kustom

Telegram mendukung dua jenis keyboard yang sangat berguna untuk interaksi pengguna: Reply Keyboard dan Inline Keyboard.

4.2.1 Reply Keyboard (Keyboard Balasan)

Keyboard ini menggantikan keyboard bawaan Telegram dan sangat cocok untuk menu utama.

bot.cmd("menu", (ctx) => {
  const keyboard = [
    ["Pilihan A", "Pilihan B"],
    ["Bantuan", "Kembali ke Awal"],
  ];

  // Menggunakan metode replyKeyboard dari Lumpia
  ctx.reply("Silakan pilih menu:", lumpia.replyKeyboard(keyboard));
});

// Menangani respons dari tombol Reply Keyboard
bot.hears("Pilihan A", (ctx) => ctx.reply("Kamu memilih Pilihan A."));

4.2.2 Inline Keyboard (Keyboard Sebaris)

Keyboard ini muncul tepat di bawah pesan bot dan sangat cocok untuk aksi spesifik. Ketika tombol Inline Keyboard diklik, bot menerima callback query alih-alih pesan teks.

bot.cmd("aksi", (ctx) => {
  const inlineKeyboard = [
    [{ text: "Klik Saya", callback_data: "data_klik_saya" }],
    [{ text: "Kunjungi Google", url: "https://google.com" }],
  ];

  // Menggunakan metode inlineKeyboard dari Lumpia
  ctx.reply("Pilih aksi di bawah ini:", lumpia.inlineKeyboard(inlineKeyboard));
});

// Menangani Callback Query dari Inline Keyboard
bot.on("callback_query", (ctx) => {
  const data = ctx.update.callback_query.data;

  if (data === "data_klik_saya") {
    // Lumpia menyediakan ctx.answerCbQuery untuk notifikasi pop-up
    ctx.answerCbQuery("Tombol berhasil diklik!", true);

    // Mengedit pesan yang memiliki Inline Keyboard
    ctx.telegram.editMessageText(
      ctx.chat.id,
      ctx.update.callback_query.message.message_id,
      "Pesan ini sudah diubah setelah tombol diklik.",
    );
  }
});

Bab 5: Fitur Mahir - Middleware dan Integrasi GAS

Di bab terakhir ini, kita akan membahas fitur-fitur yang akan membawa bot kamu ke tingkat yang lebih profesional, termasuk manajemen sesi dan integrasi dengan layanan Google.

5.1 Middleware: Memproses Pesan Sebelum Handler

Middleware adalah fungsi yang dijalankan sebelum handler utama kamu. Ini sangat berguna untuk tugas-tugas seperti otentikasi, logging, atau manajemen sesi. Lumpia menggunakan metode bot.use(callback) untuk menambahkan middleware.

Setiap middleware harus memanggil next() untuk meneruskan kontrol ke middleware atau handler berikutnya.

Contoh Middleware untuk Logging

// Middleware untuk mencatat setiap pesan yang masuk
bot.use((ctx, next) => {
  const user = ctx.from.first_name || "Pengguna";
  const pesan = ctx.message.text || "Non-teks";

  Logger.log(`[LOG] Pesan dari ${user}: ${pesan}`);

  // Lanjutkan ke handler berikutnya
  next();
});

// Handler ini hanya akan dijalankan setelah middleware logging selesai
bot.cmd("info", (ctx) => ctx.reply("Logging berhasil dilakukan."));

5.2 Manajemen Sesi (State Management)

Untuk membuat bot yang dapat melakukan percakapan multi-langkah (misalnya, mengisi formulir), kamu perlu menyimpan state atau sesi pengguna. Lumpia Framework memfasilitasi ini melalui objek ctx.session.

Secara default, Lumpia menyimpan sesi di properti ctx.session yang dapat kamu atur. Untuk menyimpan sesi secara persisten (misalnya, di Google Sheets atau Cache Service), kamu perlu mengimplementasikan logika penyimpanan kamu sendiri di middleware.

Contoh Sesi Sederhana (Menggunakan Properti ctx.session)

// Middleware untuk inisiasi sesi (jika belum ada)
bot.use((ctx, next) => {
  // Lumpia secara otomatis menyediakan objek sesi
  if (!ctx.session) {
    ctx.session = {};
  }
  next();
});

bot.cmd("tanya", (ctx) => {
  ctx.session.state = "menunggu_nama"; // Atur state pengguna
  ctx.reply("Siapa namamu?");
});

// Handler untuk menangani pesan teks
bot.hears(/.*/, (ctx) => {
  if (ctx.session.state === "menunggu_nama") {
    const nama = ctx.message.text;
    ctx.session.nama = nama;
    ctx.session.state = "menunggu_usia";
    ctx.reply(`Halo, ${nama}. Berapa usia kamu?`);
  } else if (ctx.session.state === "menunggu_usia") {
    const usia = ctx.message.text;
    ctx.session.state = null; // Sesi selesai
    ctx.reply(`Terima kasih, ${ctx.session.nama}. Usia kamu ${usia} tahun.`);
  } else {
    // Balasan default jika tidak ada sesi aktif
    ctx.reply("Saya tidak mengerti. Ketik /tanya untuk memulai sesi.");
  }
});

Catatan: Untuk bot yang kompleks, disarankan untuk mengintegrasikan manajemen sesi dengan Google Sheets atau Cache Service GAS agar data sesi tetap tersimpan meskipun bot di-deploy ulang.

5.3 Integrasi dengan Google Sheets

Salah satu kekuatan terbesar GAS adalah integrasinya dengan Google Sheets. Kamu dapat menggunakan bot kamu untuk mencatat data pengguna, membuat log, atau bahkan berfungsi sebagai antarmuka database.

Contoh Mencatat Data ke Google Sheets

Asumsikan kamu memiliki Google Sheet dengan URL: SHEET_URL_KAMU dan nama sheet: Data Log.

// Fungsi untuk mencatat log ke Google Sheet
function logToSheet(data) {
  const sheetId = "ID_GOOGLE_SHEET_KAMU"; // Ambil ID dari URL Sheet
  const sheet = SpreadsheetApp.openById(sheetId).getSheetByName("Data Log");

  // Tambahkan baris baru dengan data
  sheet.appendRow(data);
}

bot.cmd("catat", (ctx) => {
  const timestamp = new Date();
  const userId = ctx.from.id;
  const username = ctx.from.username || "N/A";
  const messageText = ctx.message.text;

  // Data yang akan dicatat
  const dataLog = [timestamp, userId, username, messageText];

  try {
    logToSheet(dataLog);
    ctx.reply("Pesan kamu berhasil dicatat ke Google Sheet!");
  } catch (e) {
    ctx.reply(
      "Gagal mencatat data. Pastikan kamu sudah memberikan izin akses ke Google Sheet.",
    );
    Logger.log(e);
  }
});

Integrasi dengan miniSheetDBv2

Untuk mempermudah pengelolaan data di Google Sheet, kamu dapat mengintegrasikan bot dengan Library miniSheetDBv2. Library ini menyediakan abstraksi tingkat tinggi yang sangat menyederhanakan operasi database menggunakan Google Sheets sebagai backend.

Rekomendasi

Penulis sangat merekomendasikan penggunaan Library miniSheetDBv2 5 karena beberapa alasan:

  • Operasi CRUD yang Mudah: Menyediakan metode sederhana untuk Create, Read, Update, dan Delete data tanpa perlu menulis kode SpreadsheetApp yang kompleks
  • Penanganan Tipe Data Otomatis: Secara otomatis mengkonversi data antara format JavaScript dan Google Sheets
  • Query yang Fleksibel: Mendukung pencarian dan filtering data dengan sintaks yang intuitif, mirip dengan database NoSQL
  • Performa Optimal: Menggunakan caching dan batch operations untuk mengurangi API calls dan mempercepat eksekusi
  • Dokumentasi Lengkap: Dilengkapi dengan contoh kode dan tutorial dalam Bahasa Indonesia

Penutup dan Sumber Daya Lanjutan

Selamat Kita telah mempelajari dasar-dasar hingga fitur mahir dalam membangun bot Telegram menggunakan Google Apps Script dan Lumpia Framework.

Ringkasan Pembelajaran

LevelKonsep KunciMetode Lumpia yang Dipelajari
PemulaSetup GAS, Token Bot, Webhooklumpia.init(), doPost(e), bot.start(), bot.cmd(), ctx.reply()
MenengahContext, Regex, Keyboard Interaktifctx.from, ctx.chat.id, bot.hears(), lumpia.replyKeyboard(), lumpia.inlineKeyboard(), bot.on('callback_query')
MahirPercakapan Multi-langkah, Logging, Integrasibot.use(), ctx.session, Integrasi SpreadsheetApp

Sumber Daya Lanjutan

Untuk terus mengembangkan kemampuan bot kamu, kami merekomendasikan sumber daya berikut:

  1. Dokumentasi Resmi Lumpia Framework1: Selalu periksa dokumentasi resmi untuk metode dan fitur terbaru.
  2. Telegram Bot API Documentation2: Untuk memahami lebih dalam tentang struktur data yang dikirimkan oleh Telegram.
  3. Komunitas Telegram Bot Indonesia6: Bergabunglah dengan grup diskusi untuk bertanya dan berbagi pengalaman.

Note

Jangan lupa tonton video tutorialnya!

Guna memperjelas pemahaman dan insight secara umum.

thumb


Referensi


  1. Lumpia Framework Dokumentasi Resmi Lumpia Framework ↩2

  2. Telegram Bot API Dokumentasi Resmi API Telegram ↩2

  3. Google Apps Script Quotas Daftar Batas Layanan dan Kuota GAS Terbaru

  4. GAS-Lib-v3 GitHub Source Code Framework

  5. miniSheetDBv2 Library untuk integrasi Google Sheet dengan GAS

  6. Telegram Bot Indonesia Grup Diskusi Telegram

Membangun Bot Telegram dengan Bun dan GramIO

Panduan (Semoga) Lengkap dari Pemula hingga Lanjutan

Penulis: Hasanudin H Syafaat Release: Desember 2025 Versi: 0.0.1


Metadata Penulis

cover bun

Penutup dan Lampiran


Pengantar

Selamat datang di panduan komprehensif yang akan membawa Anda dari nol hingga lanjutan dalam membangun bot Telegram yang modern dan berkinerja tinggi. Kita akan memanfaatkan dua teknologi mutakhir: Bun, runtime JavaScript yang terkenal dengan kecepatannya, dan GramIO, framework Telegram Bot API yang dirancang untuk type-safety dan skalabilitas.

Buku ini bukan hanya panduan teknis; ini adalah peta jalan untuk menguasai ekosistem pengembangan bot yang efisien. Kami akan membahas setiap detail, mulai dari arsitektur internal Bun hingga strategi deployment bot siap produksi.

💡 Kutipan Motivasi: “Perjalanan seribu mil dimulai dengan satu langkah. Langkah pertama Anda adalah menguasai alat yang tepat.” - bangHasan


Bagian I: Memulai dengan Bun (The Modern JavaScript Runtime)

Bab 1: Pengantar Bun: Arsitektur dan Filosofi

1.1. Apa itu Bun? (Definisi, Visi, dan Tujuan)

Bun adalah runtime JavaScript, TypeScript, dan JSX yang serba ada (all-in-one) yang dirancang untuk kecepatan dan efisiensi. Bun bukan sekadar alternatif Node.js; ia adalah re-imajinasi dari seluruh toolchain pengembangan JavaScript.

Bun menggabungkan empat alat utama menjadi satu eksekusi tunggal:

  1. Runtime: Menjalankan kode JavaScript/TypeScript.
  2. Package Manager: Mengelola dependensi (bun install).
  3. Bundler & Transpiler: Mengemas dan mengubah kode untuk produksi (bun build).
  4. Test Runner: Menjalankan pengujian unit dan integrasi (bun test).

Visi Bun adalah untuk menghilangkan kompleksitas konfigurasi dan mempercepat setiap aspek alur kerja pengembang, dari instalasi paket hingga eksekusi kode.

💡 Kutipan Motivasi: “Kecepatan adalah raja. Dalam dunia bot, Bun adalah mahkotanya.” - bangHasan

1.2. Mengapa Bun? (Kecepatan, All-in-One Toolkit, JavaScriptCore) ⚡️

Keunggulan Bun terletak pada arsitektur internalnya yang unik:

1.2.1. Mesin JavaScriptCore dan Bahasa Zig

Bun tidak menggunakan mesin V8 (seperti Node.js dan Chrome), melainkan menggunakan JavaScriptCore (JSC), mesin yang dikembangkan oleh Apple untuk Safari. JSC dikenal memiliki waktu startup yang sangat cepat dan konsumsi memori yang lebih rendah.

Lebih lanjut, Bun ditulis dalam bahasa pemrograman tingkat rendah Zig, bukan C++ seperti Node.js. Zig memungkinkan kontrol memori yang sangat presisi dan menghasilkan binary yang sangat efisien, yang berkontribusi pada performa Bun yang superior.

1.2.2. All-in-One Toolkit: Menyederhanakan Toolchain

Bun secara fundamental menyederhanakan toolchain JavaScript. Anda tidak lagi memerlukan kombinasi npm, webpack, babel, dan jest. Semua fungsi ini sudah built-in dan dioptimalkan untuk bekerja sama.

Fitur BunManfaat bagi Pengembang Bot
Package Manager CepatInstalasi dependensi yang hampir instan, mengurangi waktu setup proyek.
Dukungan TypeScript NativeMenjalankan file .ts tanpa transpiler terpisah, ideal untuk type-safety GramIO.
Bundler BawaanMengemas kode bot untuk deployment dengan mudah dan cepat.
API yang DioptimalkanMenyediakan API I/O yang sangat cepat (misalnya bun:file, bun:sqlite).

1.3. Perbandingan Bun vs. Node.js: Analisis Mendalam

Meskipun Bun kompatibel dengan API Node.js, penting untuk memahami perbedaan mendasar yang memengaruhi performa bot Anda.

FiturBunNode.jsDampak pada Bot Telegram
Mesin JavaScriptJavaScriptCore (JSC)V8JSC lebih cepat dalam startup dan I/O, menghasilkan respons bot yang lebih cepat.
Bahasa IntiZigC++Zig memungkinkan Bun memiliki binary yang lebih kecil dan manajemen memori yang lebih efisien.
Package Managerbun install (Sangat Cepat)npm, yarn (Relatif Lambat)Waktu deployment dan setup yang jauh lebih singkat.
Dukungan TypeScriptNative (Zero-Config)Membutuhkan ts-node atau tscMengurangi kompleksitas toolchain dan mempercepat siklus pengembangan.
I/O APIbun:file, bun:serve (Dioptimalkan)fs, http (Standar)Operasi file dan jaringan yang lebih cepat, penting untuk bot yang menangani banyak media atau data.

Bab 2: Instalasi dan Menguasai Tooling Bun

2.1. Cara Instalasi Bun (Linux/macOS/WSL) 🛠️

Bun dirancang untuk sistem operasi berbasis Unix. Untuk menginstal Bun, Anda dapat menggunakan shell script resmi.

Langkah 1: Jalankan Instalasi

Buka terminal Anda dan jalankan perintah berikut:

curl -fsSL https://bun.sh/install | bash

Langkah 2: Verifikasi Instalasi

Setelah instalasi selesai, pastikan Bun telah ditambahkan ke $PATH Anda (Anda mungkin perlu me-restart terminal atau menjalankan source ~/.bashrc).

bun --version

Jika Anda melihat nomor versi, instalasi berhasil.

2.2. Menguasai Package Manager: bun install

bun install adalah salah satu fitur Bun yang paling revolusioner. Ia dapat menginstal paket hingga 20x lebih cepat daripada npm atau yarn.

Fitur Utama bun install:

  • Instalasi Cepat: Menggunakan native code dan caching yang agresif.
  • Kompatibilitas Node.js: Mampu membaca dan menulis file package.json dan node_modules standar.
  • Lockfile Tunggal: Menggunakan bun.lockb yang merupakan binary lockfile yang sangat cepat.
PerintahDeskripsi
bun installMenginstal semua dependensi dari package.json.
bun add <package>Menginstal paket baru dan menyimpannya sebagai dependencies.
bun add -d <package>Menginstal paket sebagai devDependencies.
bun remove <package>Menghapus paket dari proyek.

2.3. Menguasai Runtime: bun run

Perintah bun run digunakan untuk menjalankan file JavaScript/TypeScript atau script yang didefinisikan di package.json.

Menjalankan File:

# Menjalankan file TypeScript tanpa konfigurasi tambahan
bun run src/bot.ts

Menjalankan Script dari package.json:

Jika Anda memiliki package.json seperti ini:

{
  "scripts": {
    "start": "bun run src/bot.ts",
    "dev": "bun --watch src/bot.ts"
  }
}

Anda dapat menjalankannya dengan:

bun start
bun dev # Menggunakan fitur hot-reloading bawaan Bun

2.4. Menguasai Bundler: bun build

Untuk deployment, Anda perlu mengemas kode Anda menjadi satu file JavaScript yang dioptimalkan.

bun build ./src/bot.ts --outdir ./dist --target node

Perintah ini akan:

  1. Mengambil src/bot.ts sebagai entry point.
  2. Mengemas semua dependensi menjadi satu file.
  3. Menyimpannya di direktori ./dist.
  4. Menargetkan lingkungan Node.js (untuk kompatibilitas hosting yang lebih luas).

Bab 3: Dasar-dasar Pemrograman dengan Bun API

3.1. Membuat Proyek Bot Awal

Kita akan memulai proyek bot kita dengan struktur yang bersih.

mkdir telegram-bot-gramio
cd telegram-bot-gramio
bun init -y
bun add gramio @gramio/session node-cron @types/node-cron bun-types

Catatan: Kita menambahkan bun-types untuk autocomplete yang lebih baik di editor kode Anda.

3.2. Menggunakan bun:file untuk Operasi I/O Cepat

Bun menyediakan API I/O yang dioptimalkan. Mari kita lihat bagaimana Bun menangani operasi file secara asinkron.

import { file } from "bun";

const filePath = "data/log.txt";

// Menulis data ke file
async function writeLog(message: string) {
  const content = `${new Date().toISOString()} - ${message}\n`;
  // Bun.write adalah cara yang sangat cepat untuk menulis file
  await Bun.write(filePath, content, { append: true });
}

// Membaca data dari file
async function readLog() {
  try {
    const logFile = file(filePath);
    const content = await logFile.text();
    console.log("Isi Log:\n", content);
  } catch (error) {
    console.error("File log belum ada.");
  }
}

writeLog("Aplikasi dimulai.");
readLog();

3.3. Menggunakan bun:serve untuk Webhook (Lanjutan)

Meskipun kita akan fokus pada Long Polling, penting untuk mengetahui bahwa Bun memiliki server HTTP bawaan yang sangat cepat, ideal untuk webhook Telegram.

// Contoh sederhana server webhook
Bun.serve({
  port: 3000,
  fetch(req: Request) {
    const url = new URL(req.url);
    if (req.method === "POST" && url.pathname === "/webhook") {
      // Di sini Anda akan memproses update Telegram
      return new Response("OK", { status: 200 });
    }
    return new Response("Not Found", { status: 404 });
  },
});

Ini mengakhiri Bagian I. Kita telah meletakkan dasar yang kuat dengan memahami dan menguasai Bun sebagai toolchain utama kita.



Bagian II: Pengenalan GramIO dan Bot Telegram

Bab 4: Memahami Ekosistem Bot Telegram

4.1. Apa itu Bot Telegram? (Konsep Dasar) ✈️

Bot Telegram adalah akun otomatis yang berinteraksi dengan pengguna melalui API Telegram. Bot ini adalah program yang berjalan di server Anda, bukan di Telegram.

4.1.1. Perbedaan Bot dan Akun Pengguna Biasa
FiturBotAkun Pengguna Biasa
PendaftaranMelalui BotFather, tidak perlu nomor telepon.Membutuhkan nomor telepon yang valid.
InteraksiHanya dapat memulai percakapan jika pengguna mengirim pesan pertama atau menambahkannya ke grup.Dapat memulai percakapan kapan saja.
Status OnlineTidak memiliki status “Last Seen” atau “Online”.Memiliki status “Last Seen” atau “Online”.
APIMenggunakan Bot API (HTTP/Webhook).Menggunakan Telegram API (MTProto) untuk aplikasi klien.

4.2. Mendapatkan Token Bot dari BotFather: Kunci Rahasia Anda

Token API adalah string unik yang berfungsi sebagai kata sandi bot Anda. Token ini digunakan oleh GramIO untuk mengautentikasi permintaan ke server Telegram.

Langkah-langkah Mendapatkan Token:

  1. Cari @BotFather di Telegram.
  2. Ketik /newbot.
  3. Ikuti instruksi untuk memilih nama tampilan (misalnya, “Bot Buku Bun”) dan username (harus diakhiri dengan bot, misalnya, BotBukuBun_bot).
  4. BotFather akan memberikan Anda Token API.

Peringatan Keamanan: Token API harus diperlakukan sebagai informasi rahasia. JANGAN PERNAH menyimpannya langsung di kode sumber atau membagikannya di repositori publik. Selalu gunakan Environment Variable.

4.3. Konsep Dasar Telegram Bot API: Updates, Methods, dan Types

Memahami GramIO berarti memahami cara kerja API Telegram:

  1. Updates: Setiap interaksi pengguna (pesan, klik tombol, pengguna bergabung) dikirimkan ke bot Anda sebagai objek Update. GramIO bertugas menerima dan memproses update ini.
  2. Methods: Ini adalah fungsi yang Anda panggil untuk memerintahkan bot melakukan sesuatu (misalnya, sendMessage, editMessageText). GramIO menyediakan antarmuka yang type-safe untuk semua methods ini.
  3. Types: Ini adalah struktur data yang digunakan oleh Telegram (misalnya, Message, User, Chat). GramIO, berkat TypeScript, secara otomatis menyediakan definisi tipe untuk semua objek ini.

Bab 5: Pengantar GramIO Framework: Type-Safety dan Middleware

5.1. Apa itu GramIO? (Fitur Utama, Keunggulan) ✨

GramIO adalah framework Telegram Bot API yang dibangun dengan fokus pada type-safety dan arsitektur middleware yang fleksibel.

5.1.1. Keunggulan Type-Safety

Karena GramIO ditulis dalam TypeScript, Anda mendapatkan autocompletion dan pemeriksaan kesalahan tipe saat Anda menulis kode. Ini sangat mengurangi bug saat berinteraksi dengan struktur data Telegram yang kompleks.

5.1.2. Arsitektur Middleware

GramIO mengadopsi pola desain middleware (mirip dengan Express.js atau Koa.js). Setiap update melewati serangkaian fungsi (middleware) sebelum mencapai handler akhir. Ini memungkinkan Anda untuk:

  • Pre-processing: Melakukan logging, autentikasi, atau rate limiting.
  • Modifikasi Konteks: Menambahkan data sesi atau database ke objek Context.
  • Filtering: Menghentikan pemrosesan jika update tidak relevan.

5.2. Setup Proyek GramIO Pertama dengan Bun

Kita akan menggunakan Bun untuk menginstal GramIO dan menjalankan bot.

Langkah 1: Instalasi Dependensi

bun add gramio @gramio/session node-cron @types/node-cron

Langkah 2: Konfigurasi Environment Variable

Buat file .env di root proyek Anda. Bun akan memuatnya secara otomatis saat Anda menggunakan bun run.

File: .env

BOT_TOKEN="TOKEN_ANDA_DARI_BOTFATHER"

Langkah 3: Inisialisasi Bot

File: src/bot.ts

import { Bot } from "gramio";

const BOT_TOKEN = process.env.BOT_TOKEN;

if (!BOT_TOKEN) {
  throw new Error(
    "BOT_TOKEN tidak ditemukan. Pastikan Anda mengatur environment variable.",
  );
}

// Inisialisasi Bot GramIO
const bot = new Bot({
  token: BOT_TOKEN,
  // Opsi lain: mode polling (default) atau webhook
});

// Menjalankan bot dalam mode Long Polling
bot.start();
console.log("Bot GramIO sedang berjalan di Bun...");

Bab 6: Bot Pertama: Reaksi dan Respons

6.1. Konsep Context (Ctx): Jantung Bot Anda

Objek Context adalah objek yang dibuat GramIO untuk setiap update. Ini adalah objek yang Anda gunakan untuk:

  • Mengakses data pesan (context.text, context.from, context.chat).
  • Memanggil methods API Telegram (context.send, context.reply, context.editMessageText).
  • Mengakses data sesi (context.session).

6.2. Menangani Perintah (bot.command)

Perintah adalah pesan yang dimulai dengan / (misalnya, /start, /help).

// Menangani perintah /start
bot.command("start", (context) => {
  // context.send adalah shortcut untuk bot.api.sendMessage
  return context.send("Selamat datang di Bot Bun + GramIO!");
});

// Menangani perintah dengan argumen
bot.command("echo", (context) => {
  // context.text akan berisi '/echo pesan saya'
  const message = context.text.replace("/echo", "").trim();
  if (message) {
    return context.reply(`Anda meminta saya mengulang: ${message}`);
  }
  return context.send("Gunakan: /echo [pesan]");
});

6.3. Menangani Pesan Teks dan Filter (bot.on dan bot.hears)

  • bot.on("text"): Menangani semua pesan teks.
  • bot.hears(regex): Menangani pesan teks yang cocok dengan ekspresi reguler.
// Echo Bot Sederhana
bot.on("text", (context) => {
  // Pastikan bot tidak merespons perintah lain
  if (!context.text.startsWith("/")) {
    return context.reply(`Saya menerima pesan Anda: "${context.text}"`);
  }
});

// Menangani kata kunci spesifik
bot.hears(/bun/i, (context) => {
  return context.send("Bun adalah runtime JavaScript tercepat!");
});

Bagian III: Pengembangan Bot Tingkat Menengah

Bab 7: Menguasai Middleware dan Aliran Kontrol 🔄

7.1. Struktur Middleware: context dan next()

Middleware adalah fungsi dengan tanda tangan (context: Ctx, next: Next) => Promise<void> | void.

  • context: Objek konteks update saat ini.
  • next(): Fungsi yang harus dipanggil untuk meneruskan kontrol ke middleware berikutnya atau handler akhir.

7.2. Contoh Middleware: Autentikasi Admin

Middleware ini memastikan hanya pengguna dengan ID tertentu yang dapat mengakses handler berikutnya.

const ADMIN_ID = 123456789; // ID Admin Anda

const adminOnlyMiddleware = (context: any, next: any) => {
  if (context.from?.id === ADMIN_ID) {
    // Lanjutkan ke handler berikutnya
    return next();
  } else {
    // Hentikan pemrosesan dan kirim pesan penolakan
    return context.send("Akses ditolak. Perintah ini hanya untuk admin.");
  }
};

// Menerapkan middleware hanya pada perintah /secret
bot.command("secret", adminOnlyMiddleware, (context) => {
  context.send("Selamat datang di ruang rahasia admin!");
});

7.3. Aliran Kontrol Lanjutan: bot.use dan bot.filter

  • bot.use(middleware): Menerapkan middleware secara global untuk SEMUA update.
  • bot.filter(filterFunction): Menerapkan handler hanya jika fungsi filter mengembalikan true.
// Contoh: Hanya memproses pesan dari grup, bukan dari chat pribadi
bot.filter(
  (context) =>
    context.chat.type === "group" || context.chat.type === "supergroup",
  (context) => {
    context.send("Terima kasih telah menggunakan bot ini di grup!");
  },
);

Bab 8: Interaksi Kaya: Media dan Callback Queries

8.1. Menangani Media dengan Filter Spesifik

GramIO menyediakan objek Filter untuk menangani berbagai jenis media dengan mudah.

import { Filter } from "gramio";

// Menangani foto
bot.on(Filter.photo, (context) => {
  const photo = context.photo.pop(); // Ambil resolusi tertinggi
  context.reply(`Foto diterima! File ID: ${photo?.file_id}`);
});

// Menangani video
bot.on(Filter.video, (context) => {
  context.reply(`Video diterima! Judul: ${context.video?.file_name}`);
});

// Menangani pesan yang berisi stiker
bot.on(Filter.sticker, (context) => {
  context.reply("Stiker lucu! Saya akan membalas dengan stiker yang sama.");
  context.sendSticker({ sticker: context.sticker.file_id });
});

8.2. Menggunakan Inline Keyboard: Interaksi Non-Intrusif

Inline Keyboard adalah tombol yang melekat pada pesan dan tidak memenuhi layar pengguna.

import { InlineKeyboard } from "gramio";

bot.command("poll", (context) => {
  const pollKeyboard = new InlineKeyboard()
    .text("Pilihan A", "vote_A")
    .text("Pilihan B", "vote_B")
    .row() // Baris baru
    .url("Lihat Hasil", "https://example.com/results");

  context.send("Pilih opsi favorit Anda:", {
    reply_markup: pollKeyboard,
  });
});

// Menangani Callback Query
bot.callbackQuery("vote_A", (context) => {
  // Mengirim notifikasi pop-up ke pengguna
  context.answerCallbackQuery({
    text: "Anda memilih Pilihan A. Terima kasih!",
  });

  // Mengedit pesan asli untuk menunjukkan bahwa pengguna telah memilih
  context.editMessageText(
    `Pilihan A telah dipilih oleh ${context.from.first_name}.`,
  );
});

Bab 9: Keyboard Kustom dan Pengelolaan Pesan

9.1. Reply Keyboard: Menu Utama yang Nyaman

Reply Keyboard menggantikan keyboard standar Telegram dan ideal untuk menu utama.

import { Keyboard } from "gramio";

bot.command("menu", (context) => {
  const menuKeyboard = new Keyboard()
    .text("Mulai Pendaftaran")
    .text("Cek Saldo DB")
    .row()
    .text("Bantuan")
    .text("Inline Menu")
    .oneTime(); // Keyboard akan hilang setelah digunakan

  context.send("Pilih aksi Anda:", {
    reply_markup: menuKeyboard,
  });
});

9.2. Mengedit dan Menghapus Pesan

Bot dapat mengedit pesan yang dikirimnya sendiri, yang penting untuk stateful UI (misalnya, menu navigasi).

bot.callbackQuery("navigate_to_help", (context) => {
  // Mengedit teks pesan yang berisi keyboard inline
  context.editMessageText(
    "Ini adalah halaman Bantuan. Pilih menu lain di bawah:",
    {
      reply_markup: new InlineKeyboard().text(
        "Kembali ke Menu Utama",
        "main_menu",
      ),
    },
  );
  context.answerCallbackQuery(); // Selalu jawab callback query
});


Bagian IV: Pengembangan Bot Tingkat Lanjut dan Produksi

Bab 10: State Management dan Persistent Storage 💾

10.1. Konsep Sesi (Session) dalam GramIO: Mengingat Pengguna

Sesi adalah mekanisme untuk menyimpan data spesifik pengguna di antara interaksi. Tanpa sesi, bot Anda akan “lupa” apa yang terjadi di langkah sebelumnya.

10.1.1. Session Middleware dan Tipe Data

GramIO menggunakan plugin @gramio/session untuk mengelola sesi. Anda harus mendefinisikan tipe data sesi Anda (jika menggunakan TypeScript) dan memilih storage yang sesuai.

import { MemorySessionStorage, session } from "@gramio/session";

// 1. Definisikan Tipe Data Sesi
interface SessionData {
  step: "idle" | "waiting_for_name" | "waiting_for_age";
  name?: string;
  cart: string[]; // Contoh: Keranjang belanja
}

// 2. Terapkan Middleware
bot.use(
  session<SessionData>({
    // MemorySessionStorage hanya untuk pengembangan. Data akan hilang saat bot restart.
    storage: new MemorySessionStorage(),
    initial: () => ({ step: "idle", cart: [] }), // Nilai awal
  }),
);

// 3. Gunakan di Handler
bot.command("add_to_cart", (context) => {
  context.session.cart.push("Item Baru");
  context.send(
    `Item ditambahkan. Total item di keranjang: ${context.session.cart.length}`,
  );
});

10.2. Integrasi Database dengan bun:sqlite: Penyimpanan Lokal yang Cepat 🗄️

Untuk bot yang berjalan dalam mode Long Polling dan membutuhkan penyimpanan data lokal yang cepat dan persisten, bun:sqlite adalah pilihan yang sangat baik. Bun menyediakan API yang sangat cepat untuk berinteraksi dengan database SQLite.

10.2.1. Setup dan Operasi Dasar SQLite
import { Database } from "bun:sqlite";

// Buka atau buat database file. File 'bot_data.sqlite' akan dibuat.
const db = new Database("bot_data.sqlite");

// Membuat tabel jika belum ada
db.run(`
  CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY,
    username TEXT,
    balance REAL DEFAULT 0.0,
    created_at TEXT DEFAULT CURRENT_TIMESTAMP
  )
`);

// Fungsi untuk menyimpan atau memperbarui saldo pengguna
function saveUserBalance(userId: number, username: string, balance: number) {
  // Menggunakan prepared statement untuk keamanan dan performa
  const query = db.query(`
    INSERT INTO users (id, username, balance) 
    VALUES (?, ?, ?) 
    ON CONFLICT(id) DO UPDATE SET 
      username=excluded.username, 
      balance=excluded.balance
  `);
  query.run(userId, username, balance);
}

// Fungsi untuk mendapatkan saldo
function getUserBalance(userId: number): number {
  const query = db.query("SELECT balance FROM users WHERE id = ?");
  const result = query.get(userId) as { balance: number } | null;
  return result ? result.balance : 0;
}
10.2.2. Mengintegrasikan SQLite ke Bot
// Handler untuk mengecek saldo
bot.hears("Cek Saldo DB", (context) => {
  const balance = getUserBalance(context.from.id);
  context.send(`Saldo Anda saat ini: Rp ${balance.toLocaleString("id-ID")}`);
});

// Contoh: Setelah pendaftaran selesai
// ...
// saveUserBalance(context.from.id, context.from.username || context.from.first_name, 100);
// ...

Bab 11: Bot Terjadwal (Cron/Scheduler): Menjadi Proaktif ⏰

Bot terjadwal memungkinkan bot Anda untuk melakukan tugas tanpa dipicu oleh pesan pengguna.

💡 Kutipan Motivasi: “Jangan biarkan bot Anda tidur. Jadwalkan kesuksesan, dan biarkan kode Anda bekerja saat Anda beristirahat.” - bangHasan

11.1. Memahami Ekspresi Cron

Ekspresi Cron adalah string yang mendefinisikan kapan tugas harus dijalankan. Format yang umum digunakan adalah 5 atau 6 bidang:

PosisiDeskripsiNilai yang DiizinkanContoh
1Menit0-5930 (Menit ke-30)
2Jam0-2310 (Pukul 10 pagi)
3Hari dalam Bulan1-31* (Setiap hari)
4Bulan1-12* (Setiap bulan)
5Hari dalam Minggu0-7 (0 atau 7 = Minggu)1-5 (Senin sampai Jumat)
Ekspresi CronArtinya
* * * * *Setiap menit.
0 9 * * *Setiap hari pada pukul 9:00 pagi.
0 18 * * 1-5Setiap hari kerja pada pukul 6:00 sore.

11.2. Implementasi Cron Job dengan node-cron

Meskipun Bun tidak memiliki scheduler bawaan, library node-cron bekerja dengan sangat baik di Bun.

Langkah 1: Instalasi

bun add node-cron @types/node-cron

Langkah 2: Membuat Tugas Terjadwal

import * as cron from "node-cron";

// Fungsi untuk mengirim pesan ke semua pengguna (simulasi)
async function sendMassNotification(botInstance: Bot) {
  console.log("Memulai pengiriman notifikasi massal...");

  // Ambil semua ID pengguna dari database (simulasi)
  const userIds = [123456789, 987654321]; // Ganti dengan hasil query DB

  for (const userId of userIds) {
    try {
      await botInstance.api.sendMessage({
        chat_id: userId,
        text: "📢 Notifikasi Harian: Bot Anda aktif dan siap melayani!",
      });
      console.log(`Notifikasi terkirim ke user ${userId}`);
    } catch (error) {
      console.error(`Gagal mengirim ke user ${userId}:`, error);
    }
  }
}

// Jadwal: Setiap hari pada pukul 10:00 pagi
cron.schedule("0 10 * * *", () => {
  // Pastikan bot sudah terinisialisasi sebelum memanggil API
  if (bot.api) {
    sendMassNotification(bot);
  }
}, {
  // Tentukan zona waktu agar jadwal akurat
  timezone: "Asia/Jakarta",
});

console.log(
  "Cron job terjadwal: Notifikasi harian pada 10:00 AM (Asia/Jakarta).",
);

Bab 12: ☁️ Deployment dan Produksi: Menjadikan Bot Anda Hidup

Deployment adalah langkah krusial untuk memastikan bot Anda berjalan 24/7 dan dapat diakses oleh pengguna.

💡 Kutipan Motivasi: “Kode yang hebat tanpa deployment yang andal hanyalah puisi. Jadikan puisi Anda nyata di cloud.” - bangHasan

12.1. Persiapan Produksi dengan Bun

Sebelum deployment, pastikan Anda:

  1. Menggunakan bun build untuk mengoptimalkan kode (lihat Bab 2.4).
  2. Mengatur Environment Variable (BOT_TOKEN) dengan benar.
  3. Menggunakan penyimpanan sesi yang persisten (misalnya Redis atau database, bukan MemorySessionStorage).

12.2. Strategi Deployment: Memilih yang Tepat

PlatformMetode BotKelebihanKekuranganCocok untuk
VPS/VMLong Polling / WebhookKontrol penuh, dapat menggunakan bun:sqlite secara lokal.Membutuhkan manajemen OS (Linux), perlu process manager (PM2).Bot dengan kebutuhan I/O tinggi atau database lokal.
RailwayLong PollingSangat mudah, integrasi Git, zero-config untuk Bun.Biaya bisa meningkat seiring penggunaan, tidak ideal untuk Webhook.Bot Long Polling skala kecil hingga menengah.
DockerLong Polling / WebhookPortabilitas tinggi, lingkungan terisolasi.Membutuhkan pemahaman Docker, file bun.lockb harus disertakan.Bot skala besar, arsitektur microservices.
Vercel/ServerlessWebhookSkala otomatis, bayar sesuai penggunaan.Tidak mendukung Long Polling, tidak dapat menggunakan bun:sqlite (karena stateless).Bot yang hanya menggunakan Webhook dan database eksternal.

12.3. Deployment dengan PM2 di VPS

PM2 adalah process manager yang populer untuk aplikasi Node.js/Bun. Ia memastikan bot Anda tetap berjalan dan otomatis restart jika terjadi crash.

Langkah-langkah di VPS:

  1. Instal PM2 secara global: npm install -g pm2 (atau bun add -g pm2).
  2. Jalankan bot Anda:
    pm2 start --name "telegram-bot-bun" bun -- run src/bot.ts
    
  3. Simpan konfigurasi agar otomatis restart saat server reboot: pm2 save.

12.4. Deployment dengan Docker

Menggunakan Docker adalah cara terbaik untuk memastikan lingkungan produksi Anda sama dengan lingkungan pengembangan.

File: Dockerfile

# Tahap 1: Build
FROM oven/bun:latest AS builder

WORKDIR /app

# Salin file yang diperlukan untuk instalasi
COPY package.json bun.lockb ./

# Instal dependensi
RUN bun install --frozen-lockfile

# Salin kode sumber
COPY . .

# Tahap 2: Final
FROM oven/bun:latest

WORKDIR /app

# Salin hasil instalasi dan kode dari tahap builder
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/src ./src
COPY --from=builder /app/package.json ./package.json
COPY --from=builder /app/bot_data.sqlite ./bot_data.sqlite # Jika menggunakan SQLite

# Perintah untuk menjalankan bot
CMD ["bun", "run", "src/bot.ts"]

Membangun dan Menjalankan:

docker build -t my-bun-bot .
docker run -d --name bun-bot-prod -e BOT_TOKEN="YOUR_TOKEN" my-bun-bot

Penutup

Selamat! Anda telah menyelesaikan panduan komprehensif ini. Anda kini tidak hanya menguasai dasar-dasar bot Telegram, tetapi juga telah memahami bagaimana memanfaatkan kecepatan Bun, struktur GramIO, dan teknik-teknik tingkat lanjut seperti manajemen sesi, database SQLite, penjadwalan Cron, dan strategi deployment modern.

Kombinasi Bun dan GramIO menempatkan Anda di garis depan pengembangan bot yang cepat, andal, dan type-safe.

💡 Kutipan Motivasi: “Belajar adalah proses tanpa akhir. Teruslah bereksperimen, teruslah membangun, dan biarkan bot Anda menjadi karya terbaik Anda.” - bangHasan


Lampiran

A. Referensi Cepat Perintah Bun

PerintahDeskripsi
bun installMenginstal dependensi dari package.json.
bun add <package>Menambahkan paket baru.
bun run <file>Menjalankan file JavaScript/TypeScript.
bun startMenjalankan script start di package.json.
bun build <file> --outdir ./distMem-bundle kode untuk produksi.

B. Referensi Cepat GramIO API

FiturMetode GramIODeskripsi
Inisialisasinew Bot({ token: ... })Membuat instance bot.
Mulaibot.start()Memulai Long Polling.
Middlewarebot.use(middleware)Menerapkan middleware global.
Handlerbot.on("text", ...)Menangani update berdasarkan tipe.
Perintahbot.command("start", ...)Menangani perintah /start.
Kontekscontext.send(...)Mengirim pesan balasan.
Keyboardnew InlineKeyboard()Membuat keyboard inline.
Sesisession(...)Middleware untuk manajemen state.

C. Kode Sumber Lengkap (src/bot.ts)

import { Bot, Filter, InlineKeyboard, Keyboard } from "gramio";
import { MemorySessionStorage, session } from "@gramio/session";
import { Database } from "bun:sqlite";
import * as cron from "node-cron";

// --- Konfigurasi ---
const BOT_TOKEN = process.env.BOT_TOKEN || "YOUR_BOT_TOKEN_HERE";
const ADMIN_ID = 123456789; // Ganti dengan ID Telegram Admin Anda

if (BOT_TOKEN === "YOUR_BOT_TOKEN_HERE") {
  console.warn(
    "PERINGATAN: Menggunakan token placeholder. Bot tidak akan terhubung ke Telegram.",
  );
}

// --- Inisialisasi Bot ---
const bot = new Bot({ token: BOT_TOKEN });

// --- Konfigurasi Database Sederhana (bun:sqlite) ---
const db = new Database("bot_data.sqlite");
db.run(
  "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, username TEXT, balance REAL DEFAULT 0.0)",
);

function saveUserBalance(userId: number, username: string, balance: number) {
  const query = db.query(`
    INSERT INTO users (id, username, balance) 
    VALUES (?, ?, ?) 
    ON CONFLICT(id) DO UPDATE SET 
      username=excluded.username, 
      balance=excluded.balance
  `);
  query.run(userId, username, balance);
}

function getUserBalance(userId: number): number {
  const query = db.query("SELECT balance FROM users WHERE id = ?");
  const result = query.get(userId) as { balance: number } | null;
  return result ? result.balance : 0;
}

// --- Middleware Logging ---
const loggingMiddleware = (context: any, next: any) => {
  const user = context.from?.username || context.from?.first_name ||
    "Unknown User";
  console.log(
    `[LOG] Pesan dari @${user}: ${context.text || "[Non-text message]"}`,
  );
  return next();
};

bot.use(loggingMiddleware);

// --- Middleware Sesi ---
interface SessionData {
  step: "idle" | "waiting_for_name" | "waiting_for_age";
  name?: string;
}

bot.use(
  session<SessionData>({
    storage: new MemorySessionStorage(),
    initial: () => ({ step: "idle" }),
  }),
);

// --- Handler Perintah Dasar ---
bot.command("start", (context) => {
  return context.send(
    "Halo! Saya adalah bot GramIO yang berjalan di Bun. Ketik /menu untuk melihat opsi.",
  );
});

// --- Handler Perintah Admin ---
const adminOnlyMiddleware = (context: any, next: any) => {
  const ADMIN_ID = 123456789; // Ganti dengan ID Admin Anda
  if (context.from?.id === ADMIN_ID) {
    return next();
  } else {
    return context.send("Akses ditolak. Perintah ini hanya untuk admin.");
  }
};

bot.command("admin", adminOnlyMiddleware, (context) => {
  context.send("Selamat datang, Admin!");
});

// --- Handler Keyboard Kustom ---
bot.command("menu", (context) => {
  const menuKeyboard = new Keyboard()
    .text("Mulai Pendaftaran")
    .text("Inline Menu")
    .row()
    .text("Cek Saldo DB");

  context.send("Pilih salah satu opsi di bawah:", {
    reply_markup: menuKeyboard,
  });
});

// --- Handler Database ---
bot.hears("Cek Saldo DB", (context) => {
  const balance = getUserBalance(context.from.id);
  context.send(`Saldo Anda saat ini: Rp ${balance.toLocaleString("id-ID")}`);
});

// --- Handler Keyboard Inline ---
bot.hears("Inline Menu", (context) => {
  const inlineKeyboard = new InlineKeyboard()
    .text("Beli Sekarang", "buy_item")
    .url("Kunjungi GramIO", "https://gramio.dev")
    .row()
    .text("Tutup Menu", "close_message");

  context.send("Ini adalah tombol inline:", {
    reply_markup: inlineKeyboard,
  });
});

// --- Handler Callback Query ---
bot.callbackQuery("buy_item", (context) => {
  context.answerCallbackQuery({ text: "Item berhasil dibeli! (Simulasi)" });
  context.editMessageText(
    "Terima kasih atas pembelian Anda! (Pesan telah diedit)",
  );
});

bot.callbackQuery("close_message", (context) => {
  context.editMessageReplyMarkup({ reply_markup: undefined });
  context.answerCallbackQuery({ text: "Menu ditutup." });
});

// --- Handler Sesi Pendaftaran ---
bot.hears("Mulai Pendaftaran", (context) => {
  context.session.step = "waiting_for_name";
  context.send("Selamat datang! Siapa nama Anda?");
});

bot.on("text", (context) => {
  if (context.session.step === "waiting_for_name") {
    context.session.name = context.text;
    context.session.step = "waiting_for_age";
    context.send(`Halo, ${context.session.name}! Berapa usia Anda?`);
  } else if (context.session.step === "waiting_for_age") {
    const age = parseInt(context.text);
    if (isNaN(age)) {
      return context.send("Mohon masukkan usia dalam angka.");
    }
    // Simpan ke DB
    saveUserBalance(
      context.from.id,
      context.from.username || context.from.first_name,
      100,
    );

    context.session.step = "idle";
    context.send(
      `Terima kasih, ${context.session.name}, usia Anda ${age} tahun. Pendaftaran selesai! Saldo awal Anda 100.`,
    );
  } else if (context.session.step === "idle") {
    // Echo Bot
    const originalText = context.text;
    return context.send(`Anda berkata: "${originalText}"`);
  }
});

// --- Handler Inline Query ---
bot.on("inline_query", async (context) => {
  const query = context.inlineQuery.query;

  const results = [
    {
      type: "article",
      id: "1",
      title: `Echo Inline: ${query}`,
      input_message_content: {
        message_text: `Hasil Inline Query: ${query}`,
      },
    },
  ];

  await context.answerInlineQuery(results, {
    cache_time: 0,
  });
});

// --- Bot Terjadwal (Cron Job) ---
// Jadwal: Setiap hari pada pukul 10:00 pagi (Asia/Jakarta)
cron.schedule("0 10 * * *", async () => {
  const TEST_CHAT_ID = 123456789; // Ganti dengan ID chat yang valid
  console.log("Menjalankan tugas cron: Notifikasi harian.");

  // Contoh: Mengirim notifikasi ke TEST_CHAT_ID
  // await bot.api.sendMessage({
  //     chat_id: TEST_CHAT_ID,
  //     text: "📢 Notifikasi Harian: Bot Anda aktif dan siap melayani!",
  // });
}, {
  timezone: "Asia/Jakarta",
});

// --- Mulai Bot ---
bot.start();
console.log("Bot GramIO sedang berjalan di Bun...");
console.log("Untuk menguji, ganti BOT_TOKEN di src/bot.ts dengan token Anda.");

Caution

🚫 Materi ini masih draft, kemungkinan akan mengalami banyak errornya baik ketika dipraktekkan maupun susunan materinya.

DRAFT

BOT TELEGRAM DENGAN RUST DAN TELOXIDE

Pengantar

Selamat datang di panduan komprehensif untuk membangun bot Telegram yang cepat, aman, dan andal menggunakan bahasa pemrograman Rust dan framework Teloxide.

Jika kamu adalah seorang pemula yang baru mengenal Rust atau pengembangan bot, jangan khawatir. E-book ini dirancang untuk memandumu langkah demi langkah, mulai dari instalasi dasar hingga implementasi fitur-fitur canggih. Jika kamu sudah memiliki pengalaman, e-book ini akan membantumu memahami bagaimana Teloxide memanfaatkan kekuatan Rust untuk menciptakan bot yang luar biasa.

Mengapa Rust untuk Bot Telegram?

Rust adalah bahasa pemrograman yang berfokus pada dua hal utama: kecepatan dan keamanan memori.

  • Performa Tinggi: Rust dikompilasi menjadi kode mesin, yang berarti bot kamu akan berjalan sangat cepat, setara dengan C atau C++. Ini sangat penting untuk bot yang menangani banyak permintaan secara bersamaan.
  • Keamanan: Rust menjamin keamanan memori tanpa garbage collector, mencegah bug umum seperti null pointer dereference atau data race saat menggunakan multithreading. Bot kamu akan lebih stabil dan minim crash.
  • Ekosistem Asinkron yang Kuat: Rust memiliki ekosistem asinkron (async/await) yang matang, sempurna untuk operasi I/O-berat seperti berkomunikasi dengan API Telegram.

Bagian I: Persiapan dan Dasar-Dasar Rust

Bagian ini akan memandumu dalam menyiapkan lingkungan pengembangan dan mempelajari dasar-dasar bahasa Rust yang diperlukan sebelum kita terjun ke Teloxide.

Bab 1: Instalasi Rust dan Lingkungan Pengembangan

Untuk memulai, kamu perlu menginstal Rust. Cara termudah dan paling direkomendasikan adalah melalui rustup, alat manajemen versi Rust.

Langkah 1: Menginstal rustup

Buka terminal (di Linux/macOS) atau PowerShell/Command Prompt (di Windows).

Untuk Linux dan macOS:

Jalankan perintah berikut:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

Setelah instalasi selesai, kamu mungkin perlu me-muat ulang shell kamu atau menjalankan perintah berikut untuk memastikan cargo (manajer paket Rust) ada di PATH sistem kamu:

source $HOME/.cargo/env

Untuk Windows:

  1. Kunjungi situs resmi rustup: https://rustup.rs/.
  2. Unduh dan jalankan installer rustup-init.exe.
  3. Ikuti instruksi di layar. Biasanya, kamu bisa memilih opsi instalasi default (pilihan 1).
  4. Pastikan kamu juga telah menginstal build tools C++ untuk Visual Studio, yang diperlukan Rust untuk mengkompilasi kode. Installer Rust biasanya akan memandumu untuk menginstalnya.

Langkah 2: Verifikasi Instalasi

Setelah instalasi, verifikasi bahwa Rust dan cargo telah terinstal dengan benar dengan menjalankan perintah:

rustc --version
cargo --version

version cargo

Jika kamu melihat nomor versi, selamat! Lingkungan Rust kamu sudah siap.

Bab 2: Proyek Rust Pertama dengan Cargo

Semua proyek Rust modern dikelola oleh Cargo, manajer paket dan sistem build resmi Rust.

Membuat Proyek Baru

Mari kita buat proyek Rust pertama kita, yang akan kita sebut hello_rust:

cargo new hello_rust
cd hello_rust

Perintah ini akan membuat direktori hello_rust dengan struktur dasar:

hello_rust/
├── Cargo.toml
└── src/
    └── main.rs
  • Cargo.toml: File konfigurasi proyek. Di sinilah kamu mendefinisikan dependensi (pustaka/ crate) dan metadata proyek.
  • src/main.rs: Berisi kode sumber utama aplikasi kamu.

Menjalankan Proyek

Buka src/main.rs. Kamu akan melihat kode “Hello, World!” standar:

fn main() {
    println!("Hello, world!");
}
Kamu bisa menjalankan contoh source code untuk pelajaran Rust dasar dengan mengklik tombol Run (pojok kanan atas, disamping tombol `copy`)

Untuk mengkompilasi dan menjalankan proyek, gunakan:

cargo run

Kamu akan melihat output: Hello, world!.

Membangun Proyek

Jika kamu hanya ingin mengkompilasi kode tanpa menjalankannya, gunakan:

cargo build

Executable yang dihasilkan akan berada di direktori target/debug/.

Bab 3: Dasar-Dasar Bahasa Rust (Tutorial Singkat)

Sebelum kita masuk ke Teloxide, mari kita pahami beberapa konsep dasar Rust.

3.1. Variabel dan Mutabilitas

Secara default, variabel di Rust bersifat tidak dapat diubah (immutable).

fn main() {
    let x = 5; // x immutable
    println!("Nilai x adalah: {}", x);

    // x = 6; // ERROR! Kamu tidak bisa mengubah variabel immutable

    let mut y = 5; // Tambahkan 'mut' untuk membuatnya mutable
    println!("Nilai y sebelum diubah: {}", y);
    y = 6; // OK
    println!("Nilai y setelah diubah: {}", y);
}

3.2. Tipe Data Dasar

Rust adalah bahasa yang diketik secara statis (statically typed), tetapi seringkali dapat menyimpulkan tipe data.

Tipe DataDeskripsiContoh
IntegerBilangan bulat (i8, u8, i32, u32, i64, u64, dll.)let a: i32 = 42;
Floating-PointBilangan desimal (f32, f64)let b: f64 = 3.14;
BooleanBenar atau salahlet c: bool = true;
CharKarakter Unicode tunggallet d: char = '🦀';
StringTeks (ada dua jenis utama: &str dan String)let s = "Halo";

3.3. Struktur Kontrol: if dan match

Rust menggunakan if seperti bahasa lain, tetapi juga memiliki ekspresi match yang sangat kuat.

fn main() {
    let angka = 7;

    // Contoh if/else
    if angka < 5 {
        println!("Angka kecil");
    } else if angka == 7 {
        println!("Angka keberuntungan!");
    } else {
        println!("Angka besar");
    }

    // Contoh match (sangat umum di Rust)
    let status_kode = 200;
    match status_kode {
        200 => println!("OK"),
        404 => println!("Tidak Ditemukan"),
        500 => println!("Kesalahan Server"),
        _ => println!("Status tidak diketahui"), // _ adalah wildcard
    }
}

3.4. Fungsi

Fungsi didefinisikan dengan kata kunci fn.

// Fungsi tanpa nilai kembalian
fn sapa_kamu(nama: &str) {
    println!("Halo, {}!", nama);
}

// Fungsi dengan nilai kembalian (ditentukan setelah ->)
fn tambah_dua(x: i32) -> i32 {
    x + 2 // Ekspresi tanpa titik koma (;) adalah nilai kembalian
}

fn main() {
    sapa_kamu("Budi");
    let hasil = tambah_dua(10);
    println!("10 + 2 = {}", hasil);
}

3.5. Konsep Kunci: Ownership (Kepemilikan)

Ownership adalah fitur unik Rust yang menjamin keamanan memori. Ini adalah konsep yang paling sulit bagi pemula, tetapi memahaminya adalah kunci untuk menulis kode Rust yang baik.

Aturan Dasar Ownership:

  1. Setiap nilai di Rust memiliki variabel yang disebut pemilik (owner).
  2. Hanya ada satu pemilik pada satu waktu.
  3. Ketika pemilik keluar dari scope, nilai akan dihapus (dropped).

Contoh Sederhana:

fn main() {
    let s1 = String::from("halo"); // s1 adalah pemilik String "halo"
    let s2 = s1; // KEPEMILIKAN PINDAH (MOVE) dari s1 ke s2. s1 tidak valid lagi!

    // println!("s1: {}", s1); // ERROR! s1 sudah tidak valid

    println!("s2: {}", s2); // OK
}

Untuk menghindari move dan hanya menggunakan nilai tanpa mengambil kepemilikan, kita menggunakan Referensi dan Peminjaman (References and Borrowing).

fn hitung_panjang(s: &String) -> usize { // Menerima referensi (&String)
    s.len()
} // s keluar dari scope, tetapi karena itu hanya referensi, tidak ada yang dihapus

fn main() {
    let s1 = String::from("Teloxide");
    let panjang = hitung_panjang(&s1); // Kita meminjam (&) s1
    println!("Panjang '{}' adalah {}", s1, panjang); // s1 masih valid!
}

Konsep ini akan menjadi lebih jelas saat kita mulai menulis kode bot. Untuk saat ini, cukup ketahui bahwa Rust sangat ketat tentang siapa yang memiliki data dan kapan data itu dapat diakses.


Sampai di sini, kamu sudah memiliki dasar yang kuat untuk melanjutkan ke pengembangan bot Telegram!

Bagian II akan membahas cara mendapatkan token bot dan mulai menggunakan crate Teloxide.


Bagian II: Memulai dengan Teloxide

Sekarang kita akan mulai membangun bot Telegram pertama kita. Kita akan menggunakan Teloxide, framework yang kuat dan mudah digunakan untuk Rust.

Bab 4: Persiapan Bot Telegram dan Proyek Teloxide

4.1. Mendapatkan Token Bot dari BotFather

Bot Father

Setiap bot Telegram membutuhkan sebuah token unik untuk berinteraksi dengan API Telegram. Kamu bisa mendapatkannya dari BotFather, bot resmi Telegram.

  1. Buka Telegram dan cari @BotFather.
  2. Ketik /newbot dan ikuti instruksi.
  3. Pilih nama untuk bot kamu (misalnya, “Bot Rust Keren”).
  4. Pilih username untuk bot kamu (harus diakhiri dengan “bot”, misalnya, “rust_keren_bot”).
  5. BotFather akan memberimu sebuah token yang terlihat seperti ini: 1234567890:ABC-DEF1234ghIkl-zyx57W2v1u123456. Simpan token ini dengan aman! Ini adalah kunci bot kamu.

Token Bot Telegram

4.2. Membuat Proyek Teloxide Baru

Kita akan membuat proyek baru bernama teloxide_pertama.

cargo new teloxide_pertama

ketika dijalankan akan tampil seperti ini:

$ cargo new teloxide_pertama
    Creating binary (application) `teloxide_pertama` package
note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Kemudian masuk ke direktori tersebut:

cd teloxide_pertama

Buka menggunakan editor favoritmu, misalnya VS Code, Sublime, Zed, atau lainnya.

$ zed .

Saya menggunakan Zed1 untuk editor, karena lebih ringan.

4.3. Menambahkan Dependensi

Buka file Cargo.toml dan tambahkan dependensi yang diperlukan di bagian [dependencies]. Kita membutuhkan teloxide dan tokio (runtime asinkron yang digunakan Teloxide).

# teloxide_pertama/Cargo.toml

[package]
name = "teloxide_pertama"
version = "0.1.0"
edition = "2024"

[dependencies]
# Teloxide: Framework bot Telegram
teloxide = { version = "0.17.0", features = ["macros"] }

# Tokio: Runtime asinkron
tokio = { version =  "1.8", features = ["rt-multi-thread", "macros"] }

# Log: Untuk logging yang lebih baik (opsional, tapi direkomendasikan)
log = "0.4"
pretty_env_logger = "0.5"

Catatan: Pastikan kamu menggunakan versi yang stabil. Versi di atas mungkin sudah usang saat kamu membaca ini, tetapi konsepnya tetap sama.

Saat ini ditulis, sudah menggunakan versi terbaru.

-- Desember 2025

Bab 5: Bot “Hello World” Teloxide

Sekarang, mari kita tulis kode bot paling sederhana.

5.1. Kode Bot Dasar

Jangan di run di sini, pasti akan error. Jalankan pada komputer / vps kamu.

Buka src/main.rs dan ganti isinya dengan kode berikut:

// src/main.rs

use log::info;
use teloxide::{prelude::*, utils::command::BotCommands};

// 1. Definisikan Perintah Bot
// Kita menggunakan macro BotCommands dari Teloxide untuk mendefinisikan perintah
// yang akan kita tangani.
#[derive(BotCommands, Clone)]
#[command(
    rename_rule = "lowercase",
    description = "Perintah yang didukung bot ini:"
)]
enum Command {
    // Perintah /start
    #[command(description = "menampilkan pesan sambutan.")]
    Start,
    // Perintah /help
    #[command(description = "menampilkan informasi bantuan.")]
    Help,
    // Perintah /halo
    #[command(description = "membalas dengan sapaan sederhana.")]
    Halo,
}

// 2. Fungsi Handler untuk Perintah
// Fungsi ini akan dipanggil setiap kali bot menerima perintah yang terdaftar di enum Command.
async fn command_handler(bot: Bot, msg: Message, cmd: Command) -> ResponseResult<()> {
    match cmd {
        Command::Start => {
            bot.send_message(
                msg.chat.id,
                "Selamat datang! Saya adalah bot Rust pertamamu.",
            )
            .await?;
        }
        Command::Help => {
            // BotCommands::descriptions() akan menghasilkan daftar semua perintah
            bot.send_message(msg.chat.id, Command::descriptions().to_string())
                .await?;
        }
        Command::Halo => {
            bot.send_message(msg.chat.id, "Halo juga, kamu! Senang bertemu denganmu.")
                .await?;
        }
    }

    Ok(())
}

// 3. Fungsi Utama (Main)
#[tokio::main] // Gunakan macro tokio::main untuk menjalankan fungsi async
async fn main() {
    // Inisialisasi logger
    pretty_env_logger::init();
    info!("Memulai Bot Teloxide...");

    // Mendapatkan token bot dari environment variable
    // Ini adalah cara yang aman untuk menyimpan token
    let bot = Bot::from_env();

    // Dispatcher: Mekanisme utama Teloxide untuk menerima dan memproses update
    // Filter hanya pesan yang mengandung command dan arahkan ke handler yang kita definisikan.
    let handler = Update::filter_message()
        .filter_command::<Command>()
        .endpoint(command_handler);

    Dispatcher::builder(bot, handler)
        .enable_ctrlc_handler() // Memungkinkan bot berhenti dengan Ctrl+C
        .build()
        .dispatch() // Mulai mendengarkan update
        .await;
}

5.2. Menjalankan Bot

Untuk menjalankan bot, kamu perlu mengatur token bot sebagai environment variable.

Di Linux/macOS:

Ganti YOUR_BOT_TOKEN dengan token yang kamu dapatkan dari BotFather.

export TELOXIDE_TOKEN="YOUR_BOT_TOKEN"
cargo run

Di Windows (PowerShell):

$env:TELOXIDE_TOKEN="YOUR_BOT_TOKEN"
cargo run

Jika keluar error seperti ini:

thread 'main' (124428) panicked at /home/banghasan/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/teloxide-core-0.13.0/src/bot.rs:319:43:
Cannot get the TELOXIDE_TOKEN env variable
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Artinya, kamu belum measukkan TOKEN BOT dengan command export TELOXIDE_TOKEN="YOUR_BOT_TOKEN"

Setelah kamu menjalankan cargo run, kamu akan melihat output log seperti: INFO [teloxide_pertama] Memulai Bot Teloxide....

Jalankan Log muncul info pada shell, ketikkan command ini: `export RUST_LOG=info`

cargo run

Sekarang, buka Telegram, cari bot kamu, dan coba kirim perintah:

  • /start
  • /help
  • /halo

cargo run

Selamat! Kamu telah berhasil membuat dan menjalankan bot Telegram pertamamu dengan Rust dan Teloxide.

=== SAMPAI SINI DULU VERIFIKASINYA ===

Bab 6: Menangani Pesan Teks Biasa dan State

Bot tidak hanya merespons perintah. Bot juga harus bisa merespons pesan teks biasa dan, yang lebih penting, mengingat state (keadaan) pengguna.

6.1. Menangani Pesan Teks Biasa

Kita perlu memodifikasi dispatcher untuk menangani semua jenis pesan, bukan hanya perintah.

Ganti bagian dptree::entry() di main dengan ini:

// teloxide_pertama/src/main.rs (Modifikasi di fungsi main)

// ... (Kode sebelumnya)

async fn handle_message(bot: Bot, msg: Message) -> ResponseResult<()> {
    // Jika pesan adalah perintah, biarkan command_handler yang menanganinya
    if let Ok(cmd) = msg.parse_as_command::<Command>() {
        command_handler(bot, msg, cmd).await?;
        return Ok(());
    }

    // Jika bukan perintah, tangani sebagai pesan teks biasa
    if let Some(text) = msg.text() {
        let balasan = format!("Kamu bilang: \"{}\". Coba ketik /help untuk melihat perintah.", text);
        bot.send_message(msg.chat.id, balasan).await?;
    }

    Ok(())
}

#[tokio::main]
async fn main() {
    pretty_env_logger::init();
    info!("Memulai Bot Teloxide...");

    let bot = Bot::from_env();

    // Dispatcher sekarang akan memproses SEMUA pesan
    Dispatcher::builder(bot, dptree::entry().branch(Update::filter_message().endpoint(handle_message)))
        .enable_ctrlc_handler()
        .build()
        .dispatch()
        .await;
}

Penjelasan:

  • Kita membuat fungsi handler baru handle_message yang menerima Message.
  • Di dalam handle_message, kita mencoba mem-parsing pesan sebagai perintah. Jika berhasil, kita panggil command_handler.
  • Jika gagal, kita anggap itu adalah pesan teks biasa dan membalasnya.
  • Dispatcher kini menggunakan dptree::entry().branch(Update::filter_message().endpoint(handle_message)) untuk mengarahkan semua update pesan ke fungsi handle_message.

6.2. Menangani State Pengguna (FSM - Finite State Machine)

Untuk bot yang lebih kompleks (misalnya, bot kuis, bot pendaftaran), kamu perlu melacak state pengguna. Teloxide sangat mendukung pola FSM (Finite State Machine) melalui crate dptree.

Studi Kasus: Bot Pendaftaran Nama

Kita akan membuat bot yang meminta nama pengguna, menunggu balasan, dan kemudian menyimpan nama tersebut.

Langkah 1: Definisikan State

Tambahkan crate std::sync::Arc dan std::collections::HashMap di bagian use dan definisikan state di luar main.

// teloxide_pertama/src/main.rs (Tambahkan di bagian atas)
use std::{sync::Arc, collections::HashMap};
use teloxide::dispatching::dialogue::{InMemStorage, Dialogue};

// Definisikan State (Keadaan) yang mungkin
#[derive(Clone, Default)]
pub enum State {
    #[default]
    Start, // State awal
    WaitingForName, // State setelah bot meminta nama
}

// Definisikan Tipe Dialogue
type MyDialogue = Dialogue<State, InMemStorage<State>>;
type HandlerResult = Result<(), Box<dyn std::error::Error + Send + Sync>>;

Langkah 2: Modifikasi Handler

Kita akan membuat handler baru yang menggunakan dialogue (state).

// Handler untuk perintah /register
async fn register_command(bot: Bot, dialogue: MyDialogue, msg: Message) -> HandlerResult {
    bot.send_message(msg.chat.id, "Siapa nama kamu?").await?;
    dialogue.update(State::WaitingForName).await?;
    Ok(())
}

// Handler untuk pesan teks biasa yang bergantung pada state
async fn handle_text(bot: Bot, dialogue: MyDialogue, msg: Message, text: String) -> HandlerResult {
    match dialogue.get().await? {
        State::Start => {
            bot.send_message(msg.chat.id, "Saya tidak mengerti. Coba ketik /register untuk memulai pendaftaran.").await?;
        }
        State::WaitingForName => {
            bot.send_message(msg.chat.id, format!("Terima kasih, {}! Nama kamu sudah saya simpan.", text)).await?;
            dialogue.update(State::Start).await?; // Kembali ke state awal
        }
    }
    Ok(())
}

Langkah 3: Modifikasi Dispatcher

Kita perlu mengaktifkan dialogue di dispatcher dan mengatur routing berdasarkan state.

// teloxide_pertama/src/main.rs (Modifikasi di fungsi main)

#[tokio::main]
async fn main() {
    pretty_env_logger::init();
    info!("Memulai Bot Teloxide...");

    let bot = Bot::from_env();

    // Inisialisasi storage untuk dialogue (InMemStorage berarti disimpan di memori)
    let storage = InMemStorage::<State>::new();

    // Dispatcher dengan Dialogue
    Dispatcher::builder(
        bot,
        dptree::entry()
            // 1. Ambil Dialogue
            .enter_dialogue::<Update, InMemStorage<State>, State>()
            // 2. Cabang untuk Perintah
            .branch(
                Update::filter_message()
                    .filter_command::<Command>()
                    .endpoint(register_command), // Hanya /register yang kita tangani di sini
            )
            // 3. Cabang untuk Pesan Teks (berdasarkan state)
            .branch(
                Update::filter_message()
                    .filter_text()
                    .endpoint(handle_text),
            ),
    )
    .dependencies(dptree::deps![storage]) // Masukkan storage sebagai dependency
    .enable_ctrlc_handler()
    .build()
    .dispatch()
    .await;
}

// Catatan: Kamu perlu memodifikasi enum Command untuk menyertakan Register
#[derive(BotCommands, Clone)]
#[command(rename_rule = "lowercase", description = "Perintah yang didukung bot ini:")]
enum Command {
    // ... (Perintah sebelumnya)
    #[command(description = "memulai proses pendaftaran nama.")]
    Register,
}

// Hapus command_handler lama dan ganti dengan yang baru (atau gabungkan)
// Untuk kesederhanaan, kita hanya fokus pada /register dan handle_text
// Pastikan kamu menghapus atau mengganti command_handler lama agar tidak terjadi konflik.
// Untuk e-book ini, kita akan fokus pada pola FSM yang baru.

Dengan pola FSM ini, bot kamu dapat mengingat langkah mana dalam percakapan yang sedang diikuti pengguna, memungkinkan alur interaksi yang jauh lebih kompleks dan terstruktur.


Bagian III akan membawa kita ke fitur-fitur lanjutan, termasuk inline keyboard dan studi kasus yang lebih menarik.


Bagian III: Fitur Lanjutan dan Studi Kasus Menarik

Setelah menguasai dasar-dasar, mari kita eksplorasi fitur-fitur yang membuat bot Telegram menjadi interaktif dan kuat.

Bab 7: Membuat Bot Interaktif dengan Inline Keyboard

Inline Keyboard adalah tombol yang muncul tepat di bawah pesan bot, bukan di area input teks. Ini sangat berguna untuk membuat menu interaktif, survei, atau konfirmasi tindakan.

7.1. Konsep Dasar Inline Keyboard

Setiap tombol inline memiliki dua bagian penting:

  1. Teks: Teks yang terlihat oleh pengguna.
  2. callback_data: Data tersembunyi yang dikirim kembali ke bot saat tombol ditekan.

Studi Kasus: Bot Pemilih Warna Favorit

Kita akan membuat bot yang menawarkan tiga pilihan warna dan merespons berdasarkan pilihan pengguna.

Langkah 1: Definisikan Callback Data

Kita akan menggunakan enum untuk mendefinisikan data yang akan dikirim kembali. Ini adalah praktik terbaik di Rust.

// teloxide_pertama/src/main.rs (Tambahkan di bagian atas)
use serde::{Deserialize, Serialize};
use teloxide::types::{InlineKeyboardMarkup, InlineKeyboardButton};

// Definisikan data yang akan dikirim saat tombol ditekan
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
enum CallbackData {
    PilihWarna(Warna),
}

#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
enum Warna {
    Merah,
    Biru,
    Hijau,
}

Langkah 2: Fungsi Pembuat Keyboard

Buat fungsi yang menghasilkan inline keyboard.

fn buat_keyboard() -> InlineKeyboardMarkup {
    let tombol_merah = InlineKeyboardButton::callback(
        "Merah",
        serde_json::to_string(&CallbackData::PilihWarna(Warna::Merah)).unwrap(),
    );
    let tombol_biru = InlineKeyboardButton::callback(
        "Biru",
        serde_json::to_string(&CallbackData::PilihWarna(Warna::Biru)).unwrap(),
    );
    let tombol_hijau = InlineKeyboardButton::callback(
        "Hijau",
        serde_json::to_string(&CallbackData::PilihWarna(Warna::Hijau)).unwrap(),
    );

    // Kita buat keyboard dengan satu baris berisi tiga tombol
    InlineKeyboardMarkup::new(vec![vec![tombol_merah, tombol_biru, tombol_hijau]])
}

Langkah 3: Handler untuk Mengirim Keyboard

Tambahkan perintah baru /warna dan handler-nya.

// Tambahkan /warna ke enum Command
// ...
    #[command(description = "meminta kamu memilih warna favorit.")]
    Warna,
// ...

// Handler untuk perintah /warna
async fn warna_command(bot: Bot, msg: Message) -> HandlerResult {
    bot.send_message(msg.chat.id, "Pilih warna favoritmu:")
        .reply_markup(buat_keyboard()) // Lampirkan keyboard
        .await?;
    Ok(())
}

Langkah 4: Handler untuk Callback Query

Ini adalah bagian terpenting. Ketika pengguna menekan tombol, bot menerima CallbackQuery, bukan Message. Kita perlu handler terpisah untuk ini.

async fn callback_handler(bot: Bot, q: CallbackQuery) -> HandlerResult {
    // Pastikan ada data callback
    let data = q.data.ok_or_else(|| "Callback query tanpa data")?;

    // Deserialisasi data JSON kembali ke enum CallbackData
    let callback_data: CallbackData = serde_json::from_str(&data)?;

    // Ambil ID chat dan ID pesan asli
    let chat_id = q.message.as_ref().map(|m| m.chat.id).unwrap_or_default();
    let message_id = q.message.as_ref().map(|m| m.id).unwrap_or_default();

    match callback_data {
        CallbackData::PilihWarna(warna) => {
            let balasan = format!("Pilihanmu adalah: {:?}. Terima kasih!", warna);

            // 1. Edit pesan asli untuk menunjukkan hasil
            bot.edit_message_text(chat_id, message_id, balasan)
                .await?;

            // 2. Kirim notifikasi pop-up (opsional)
            bot.answer_callback_query(q.id)
                .text(format!("Kamu memilih {:?}", warna))
                .await?;
        }
    }

    Ok(())
}

Langkah 5: Modifikasi Dispatcher untuk Callback Query

Kita perlu menambahkan cabang baru di dispatcher untuk menangani CallbackQuery.

// teloxide_pertama/src/main.rs (Modifikasi di fungsi main)

#[tokio::main]
async fn main() {
    // ... (Kode inisialisasi)

    Dispatcher::builder(
        bot,
        dptree::entry()
            // Cabang untuk Message (perintah dan teks)
            .branch(
                Update::filter_message()
                    .branch(dptree::entry().filter_command::<Command>().endpoint(warna_command)) // Tambahkan handler /warna
                    // ... (Tambahkan handler perintah lain di sini)
            )
            // Cabang BARU untuk CallbackQuery
            .branch(Update::filter_callback_query().endpoint(callback_handler)),
    )
    // ... (Dependencies dan dispatch)
}

Dengan inline keyboard, kamu telah meningkatkan interaktivitas bot kamu secara signifikan!

Bab 8: Studi Kasus Lanjutan: Bot Pengingat Sederhana

Untuk menunjukkan kekuatan async Rust dan Teloxide, mari kita buat bot yang dapat mengirim pengingat setelah beberapa detik.

8.1. Konsep Asinkron dan tokio::time::sleep

Karena Rust menggunakan model asinkron, kita dapat “tidur” (sleep) tanpa memblokir seluruh bot.

Langkah 1: Tambahkan Perintah Pengingat

Tambahkan perintah /ingatkan <waktu_detik> <pesan> ke enum Command.

// ...
    #[command(description = "mengirim pengingat setelah beberapa detik.", parse_with = "split")]
    Ingatkan {
        waktu_detik: u64,
        pesan: String,
    },
// ...

Langkah 2: Handler Pengingat

use std::time::Duration;

async fn ingatkan_command(bot: Bot, msg: Message, waktu_detik: u64, pesan: String) -> HandlerResult {
    let chat_id = msg.chat.id;

    bot.send_message(chat_id, format!("Oke, saya akan mengingatkanmu dalam {} detik.", waktu_detik)).await?;

    // Ini adalah kunci: kita menggunakan tokio::time::sleep
    // Bot akan "tidur" di sini, tetapi thread utama tidak akan terblokir.
    tokio::time::sleep(Duration::from_secs(waktu_detik)).await;

    // Setelah tidur, kirim pesan pengingat
    bot.send_message(chat_id, format!("🔔 PENGINGAT: {}", pesan)).await?;

    Ok(())
}

Langkah 3: Modifikasi Dispatcher

Pastikan ingatkan_command ditambahkan ke cabang perintah di dispatcher.

// teloxide_pertama/src/main.rs (Modifikasi di fungsi main)

// ...
            .branch(
                Update::filter_message()
                    .filter_command::<Command>()
                    .endpoint(|bot: Bot, msg: Message, cmd: Command| async move {
                        match cmd {
                            Command::Warna => warna_command(bot, msg).await,
                            Command::Ingatkan { waktu_detik, pesan } => ingatkan_command(bot, msg, waktu_detik, pesan).await,
                            // ... (Perintah lain)
                            _ => Ok(()),
                        }
                    })
            )
// ...

Dengan studi kasus ini, kamu telah melihat bagaimana Rust dan Teloxide menangani tugas-tugas asinkron dengan elegan, yang merupakan fondasi untuk bot yang lebih kompleks seperti bot penjadwalan atau bot yang melakukan polling API eksternal.


Bagian IV akan membahas integrasi basis data, yang merupakan langkah penting untuk bot yang perlu menyimpan data secara permanen.


Bagian IV: Persistensi Data dengan SQLite

Bot yang berguna harus mampu menyimpan data. Kita akan menggunakan SQLite, basis data ringan yang sangat cocok untuk aplikasi bot karena tidak memerlukan server terpisah. Kita akan menggunakan crate sqlx yang merupakan ORM (Object-Relational Mapper) asinkron yang modern untuk Rust.

Bab 9: Alternatif Deployment: Menggunakan Webhook

Sejauh ini, kita telah menggunakan metode Long Polling, di mana bot secara berkala “bertanya” kepada server Telegram apakah ada update baru. Metode ini sederhana dan cocok untuk pengembangan.

Namun, untuk bot yang lebih besar dan lebih responsif, metode Webhook lebih disukai. Dengan Webhook, kamu memberi tahu Telegram sebuah URL, dan Telegram akan mengirimkan update ke URL tersebut secara real-time (seperti push notification).

9.1. Kelebihan Webhook

  • Responsivitas Instan: Bot merespons segera setelah update diterima.
  • Efisiensi Sumber Daya: Bot tidak perlu terus-menerus melakukan polling ke server Telegram.
  • Skalabilitas: Lebih mudah diskalakan untuk menangani volume lalu lintas yang tinggi.

9.2. Persiapan Webhook

Untuk menggunakan Webhook, kamu memerlukan:

  1. Server Web: Bot kamu harus berjalan di server yang dapat menerima permintaan HTTP POST.
  2. URL Publik (HTTPS): URL server kamu harus dapat diakses publik dan menggunakan protokol HTTPS.

Dalam contoh ini, kita akan menggunakan crate axum (sebuah framework web populer di Rust) bersama dengan Teloxide.

9.3. Menambahkan Dependensi untuk Webhook

Buka Cargo.toml dan tambahkan axum dan hyper.

# teloxide_pertama/Cargo.toml

[dependencies]
# ... (Dependensi Teloxide, Tokio, dll.)

# Axum: Web framework untuk server Webhook
axum = "0.7"
hyper = { version = "1.0", features = ["full"] }
tokio = { version = "1.35", features = ["full"] } # Pastikan fitur "full" aktif

9.4. Implementasi Kode Webhook

Kita akan membuat endpoint HTTP yang akan menerima update dari Telegram.

// teloxide_pertama/src/main.rs (Modifikasi di fungsi main)

use axum::{
    extract::State,
    routing::post,
    Json, Router,
};
use hyper::server::conn::http1;
use hyper::service::service_fn;
use hyper::{body::Incoming, Request};
use std::net::SocketAddr;
use teloxide::dispatching::update_listeners::webhooks;
use teloxide::update_listeners::webhooks::Options;
use teloxide::types::Update;

// ... (Semua use, enum Command, dan handler lainnya tetap sama)

// Fungsi utama untuk menjalankan bot dengan Webhook
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    // ... (Inisialisasi logger, load .env, dll.)

    let bot = Bot::from_env();

    // 1. Tentukan URL Webhook
    // Ganti dengan URL publik server kamu. Misalnya: https://namadomainmu.com/webhook/
    let url = std::env::var("WEBHOOK_URL").expect("WEBHOOK_URL harus diatur");
    let port: u16 = std::env::var("PORT")
        .unwrap_or_else(|_| "8080".to_string())
        .parse()?;
    let addr = SocketAddr::from(([0, 0, 0, 0], port));

    // 2. Buat Listener Webhook
    let (mut listener, stop_flag) = webhooks::axum(bot.clone(), Options::new(url.parse()?)).await?;

    // 3. Setup Dispatcher (Sama seperti Long Polling)
    let handler = dptree::entry()
        // ... (Semua cabang handler kamu, seperti filter_command, filter_callback_query, dll.)
        // Untuk contoh ini, kita akan menggunakan handler sederhana:
        .branch(Update::filter_message().endpoint(|bot: Bot, msg: Message| async move {
            bot.send_message(msg.chat.id, "Webhook berhasil menerima pesan!").await?;
            ResponseResult::Ok(())
        }));

    // 4. Buat Service Axum
    let app = Router::new()
        .route("/", post(handle_update))
        .with_state(listener.clone()); // Masukkan listener sebagai state Axum

    // Handler Axum untuk menerima Update
    async fn handle_update(
        State(mut listener): State<webhooks::Listener<Arc<Bot>>>,
        Json(update): Json<Update>,
    ) -> () {
        // Kirim update ke dispatcher Teloxide
        listener.feed(update).await
    }

    // 5. Jalankan Server Webhook
    info!("Memulai server Webhook di {}", addr);

    axum::serve(tokio::net::TcpListener::bind(&addr).await?, app.into_make_service())
        .await?;

    Ok(())
}

9.5. Langkah-Langkah Deployment Webhook

  1. Atur Environment Variable: Pastikan kamu mengatur WEBHOOK_URL dan PORT di file .env.
    # .env
    TELOXIDE_TOKEN="YOUR_BOT_TOKEN"
    WEBHOOK_URL="https://namadomainmu.com/webhook/"
    PORT=8080
    
  2. Deployment: Deploy aplikasi Rust kamu ke server publik (misalnya, Heroku, AWS, atau VPS).
  3. Pengaturan Webhook: Saat bot dijalankan, Teloxide akan secara otomatis memanggil setWebhook ke Telegram dengan URL yang kamu berikan.

Dengan Webhook, kamu telah melangkah ke level profesional dalam deployment bot Telegram!


Bab 10: Integrasi sqlx dan SQLite

10.1. Menambahkan Dependensi

Buka Cargo.toml dan tambahkan dependensi berikut. Perhatikan bahwa kita perlu mengaktifkan fitur runtime-tokio-rustls dan sqlite untuk sqlx.

teloxide_pertama/Cargo.toml

[dependencies]
... (Dependensi sebelumnya)

SQLx: ORM asinkron untuk Rust
sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "sqlite", "macros"] }
dotenvy = "0.15" # Untuk memuat environment variable dari file .env

10.2. Setup Database dan Migrasi

sqlx memerlukan tool sqlx-cli untuk menjalankan migrasi (pembuatan skema tabel).

Langkah 1: Instal sqlx-cli

cargo install sqlx-cli

Langkah 2: Buat File .env

Buat file .env di root proyek kamu untuk menyimpan path ke basis data SQLite.

# .env
DATABASE_URL=sqlite:bot_data.db

Langkah 3: Buat Migrasi

Kita akan membuat tabel sederhana untuk menyimpan catatan (seperti to-do list).

sqlx migrate add create_notes_table

Perintah ini akan membuat direktori migrations/ dan sebuah file dengan timestamp di dalamnya. Buka file tersebut (misalnya, migrations/20251201000000_create_notes_table.sql) dan isi dengan skema tabel:

-- Up migration
CREATE TABLE notes (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    chat_id BIGINT NOT NULL,
    content TEXT NOT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

-- Down migration
DROP TABLE notes;

Langkah 4: Jalankan Migrasi

cargo sqlx migrate run

Ini akan membuat file bot_data.db dan tabel notes di dalamnya.

10.3. Koneksi Database ke Bot

Kita perlu membuat pool koneksi basis data dan menyediakannya sebagai dependency untuk handler bot.

Langkah 1: Modifikasi main.rs

Tambahkan use yang diperlukan dan load .env.

// teloxide_pertama/src/main.rs (Tambahkan di bagian atas)
use sqlx::{SqlitePool, migrate::Migrator};
use dotenvy::dotenv;
use std::path::Path;

// ... (use lainnya)

// Definisikan tipe Pool
type DbPool = SqlitePool;

// ... (Kode lainnya)

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    dotenv().ok(); // Muat file .env
    pretty_env_logger::init();
    info!("Memulai Bot Teloxide...");

    let bot = Bot::from_env();

    // 1. Inisialisasi Pool Koneksi Database
    let database_url = std::env::var("DATABASE_URL")
        .expect("DATABASE_URL harus diatur di .env");

    let pool = SqlitePool::connect(&database_url).await?;

    // 2. Jalankan Migrasi (opsional, tapi bagus untuk memastikan skema terbaru)
    // Ini akan menjalankan migrasi yang belum diterapkan
    Migrator::new(Path::new("./migrations"))
        .await?
        .run(&pool)
        .await?;

    // ... (Dispatcher setup)

    // Masukkan pool sebagai dependency
    Dispatcher::builder(
        bot,
        dptree::entry()
            // ... (Cabang-cabang lainnya)
    )
    .dependencies(dptree::deps![pool]) // Masukkan pool di sini
    .enable_ctrlc_handler()
    .build()
    .dispatch()
    .await;

    Ok(())
}

Bab 11: Implementasi CRUD+List

Kita akan membuat bot yang dapat menyimpan, melihat, memperbarui, dan menghapus catatan.

11.1. Definisikan Perintah CRUD

Tambahkan perintah berikut ke enum Command:

// ...
    #[command(description = "menambahkan catatan baru.", parse_with = "split")]
    Tambah { content: String },
    #[command(description = "melihat semua catatan.")]
    List,
    #[command(description = "memperbarui catatan berdasarkan ID.", parse_with = "split")]
    Update { id: i64, content: String },
    #[command(description = "menghapus catatan berdasarkan ID.")]
    Hapus { id: i64 },
// ...

11.2. Handler untuk CREATE (Tambah)

async fn tambah_note(bot: Bot, msg: Message, pool: DbPool, content: String) -> HandlerResult {
    let chat_id = msg.chat.id.0; // Ambil ID chat sebagai i64

    sqlx::query!(
        "INSERT INTO notes (chat_id, content) VALUES (?, ?)",
        chat_id,
        content
    )
    .execute(&pool)
    .await?;

    bot.send_message(msg.chat.id, "✅ Catatan berhasil ditambahkan!").await?;
    Ok(())
}

11.3. Handler untuk READ (List)

// Struktur untuk memetakan hasil query
#[derive(Debug)]
struct Note {
    id: i64,
    content: String,
    created_at: String,
}

async fn list_notes(bot: Bot, msg: Message, pool: DbPool) -> HandlerResult {
    let chat_id = msg.chat.id.0;

    let notes = sqlx::query_as!(
        Note,
        "SELECT id, content, created_at FROM notes WHERE chat_id = ? ORDER BY id DESC",
        chat_id
    )
    .fetch_all(&pool)
    .await?;

    if notes.is_empty() {
        bot.send_message(msg.chat.id, "Kamu belum punya catatan. Coba /tambah <catatanmu>.").await?;
        return Ok(());
    }

    let mut response = String::from("📝 **Daftar Catatanmu:**\n\n");

    for note in notes {
        response.push_str(&format!("**ID:** `{}`\n**Isi:** {}\n*Dibuat: {}*\n\n",
            note.id,
            note.content,
            note.created_at.split('.').next().unwrap_or(&note.created_at) // Hapus milidetik
        ));
    }

    bot.send_message(msg.chat.id, response)
        .parse_mode(teloxide::types::ParseMode::Markdown)
        .await?;

    Ok(())
}

11.4. Handler untuk UPDATE

async fn update_note(bot: Bot, msg: Message, pool: DbPool, id: i64, content: String) -> HandlerResult {
    let chat_id = msg.chat.id.0;

    let result = sqlx::query!(
        "UPDATE notes SET content = ? WHERE id = ? AND chat_id = ?",
        content,
        id,
        chat_id
    )
    .execute(&pool)
    .await?;

    if result.rows_affected() > 0 {
        bot.send_message(msg.chat.id, format!("✅ Catatan ID `{}` berhasil diperbarui.", id)).await?;
    } else {
        bot.send_message(msg.chat.id, format!("❌ Catatan ID `{}` tidak ditemukan atau bukan milikmu.", id)).await?;
    }

    Ok(())
}

11.5. Handler untuk DELETE (Hapus)

async fn hapus_note(bot: Bot, msg: Message, pool: DbPool, id: i64) -> HandlerResult {
    let chat_id = msg.chat.id.0;

    let result = sqlx::query!(
        "DELETE FROM notes WHERE id = ? AND chat_id = ?",
        id,
        chat_id
    )
    .execute(&pool)
    .await?;

    if result.rows_affected() > 0 {
        bot.send_message(msg.chat.id, format!("✅ Catatan ID `{}` berhasil dihapus.", id)).await?;
    } else {
        bot.send_message(msg.chat.id, format!("❌ Catatan ID `{}` tidak ditemukan atau bukan milikmu.", id)).await?;
    }

    Ok(())
}

11.6. Mengintegrasikan Handler ke Dispatcher

Terakhir, kita perlu menambahkan handler CRUD ini ke dispatcher utama.

// teloxide_pertama/src/main.rs (Modifikasi di fungsi main)

// ... (Di dalam Dispatcher::builder)

            .branch(
                Update::filter_message()
                    .filter_command::<Command>()
                    .endpoint(|bot: Bot, msg: Message, cmd: Command, pool: DbPool| async move {
                        match cmd {
                            // ... (Perintah sebelumnya)
                            Command::Tambah { content } => tambah_note(bot, msg, pool, content).await,
                            Command::List => list_notes(bot, msg, pool).await,
                            Command::Update { id, content } => update_note(bot, msg, pool, id, content).await,
                            Command::Hapus { id } => hapus_note(bot, msg, pool, id).await,
                            _ => Ok(()),
                        }
                    })
            )
// ...

Dengan implementasi ini, bot kamu kini memiliki kemampuan untuk menyimpan data secara permanen, menjadikannya aplikasi yang jauh lebih fungsional dan canggih.


Bagian V: Penutup dan Sumber Belajar

Bab 12: Kesimpulan dan Langkah Selanjutnya

Selamat! Kamu telah menyelesaikan perjalanan dari instalasi Rust hingga membangun bot Telegram yang canggih dengan Teloxide dan integrasi basis data SQLite.

Kamu telah mempelajari:

  • Dasar-dasar Rust, termasuk ownership dan mutability.
  • Cara menyiapkan proyek Teloxide dan menggunakan cargo.
  • Implementasi bot “Hello World” dan penanganan perintah.
  • Penggunaan Finite State Machine (FSM) untuk mengelola state percakapan.
  • Membuat antarmuka interaktif dengan Inline Keyboard.
  • Mengintegrasikan basis data SQLite menggunakan sqlx untuk operasi CRUD+List.

Bot yang kamu buat ini adalah fondasi yang kuat. Dari sini, kamu bisa mengembangkan bot yang lebih kompleks, seperti bot manajemen grup, bot e-commerce sederhana, atau bot yang berinteraksi dengan API eksternal lainnya.

Bab 13: Referensi dan Sumber Belajar Tambahan

Perjalanan belajar tidak berhenti di sini. Berikut adalah beberapa sumber daya penting yang dapat kamu gunakan untuk memperdalam pengetahuanmu tentang Rust dan Teloxide.

Sumber DayaDeskripsiTautan
The Rust Programming Language (Book)“Buku Rust” resmi. Sumber terbaik untuk mempelajari Rust secara mendalam.https://doc.rust-lang.org/book/
Teloxide DocumentationDokumentasi resmi Teloxide. Sangat detail dan memiliki banyak contoh.https://docs.rs/teloxide/
SQLx DocumentationDokumentasi resmi crate sqlx. Penting untuk memahami fitur basis data asinkron.https://docs.rs/sqlx/
Rust by ExampleBelajar Rust melalui contoh-contoh kode yang dapat kamu jalankan.https://doc.rust-lang.org/rust-by-example/
Asynchronous Programming in RustPanduan untuk memahami konsep async/await di Rust.https://rust-lang.github.io/async-book/

Semoga e-book ini menjadi panduan yang berharga dalam petualanganmu membangun bot Telegram dengan Rust! Selamat berkarya!


  1. https://zed.dev/ is a minimal code editor crafted for speed and collaboration with humans and AI

Panduan Setup VPS untuk Pemula

Daftar Isi


☁️ Apa Itu VPS?

VPS adalah singkatan dari Virtual Private Server, yang secara harfiah berarti “Server Pribadi Virtual.” VPS adalah metode hosting yang membagi satu server fisik yang kuat menjadi beberapa mesin virtual yang terisolasi dan independen.

Kamu bisa membayangkan konsep ini sebagai sebuah apartemen di dalam gedung besar:

KomponenAnaloginyaFungsi
Server FisikGedung ApartemenHardware fisik yang sangat besar (CPU, RAM, Storage) yang dimiliki oleh penyedia hosting.
VPSUnit Apartemen PribadiMesin virtual yang diisolasi di dalam server fisik. Resource kamu dijamin hanya untuk kamu.
Teknologi VirtualisasiDinding dan Pintu UnitTeknologi (seperti KVM) yang memastikan sumber daya dan aktivitas satu VPS tidak akan mengganggu VPS lain.

✨ Fitur Utama dan Manfaat VPS

  1. Virtual (Terbagi)

    VPS adalah software yang berjalan di atas hardware fisik, tetapi karena teknologi virtualisasi, VPS berfungsi penuh layaknya server fisik yang terpisah. Ini memungkinkan pembagian resource fisik secara efisien.

  2. Private (Pribadi dan Terisolasi)

    • Akses Root Penuh: Kamu mendapatkan akses root atau administrator penuh. Ini berarti kamu memiliki kontrol penuh untuk menginstal Sistem Operasi, software, dan mengkonfigurasi firewall (seperti UFW) sesuai kebutuhan kamu.

    • Isolasi Resource: Sumber daya yang dialokasikan (misalnya


Kegunaan dan Fungsi VPS

  1. Hosting Website dan Aplikasi Web
  • Menjalankan website dengan traffic tinggi
  • Hosting multiple websites
  • Aplikasi web yang membutuhkan konfigurasi khusus
  1. Development dan Testing
  • Environment untuk development
  • Testing aplikasi sebelum production
  • CI/CD pipelines
  1. Database Server
  • MySQL, PostgreSQL, MongoDB
  • Isolated database environment
  • Backup dan recovery control
  1. Application Server
  • API servers
  • Microservices
  • Backend applications (Node.js, Python, Go, dll)
  1. Bot dan Automation
  • Telegram bots
  • Discord bots
  • Web scraping
  • Scheduled tasks (cron jobs)
  1. Game Server
  • Minecraft server
  • Counter-Strike server
  • Private game servers
  1. VPN Server
  • Private VPN untuk keamanan
  • Bypass geo-restrictions
  • Secure remote access
  1. Mail Server
  • Email server pribadi
  • Mailing list management
  1. File Storage dan Backup
  • Cloud storage pribadi (Nextcloud)
  • Backup server
  • File sharing
  1. Learning dan Eksperimen
  • Belajar Linux administration
  • Eksperimen dengan teknologi baru
  • Practice DevOps

Perbedaan VPS dengan Hosting Lainnya

🆚 Komparasi: VPS vs. Shared Hosting

FiturVPS (Virtual Private Server)Shared Hosting
DefinisiSatu server fisik dibagi menjadi beberapa mesin virtual yang terisolasi secara mandiri.Satu server fisik dibagi dan digunakan bersama oleh ratusan pengguna.
Isolasi Sumber DayaTinggi. Sumber daya (CPU, RAM, disk) dijamin dan didedikasikan hanya untuk kamu.Rendah. Sumber daya dibagi. Kinerja kamu dapat terpengaruh oleh traffic pengguna lain (bad neighbor effect).
Akses & KontrolPenuh (Akses Root/Admin). Kamu memiliki kontrol penuh atas sistem operasi, software, firewall, dan konfigurasi.Terbatas. Kamu hanya dapat mengelola file dan database melalui panel kontrol (cPanel/Plesk).
Kinerja & StabilitasSangat Baik. Kinerja lebih stabil dan konsisten karena resource dijamin.Biasa. Kinerja dapat berfluktuasi saat server ramai (peak hours).
KeamananTinggi. Kamu bertanggung jawab penuh atas keamanan (firewall, patching), dan VPS kamu terisolasi dari pengguna lain.Menengah. Keamanan diurus oleh penyedia hosting, tetapi kerentanan satu pengguna dapat memengaruhi pengguna lain di server yang sama.
KustomisasiPenuh. Kamu bebas menginstal stack (misalnya Node.js, Python, Java), konfigurasi server web (Nginx, Apache), dan sistem operasi pilihan.Terbatas. Hanya software yang sudah terinstal oleh penyedia hosting yang dapat digunakan (umumnya PHP/MySQL).
SkalabilitasMudah ditingkatkan (Upgradable). Kamu dapat dengan mudah menambah RAM, CPU, atau disk space sesuai kebutuhan.Terbatas. Peningkatan hanya sebatas paket yang ditawarkan oleh penyedia hosting.
HargaMenengah. Lebih mahal daripada Shared Hosting, tetapi menawarkan nilai yang jauh lebih baik.Paling Murah. Pilihan paling ekonomis.
Target PenggunaAplikasi yang tumbuh, website e-commerce, developer, traffic menengah ke atas, atau layanan yang membutuhkan lingkungan khusus.Website pribadi, blog baru, atau project kecil dengan traffic sangat rendah.

Kapan kamu Membutuhkan VPS?

kamu membutuhkan VPS jika:

✅ Website kamu mulai lambat di shared hosting
✅ Membutuhkan software/library khusus yang tidak tersedia di shared hosting
✅ Ingin menjalankan aplikasi 24/7 (bot, scraper, dll)
✅ Membutuhkan kontrol penuh atas server configuration
✅ Traffic website meningkat signifikan
✅ Membutuhkan multiple IP addresses
✅ Ingin belajar server administration
✅ Membutuhkan environment development yang mirip production


Kesimpulan Ringkas

Jika kamu membutuhkan kontrol penuh, kinerja stabil, dan fleksibilitas untuk menjalankan aplikasi yang unik atau website dengan traffic yang signifikan, VPS adalah pilihan yang lebih tepat.

Jika kamu baru memulai dan membutuhkan solusi yang paling murah dan mudah tanpa memerlukan konfigurasi khusus, Shared Hosting adalah pilihan awal yang baik.

Tip

Jika kamu butuh VPS murah meriah dan sudah teruji pemakaiannya, cek webnya banghasan.com1

Tidak sampai 200 ribu per TAHUN bisa untuk belajar, uji coba, produksi dan kebutuhan lainnya. Apalagi hanya untuk bot Telegram.


Panduan Setup VPS Pertama Kali

Panduan ini menggunakan Ubuntu 24.04 LTS sebagai contoh, namun sebagian besar perintah juga berlaku untuk distro Linux lainnya.

1. Akses VPS Pertama Kali

Setelah membeli VPS, kamu akan mendapatkan:

  • IP Address
  • Username (biasanya root)
  • Password atau SSH key

Login via SSH

ssh root@IP_ADDRESS_VPS

Contoh:

ssh root@192.168.1.100

Jika menggunakan SSH key:

ssh -i /path/to/private_key root@IP_ADDRESS_VPS

💡 Tip: Jika pertama kali connect, kamu akan diminta konfirmasi fingerprint. Ketik yes.


2. Update dan Upgrade Sistem

Langkah pertama yang WAJIB dilakukan adalah update sistem:

# Update package list
apt update

# Upgrade semua package
apt upgrade -y

# Upgrade distribusi (opsional)
apt dist-upgrade -y

# Hapus package yang tidak diperlukan
apt autoremove -y

# Bersihkan cache
apt autoclean

⚠️ Penting: Selalu update sistem secara berkala untuk patch keamanan!


3. Membuat User Baru (Non-Root)

Jangan pernah menggunakan root untuk operasi sehari-hari. Buat user baru:

# Buat user baru (ganti 'namauser' dengan username kamu)
adduser namauser

# Tambahkan user ke grup sudo
usermod -aG sudo namauser

kamu akan diminta mengisi:

  • Password (pilih password yang kuat!)
  • Full Name (opsional)
  • Room Number, dll (bisa di-skip dengan Enter)

Test User Baru

# Switch ke user baru
su - namauser

# Test sudo access
sudo apt update

4. Konfigurasi SSH untuk Keamanan

A. Setup SSH Key Authentication (Sangat Direkomendasikan)

Di komputer lokal kamu (bukan di VPS):

# Generate SSH key pair (jika belum punya)
ssh-keygen -t ed25519 -C "email@example.com"

# Copy public key ke VPS
ssh-copy-id namauser@IP_ADDRESS_VPS

Atau manual:

# Di komputer lokal, lihat public key
cat ~/.ssh/id_ed25519.pub

Copy output-nya, lalu di VPS:

# Login sebagai user baru
su - namauser

# Buat direktori .ssh
mkdir -p ~/.ssh
chmod 700 ~/.ssh

# Buat file authorized_keys
nano ~/.ssh/authorized_keys
# Paste public key kamu, save (Ctrl+X, Y, Enter)

# Set permission
chmod 600 ~/.ssh/authorized_keys

B. Mengganti Port SSH (Keamanan Tambahan)

Mengganti port SSH dari default (22) ke port lain dapat mengurangi serangan brute-force otomatis. Ini adalah salah satu bentuk security through obscurity - bukan solusi utama, tapi lapisan keamanan tambahan yang efektif.

Tujuan penggantian port SSH:

  • 🛡️ Mengurangi serangan bot otomatis yang menargetkan port 22
  • 📉 Mengurangi spam di log server
  • 🔒 Lapisan keamanan tambahan (bukan pengganti password/key yang kuat)
  • 🎯 Membuat server lebih “tersembunyi” dari scanner otomatis

Langkah-langkah:

# Backup konfigurasi original
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup

# Edit konfigurasi SSH
sudo nano /etc/ssh/sshd_config

Ubah/tambahkan setting berikut:

# Ubah port SSH (pilih port antara 1024-65535, hindari port umum)
Port 2222

# Disable empty passwords
PermitEmptyPasswords no

# Limit authentication attempts
MaxAuthTries 3

# Disable X11 forwarding (jika tidak dibutuhkan)
X11Forwarding no

PENTING untuk Ubuntu 24.04: Sejak Ubuntu 24.04, SSH menggunakan socket systemd. kamu juga harus mengubah port di file socket:

# Edit SSH socket configuration
sudo nano /lib/systemd/system/ssh.socket

Cari baris ListenStream=22 dan ubah menjadi:

[Socket]
ListenStream=2222
Accept=no

Reload systemd dan restart SSH:

# Reload systemd daemon
sudo systemctl daemon-reload

# Restart SSH socket
sudo systemctl restart ssh.socket

# Restart SSH service
sudo systemctl restart sshd

# Verify SSH is listening on new port
sudo ss -tulpn | grep 2222

⚠️ PERINGATAN: Sebelum logout, test koneksi SSH di terminal baru dengan port baru!

Test koneksi baru (jangan logout dari session lama dulu):

# Di terminal baru
ssh -p 2222 namauser@IP_ADDRESS_VPS

Jika berhasil, kamu bisa lanjut ke hardening SSH.

C. Hardening SSH Configuration

Setelah yakin SSH key berfungsi, tambahkan keamanan ekstra:

sudo nano /etc/ssh/sshd_config

Tambahkan/ubah:

# Hanya izinkan user tertentu (opsional)
AllowUsers namauser

# Disable password authentication (hanya jika sudah setup SSH key!)
PasswordAuthentication no

# Disable challenge-response passwords
KbdInteractiveAuthentication no

Restart SSH:

sudo systemctl restart sshd

5. Disable Root Login

Setelah berhasil login dengan akun baru dan memastikan akun tersebut memiliki akses sudo, disable login root untuk keamanan maksimal.

# Edit SSH config
sudo nano /etc/ssh/sshd_config

Ubah baris berikut:

# Disable root login
PermitRootLogin no

Restart SSH service:

sudo systemctl restart sshd

⚠️ PENTING: Pastikan kamu sudah:

  1. Membuat user baru dengan akses sudo
  2. Berhasil login dengan user baru
  3. Test sudo berfungsi dengan baik

Jangan disable root login sebelum memastikan hal di atas, atau kamu bisa terkunci dari server!

Test di terminal baru:

# Ini seharusnya DITOLAK
ssh root@IP_ADDRESS_VPS

# Ini seharusnya BERHASIL
ssh -p 2222 namauser@IP_ADDRESS_VPS

6. Setup Firewall (UFW)

🛡️ Pentingnya Menginstal UFW di VPS

Menginstal dan mengaktifkan UFW (Uncomplicated Firewall) adalah langkah keamanan fundamental yang wajib kamu lakukan segera setelah menyiapkan VPS. UFW dirancang agar sangat mudah digunakan dan dikonfigurasi, berfungsi sebagai lapisan pertahanan pertama VPS kamu.

1. Memblokir Akses Tidak Sah (Isolasi Jaringan)
  • Prinsip Dasar: UFW bertindak sebagai penjaga pintu virtual. Secara default, UFW diatur untuk memblokir semua koneksi masuk (DENY) kecuali yang secara eksplisit kamu izinkan (ALLOW).
  • Manfaat: Hal ini memastikan bahwa hanya layanan yang kamu inginkan (misalnya, Port 22 untuk SSH, Port 80/443 untuk web) yang dapat diakses dari luar. Semua port dan layanan yang tidak terpakai akan tertutup, mencegah scanner dan serangan acak.
2. Mengurangi Permukaan Serangan (Reducing Attack Surface)
  • Setiap port yang terbuka adalah titik masuk potensial bagi penyerang. Jika kamu memiliki banyak layanan latar belakang yang berjalan, setiap layanan adalah risiko.
  • UFW memungkinkan kamu secara selektif membuka hanya port yang benar-benar dibutuhkan. Dengan membatasi port yang terbuka, kamu secara drastis mengurangi area yang dapat dieksploitasi oleh penyerang, sehingga memperkuat keamanan VPS kamu.
3. Keamanan Khusus SSH (Mencegah Brute-Force)
  • Koneksi SSH (Port 22) adalah gerbang utama kamu. Penyerang sering menggunakan serangan brute-force untuk mencoba masuk berulang kali.
  • UFW memungkinkan kamu untuk mengatur batasan (limit) koneksi berdasarkan alamat IP. Misalnya, kamu dapat membatasi upaya koneksi SSH dari IP yang sama menjadi hanya

Installasi

# Install UFW (biasanya sudah terinstall di Ubuntu)
sudo apt install ufw -y

# Set default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Allow SSH (PENTING! Sesuaikan dengan port SSH kamu)
sudo ufw allow 2222/tcp

# Allow HTTP dan HTTPS (jika hosting website)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Allow port lain sesuai kebutuhan
# Contoh untuk aplikasi Node.js di port 3000:
# sudo ufw allow 3000/tcp

# Enable firewall
sudo ufw enable

# Check status
sudo ufw status verbose

⚠️ PENTING: Pastikan port SSH sudah di-allow sebelum enable firewall!

🛡️ Perintah Dasar UFW (Uncomplicated Firewall)

1. Perintah Status dan Kontrol Dasar

PerintahFungsiDeskripsi
sudo ufw statusPeriksa StatusMenampilkan status UFW (active atau inactive) dan daftar semua aturan yang saat ini aktif. Gunakan sudo ufw status verbose untuk detail lebih lanjut.
sudo ufw enableAktifkan FirewallMengaktifkan UFW. PENTING: Pastikan Port SSH sudah diizinkan sebelum menjalankan ini.
sudo ufw disableNonaktifkan FirewallMenghentikan UFW dan menghapus semua aturan yang diterapkan.
sudo ufw default deny incomingAturan Default (Masuk)Mengatur kebijakan default untuk koneksi masuk (incoming) menjadi Ditolak/Blokir (standar keamanan terbaik).
sudo ufw default allow outgoingAturan Default (Keluar)Mengatur kebijakan default untuk koneksi keluar (outgoing) menjadi Diizinkan.

2. Perintah Mengelola Aturan (Mengizinkan/Membatasi)

PerintahFungsiContoh Penggunaan
sudo ufw allow 22Izinkan PortMengizinkan semua koneksi masuk pada Port 22 (SSH).
sudo ufw allow 80/tcpIzinkan Protokol SpesifikMengizinkan koneksi TCP masuk pada Port 80 (HTTP).
sudo ufw allow httpIzinkan Berdasarkan LayananMengizinkan koneksi untuk layanan bernama HTTP (Port 80).
sudo ufw deny 25Blokir PortMemblokir semua koneksi masuk pada Port 25 (SMTP).
sudo ufw limit sshBatasi SSHMengatur batasan (rate limit) pada koneksi SSH untuk membantu mencegah serangan brute-force.

3. Perintah Mengelola Alamat IP

PerintahFungsiContoh Penggunaan
sudo ufw allow from 192.168.1.1Izinkan IP TertentuMengizinkan semua koneksi masuk hanya dari Alamat IP 192.168.1.1.
sudo ufw allow from 192.168.1.0/24 to any port 22Izinkan Subnet ke PortMengizinkan SSH dari seluruh subnet 192.168.1.0/24.

4. Perintah Penghapusan dan Reset

PerintahFungsiDeskripsi
sudo ufw delete allow 22Hapus AturanMenghapus aturan yang mengizinkan koneksi pada Port 22.
sudo ufw resetReset TotalMengatur ulang UFW ke pengaturan default dan menonaktifkannya. PERINGATAN: Ini akan menghapus semua aturan yang sudah kamu buat.

7. Install Software Dasar

A. Build Essential dan Tools

🛠️ Pentingnya Menginstal Build Essential dan Tools

Paket Build Essential adalah kumpulan alat (tools) dan utilitas yang sangat dasar dan mendasar yang dibutuhkan oleh sistem operasi Linux agar mampu mengompilasi (membangun) perangkat lunak dari kode sumber (source code).

Meskipun kamu mungkin berencana menginstal sebagian besar aplikasi menggunakan manajer paket (package manager) seperti apt atau yum, paket ini menjadi sangat vital karena alasan-alasan berikut:

  1. Kompilasi Kode Sumber

    Apa itu? Banyak program, driver, dan utilitas yang kamu butuhkan untuk VPS mungkin tidak tersedia sebagai paket yang sudah dikompilasi (paket .deb atau .rpm). Kamu mungkin perlu mengompilasinya sendiri dari kode sumber.

    Pentingnya: Build Essential berisi alat utama seperti GCC (GNU Compiler Collection), G++, dan Make. Tanpa alat-alat ini, VPS kamu tidak memiliki kemampuan untuk menerjemahkan kode sumber menjadi program yang bisa dijalankan.

  2. Membangun Dependensi Aplikasi (Khusus Node.js/Python)

    Ini sangat relevan jika kamu menggunakan Node.js (atau Python) di VPS kamu:

    • Node.js Native Modules: Banyak paket Node.js (sering disebut native modules atau bindings) yang sangat populer dan penting, seperti yang berhubungan dengan database atau enkripsi, memerlukan kompilasi saat diinstal menggunakan npm install.

    • Contoh: Paket-paket seperti node-sass, bcrypt, atau paket yang berinteraksi langsung dengan sistem operasi memerlukan akses ke alat kompilasi untuk membangun komponen biner spesifik untuk VPS kamu. Tanpa Build Essential, instalasi paket-paket ini akan gagal total.

  3. Modifikasi dan Kustomisasi Kernel

    • Jika kamu adalah pengguna tingkat lanjut dan perlu menginstal module kernel baru atau melakukan tuning spesifik pada kernel VPS kamu, kamu pasti memerlukan alat kompilasi yang ada dalam paket ini.
  4. Debugging dan Utilitas Dasar

    Selain alat kompilasi, paket ini juga sering mencakup alat-alat dasar yang penting untuk manajemen sistem dan debugging:

    • Utilitas Dasar: Alat seperti tar, gzip, wget, curl, dan unzip sangat penting untuk mengunduh, mengekstrak, dan mengelola berkas di server.

    • Debugging: Alat-alat ini membantu kamu menganalisis kinerja dan masalah sistem.

Kesimpulan

Menginstal Build Essential adalah salah satu langkah pertama yang harus kamu lakukan setelah menyiapkan VPS, terutama jika kamu berencana menjalankan aplikasi yang bergantung pada paket dengan komponen biner (seperti banyak paket di Node.js atau Python).

Kamu bisa melihatnya sebagai alat pertukangan dasar yang harus dimiliki oleh setiap VPS agar bisa membangun dan memperbaiki dirinya sendiri.

Installasi
sudo apt install -y \
  build-essential \
  curl \
  wget \
  git \
  vim \
  nano \
  htop \
  net-tools \
  unzip \
  software-properties-common \
  apt-transport-https \
  ca-certificates \
  gnupg \
  lsb-release

B. Install Neofetch

Neofetch adalah tool untuk menampilkan informasi sistem dengan tampilan yang menarik.

Kegunaan Neofetch:

  • 📊 Menampilkan info sistem (OS, kernel, CPU, RAM, dll) dengan visual menarik
  • 🎨 Customizable dan eye-candy untuk terminal
  • 🔍 Quick overview spesifikasi server
  • 📸 Bagus untuk screenshot/dokumentasi server
  • ⚡ Ringan dan cepat
# Install neofetch
sudo apt install neofetch -y

# Jalankan neofetch
neofetch

Note

Penulis sendiri, lebih memilih menggunakan fastfetch2 karena lebih ringan dan cepat.

Contoh saat menjalankan fastfetch pada VPS penulis:

fastfetch

Opsional untuk menjalankan neofetch otomatis setiap login, tambahkan ke .bashrc:

echo "neofetch" >> ~/.bashrc

C. Install Node.js

Ketika kamu membangun aplikasi di Node.js, sangat penting untuk memilih versi LTS. Mengapa? Karena versi LTS menjamin lingkungan yang stabil dan meminimalkan risiko masalah tak terduga (breaking changes), sehingga kamu bisa lebih fokus pada pengembangan fiturnya.

Poin Penting untuk Kamu Ingat:

  1. Versi LTS adalah Jalur yang Aman

    Ketika sebuah versi Node.js ditetapkan sebagai LTS, itu berarti komunitas dan tim pengembang Node.js telah berkomitmen untuk memelihara stabilitasnya dan menjamin tidak ada perubahan yang merusak (breaking changes) akan dimasukkan. Inilah mengapa ini adalah pilihan default untuk bisnis dan perusahaan.

  2. Versi Current adalah Versi Eksplorasi

    Versi Current adalah tempat semua fitur dan ide baru pertama kali diperkenalkan. Versi ini bagus jika kamu ingin menggunakan teknologi terbaru atau menguji kompatibilitas kode kamu dengan masa depan Node.js, tetapi tidak disarankan untuk menjalankan layanan yang harus selalu online dan stabil.

Singkatnya, untuk aplikasi yang produktifitas atau kritikal, sebaiknya selalu memilih LTS.

# Install Node.js via NodeSource
curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
sudo apt install -y nodejs

# Verify
node --version
npm --version

node_npm_version

Note

Penulis akhir-akhir ini lebih sering mendevelop menggunakan Deno atau Bun daripada nodejs.

D. Install Docker

🐋 Mengapa Harus Menggunakan Docker di VPS?

Alasan utama mengapa kamu harus menginstal Docker di VPS adalah untuk mencapai konsistensi lingkungan dan isolasi aplikasi . Docker memungkinkan kamu untuk mengemas aplikasi beserta semua dependensi (pustaka, konfigurasi, variabel) ke dalam satu wadah (container) yang terisolasi.

Ini menjawab masalah klasik “bekerja di komputer saya, tetapi tidak di VPS/server,” karena container akan berjalan persis sama di mana pun ia ditempatkan.

Kelebihan Utama Menggunakan Docker di VPS
  1. Konsistensi Lingkungan (Consistency)

    Kamu menjamin bahwa lingkungan pengembangan (laptop/PC kamu) sama persis dengan lingkungan production (VPS kamu).

    Jika aplikasi kamu membutuhkan Node.js versi X, database versi Y, dan Redis versi Z, semua itu akan berjalan bersama-sama di dalam container tanpa mengganggu atau dipengaruhi oleh sistem operasi utama VPS.

  2. Isolasi dan Keamanan (Isolation)

    Setiap aplikasi (misalnya backend, frontend, database) berjalan di container terpisah.

    Jika satu container bermasalah atau diserang, ia tidak akan secara langsung mempengaruhi container lain atau sistem operasi VPS secara keseluruhan.

  3. Pemanfaatan Sumber Daya yang Lebih Efisien

    Container jauh lebih ringan daripada Virtual Machine (VM) penuh. Container berbagi kernel sistem operasi VPS, sehingga membutuhkan lebih sedikit resource (RAM, CPU, disk space) untuk menjalankan aplikasi.

    Ini berarti kamu bisa menjalankan lebih banyak aplikasi pada VPS yang sama.

Note

Menggunakan Docker di VPS mengubah cara kamu mengelola dan menyebarkan aplikasi. Ini memberikan kamu kontrol, stabilitas, dan kecepatan yang jauh lebih besar dalam lingkungan production.

Instalasi Docker
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Add user to docker group (PENTING!)
sudo usermod -aG docker $USER

# Install Docker Compose
sudo apt install docker-compose-plugin -y

# Apply group changes (atau logout dan login lagi)
newgrp docker

# Verify
docker --version
docker compose version

# Test Docker (tanpa sudo)
docker run hello-world

node_npm_version

💡 Tip: Setelah menambahkan user ke grup docker, kamu perlu logout dan login lagi agar perubahan berlaku. Atau gunakan newgrp docker untuk apply langsung.

E. Install Nginx (Web Server)

Jika sudah ada docker, tidak harus diinstall pada server utama. Namun ini buat dokumentasi jika ingin menginstall pada host vps nya.

Note

Penulis lebih suka menginstall Nginx pada docker.

sudo apt install nginx -y

# Start dan enable
sudo systemctl start nginx
sudo systemctl enable nginx

# Check status
sudo systemctl status nginx

F. Install Database

Note

Seperti hal-nya pada nginx, penulis lebih suka juga menginstallnya pada docker. Kecuali memang VPS yang hanya dipergunakan untuk database ini saja, maka penulis akan menginstall di host vps agar mendapatkan performa penuh. Tentunya dengan setingan dan konfigurasi menyeluruh yang disesuaikan.

PostgreSQL
sudo apt install postgresql postgresql-contrib -y

# Start dan enable
sudo systemctl start postgresql
sudo systemctl enable postgresql

# Akses PostgreSQL
sudo -u postgres psql

# Buat user dan database (di dalam psql)
# CREATE USER myuser WITH PASSWORD 'mypassword';
# CREATE DATABASE mydb OWNER myuser;
# \q untuk keluar

Backup PostgreSQL:

# Backup single database
sudo -u postgres pg_dump dbname > backup_$(date +%Y%m%d).sql

# Backup all databases
sudo -u postgres pg_dumpall > backup_all_$(date +%Y%m%d).sql

# Restore database
sudo -u postgres psql dbname < backup.sql
MySQL/MariaDB
# Install MariaDB (fork MySQL yang lebih modern)
sudo apt install mariadb-server mariadb-client -y

# Start dan enable
sudo systemctl start mariadb
sudo systemctl enable mariadb

# Secure installation (WAJIB!)
sudo mysql_secure_installation

Ikuti prompt untuk:

  • Set root password
  • Remove anonymous users
  • Disallow root login remotely
  • Remove test database
  • Reload privilege tables

Akses MySQL/MariaDB:

# Login sebagai root
sudo mysql -u root -p

# Buat user dan database (di dalam mysql)
# CREATE DATABASE mydb;
# CREATE USER 'myuser'@'localhost' IDENTIFIED BY 'mypassword';
# GRANT ALL PRIVILEGES ON mydb.* TO 'myuser'@'localhost';
# FLUSH PRIVILEGES;
# EXIT;

Backup MySQL/MariaDB:

# Backup single database
sudo mysqldump -u root -p dbname > backup_$(date +%Y%m%d).sql

# Backup all databases
sudo mysqldump -u root -p --all-databases > backup_all_$(date +%Y%m%d).sql

# Backup dengan kompresi
sudo mysqldump -u root -p dbname | gzip > backup_$(date +%Y%m%d).sql.gz

# Restore database
sudo mysql -u root -p dbname < backup.sql

# Restore dari file terkompresi
gunzip < backup.sql.gz | sudo mysql -u root -p dbname

Automated Backup Script (Cron Job):

Buat script backup otomatis:

# Buat direktori backup
sudo mkdir -p /var/backups/mysql

# Buat script backup
sudo nano /usr/local/bin/mysql-backup.sh

Isi script:

#!/bin/bash
# MySQL Backup Script

BACKUP_DIR="/var/backups/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
MYSQL_USER="root"
MYSQL_PASSWORD="your_password"  # Atau gunakan mysql config file
RETENTION_DAYS=7

# Buat backup
mysqldump -u $MYSQL_USER -p$MYSQL_PASSWORD --all-databases | gzip > $BACKUP_DIR/backup_$DATE.sql.gz

# Hapus backup lama (lebih dari 7 hari)
find $BACKUP_DIR -name "backup_*.sql.gz" -mtime +$RETENTION_DAYS -delete

echo "Backup completed: backup_$DATE.sql.gz"

Set permission dan jadwalkan:

# Set executable
sudo chmod +x /usr/local/bin/mysql-backup.sh

# Tambahkan ke crontab (backup setiap hari jam 2 pagi)
sudo crontab -e

# Tambahkan baris ini:
# 0 2 * * * /usr/local/bin/mysql-backup.sh >> /var/log/mysql-backup.log 2>&1

🔒 Security Tip: Jangan simpan password di script! Gunakan ~/.my.cnf untuk menyimpan kredensial MySQL dengan aman.

Buat file ~/.my.cnf:

nano ~/.my.cnf

Isi:

[client]
user=root
password=your_password

Set permission:

chmod 600 ~/.my.cnf

Lalu ubah script backup untuk tidak menggunakan password di command line:

mysqldump --all-databases | gzip > $BACKUP_DIR/backup_$DATE.sql.gz

8. Konfigurasi Timezone

Tentu, saya akan jelaskan mengapa konfigurasi Timezone (Zona Waktu) pada VPS (Virtual Private Server) itu sangat penting, terutama dalam konteks menjalankan aplikasi dan layanan.

⏰ Pentingnya Konfigurasi Timezone pada VPS

Konfigurasi zona waktu pada VPS kamu sangat penting karena dua alasan utama: Akurasi Data dan Sistem Log/Penjadwalan. Jika zona waktu VPS kamu tidak diatur dengan benar, ini dapat menyebabkan kebingungan dan masalah serius pada aplikasi yang kamu jalankan.

  1. Akurasi Data dan Stempel Waktu (Timestamping)

    Ini adalah masalah paling umum:

    • Pencatatan Transaksi: Hampir semua aplikasi web, terutama yang melibatkan transaksi keuangan, entri data pengguna, atau riwayat, akan mencatat waktu kejadian (timestamp). Jika VPS kamu diatur ke zona waktu New York (EST) padahal seharusnya Jakarta (WIB), semua data transaksi akan memiliki perbedaan waktu yang tidak akurat.

    • Contoh: Seorang pengguna melakukan pembelian pada pukul 10:00 WIB. Jika VPS diatur ke EST, server akan mencatatnya sebagai pukul 22:00 EST hari sebelumnya. Hal ini merusak integritas dan urutan waktu data.

  2. Penjadwalan Tugas Otomatis (Cron Jobs)

    Aplikasi server sering menggunakan tugas terjadwal, seperti:

    • Pencadangan Harian (Backup): Kamu mungkin ingin menjalankan backup server setiap hari tepat pukul 02:00 pagi WIB.

    • Pengiriman Laporan: Aplikasi perlu mengirimkan laporan kepada pengguna pada awal hari kerja.

    • Masalah: Tugas terjadwal yang diatur melalui utilitas seperti Cron atau scheduler di aplikasi, akan dieksekusi berdasarkan zona waktu sistem VPS. Jika kamu mengatur tugas berjalan pukul 02:00, tetapi Timezone VPS salah, tugas tersebut akan dieksekusi pada jam yang salah (misalnya, tengah hari atau tengah malam), berpotensi mengganggu kinerja server atau layanan di jam sibuk.

  3. Log Server dan Debugging

    • Ketika terjadi kesalahan atau masalah pada aplikasi, kamu akan memeriksa berkas Log server (seperti Nginx, Apache, atau log aplikasi Node.js kamu).

    • Jika log menggunakan zona waktu yang berbeda dengan zona waktu yang kamu gunakan saat membaca, debugging menjadi sangat sulit. Kamu akan kesulitan mencocokkan kapan masalah dilaporkan oleh pengguna dengan kapan masalah itu benar-benar terjadi di log server.

Tips Terbaik

  1. Pilih UTC sebagai Default Server: Banyak administrator menyarankan untuk mengatur Timezone VPS ke UTC (Coordinated Universal Time).

    Alasannya: UTC adalah waktu universal yang tidak terpengaruh oleh Daylight Saving Time (DST) dan merupakan standar internasional. Ini membuat perhitungan waktu yang akurat menjadi lebih mudah di sisi kode aplikasi kamu, terlepas dari lokasi fisik VPS.

  2. Konversi di Aplikasi: Biarkan server menggunakan UTC, dan aplikasi kamu yang bertugas mengonversi waktu UTC ke zona waktu lokal pengguna (WIB, EST, dll.) saat ditampilkan di interface web.

Note

Namun, di sini penulis tunjukkan cara pengaturan ke timezone Asia/Jakarta, untuk mempermudah dalam kasus-kasus lain.

# Lihat timezone saat ini
timedatectl

# List available timezones
timedatectl list-timezones | grep Asia

# Set timezone (contoh: Jakarta)
sudo timedatectl set-timezone Asia/Jakarta

# Verify
date

9. Setup Fail2Ban

Fail2Ban melindungi server dari brute-force attacks dengan mem-ban IP yang melakukan failed login attempts berulang kali.

# Install Fail2Ban
sudo apt install fail2ban -y

# Copy konfigurasi default
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

# Edit konfigurasi
sudo nano /etc/fail2ban/jail.local

Konfigurasi dasar untuk SSH (sesuaikan port jika kamu ubah):

[DEFAULT]
# Ban time (dalam detik) - 1 jam
bantime = 3600

# Waktu untuk menghitung retry (dalam detik) - 10 menit
findtime = 600

# Maksimal retry sebelum di-ban
maxretry = 3

[sshd]
enabled = true
port = 2222
# Atau port custom kamu
filter = sshd
logpath = /var/log/auth.log

Restart Fail2Ban:

sudo systemctl restart fail2ban
sudo systemctl enable fail2ban

# Check status
sudo fail2ban-client status

# Check status SSH jail
sudo fail2ban-client status sshd

# Unban IP (jika perlu)
# sudo fail2ban-client set sshd unbanip IP_ADDRESS

10. Monitoring Sistem

💻 Fungsi dan Kegunaan Tools Pemantauan VPS

ToolsFungsi UtamaKegunaan
htopPemantauan Proses Interaktif (CPU & RAM)Menggantikan top dengan interface yang lebih canggih untuk melihat penggunaan CPU dan RAM server secara real-time dan mengelola proses.
ncduPenganalisis Penggunaan Ruang DiskUntuk dengan cepat menemukan direktori atau file mana yang memakan paling banyak storage (disk space) di VPS kamu.
iotopPemantauan Input/Output Disk (I/O)Mendeteksi proses mana yang sedang aktif membaca atau menulis data ke disk, sangat penting untuk mendiagnosis bottleneck I/O.
nethogsPemantauan Bandwidth Jaringan per ProsesMengidentifikasi proses atau aplikasi spesifik mana yang mengonsumsi paling banyak bandwidth jaringan (upload dan download) secara real-time.

A. Install Monitoring Tools

# htop - interactive process viewer
sudo apt install htop -y

# ncdu - disk usage analyzer
sudo apt install ncdu -y

# iotop - I/O monitoring
sudo apt install iotop -y

# nethogs - network monitoring
sudo apt install nethogs -y

B. Perintah Monitoring Dasar

# CPU dan Memory usage
htop

# Disk usage
df -h
ncdu /

# Memory info
free -h

# System uptime dan load
uptime

# Running processes
ps aux

# Network connections
netstat -tulpn
# atau
ss -tulpn

# Disk I/O
sudo iotop

# Network usage per process
sudo nethogs

# System logs
sudo journalctl -xe
sudo tail -f /var/log/syslog

11. Menggunakan Screen

🖥️ Kegunaan Perintah screen pada Linux VPS

Perintah screen (atau GNU Screen) adalah program manajemen sesi terminal yang sangat penting, terutama saat kamu bekerja pada server jarak jauh melalui koneksi SSH.

Fungsi utamanya adalah memungkinkan kamu menjalankan beberapa sesi terminal virtual dalam satu jendela SSH, tetapi kegunaan terbesarnya adalah menjaga proses tetap berjalan meskipun koneksi kamu terputus.


🔑 Fungsi Utama dan Manfaat screen

1. Menjaga Proses Tetap Berjalan (Detachment)

Ini adalah fitur terpenting. screen memungkinkan kamu memulai proses yang berjalan lama (seperti instalasi software, script backup besar, atau server aplikasi) dan kemudian melepaskan (detach) sesi tersebut dari jendela terminal SSH.

  • Manfaat: Proses akan terus berjalan di latar belakang VPS meskipun koneksi SSH kamu tiba-tiba terputus atau kamu menutup laptop. Kamu bisa menghubungkan kembali (reattach) ke sesi tersebut kapan saja untuk melihat statusnya.
2. Beberapa Jendela Terminal dalam Satu Sesi
  • Multiplexing: Kamu dapat membuat beberapa jendela (window) terpisah dalam satu sesi screen.
  • Manajemen Tugas: Ini memungkinkan kamu mengelola beberapa tugas server secara paralel (misalnya, satu jendela untuk editor teks, satu untuk menjalankan aplikasi, dan satu untuk memantau log) tanpa perlu membuka koneksi SSH baru.
3. Berbagi Sesi (Session Sharing)
  • screen memungkinkan beberapa pengguna untuk menghubungkan (attach) ke sesi yang sama secara bersamaan, sangat berguna untuk kolaborasi dan debugging bersama di server yang sama.

Install Screen

sudo apt install screen -y

Perintah Dasar Screen

Membuat dan Mengelola Session:

# Membuat session baru
screen

# Membuat session dengan nama
screen -S nama_session

# List semua session
screen -ls

# Attach ke session yang ada
screen -r

# Attach ke session tertentu
screen -r nama_session

# Attach ke session yang masih attached (force)
screen -dr nama_session

Keyboard Shortcuts (dalam screen):

Semua shortcut dimulai dengan Ctrl+A, lalu tekan tombol berikutnya:

# Detach dari session (session tetap berjalan di background)
Ctrl+A, lalu D

# Membuat window baru dalam session
Ctrl+A, lalu C

# Pindah ke window berikutnya
Ctrl+A, lalu N

# Pindah ke window sebelumnya
Ctrl+A, lalu P

# List semua window
Ctrl+A, lalu "" # petik 2nya 1x, ini error penulisan dalam tutorial

# Pindah ke window tertentu (0-9)
Ctrl+A, lalu [nomor]

# Kill window saat ini
Ctrl+A, lalu K

# Split screen horizontal
Ctrl+A, lalu S

# Split screen vertical
Ctrl+A, lalu |

# Pindah antar split region
Ctrl+A, lalu Tab

# Remove current region
Ctrl+A, lalu X

# Remove all regions except current
Ctrl+A, lalu Q

# Rename window
Ctrl+A, lalu A

# Lock screen
Ctrl+A, lalu X

# Help (lihat semua commands)
Ctrl+A, lalu ?

Contoh Penggunaan Screen

Scenario 1: Menjalankan Bot Telegram 24/7

# Buat session untuk bot
screen -S telegram-bot

# Jalankan bot
cd /path/to/bot
npm start

# Detach (Ctrl+A, D)
# Bot tetap berjalan di background

# Cek session
screen -ls

# Attach kembali untuk melihat log
screen -r telegram-bot

Scenario 2: Multiple Tasks

# Buat session
screen -S devserver

# Window 1: Jalankan backend
npm run dev

# Buat window baru (Ctrl+A, C)
# Window 2: Jalankan database
docker-compose up

# Buat window baru lagi (Ctrl+A, C)
# Window 3: Monitor logs
tail -f /var/log/app.log

# Pindah antar window (Ctrl+A, N atau Ctrl+A, P)
# Detach (Ctrl+A, D)

Scenario 3: Long Running Tasks

# Buat session untuk backup
screen -S backup

# Jalankan backup besar
rsync -avz /data/ user@backup-server:/backup/

# Detach (Ctrl+A, D)
# Logout dari SSH tanpa menghentikan backup

# Login lagi nanti
ssh user@server
screen -r backup
# Lihat progress backup

Tips Screen

# Konfigurasi screen (opsional)
nano ~/.screenrc

Contoh konfigurasi .screenrc:

# Disable startup message
startup_message off

# Scrollback buffer
defscrollback 10000

# Status bar
hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{= kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B} %m-%d %{W}%c %{g}]'

# Enable 256 colors
term screen-256color

# Mouse scrolling
termcapinfo xterm* ti@:te@

⚙️ Resume Perintah Lengkap GNU Screen (Menggunakan Prefix Ctrl + A)

Semua perintah di dalam sesi screen dimulai dengan menekan kombinasi Prefix Key, yang secara default adalah Ctrl + A.

1. Perintah Manajemen Sesi (Di Luar Sesi)
PerintahFungsiDeskripsi
screenMulai Sesi BaruMembuka sesi screen baru (dapat ditambahkan dengan nama: screen -S nama_sesi).
screen -lsDaftar SesiMenampilkan semua sesi screen yang sedang berjalan atau ter-detach.
screen -r [ID/Nama]Hubungkan Kembali (Reattach)Masuk kembali ke sesi yang sudah ter-detach (contoh: screen -r 1234.pts-0 atau screen -r nama_sesi).
screen -D -r [ID/Nama]Detach & Reattach PaksaMemutus sambungan sesi lain yang masih terhubung (attached) dan menghubungkan sesi tersebut ke terminal kamu.
2. Perintah Manajemen Jendela (Di Dalam Sesi)

Semua perintah di bawah ini harus diawali dengan menekan Ctrl + A terlebih dahulu.

PerintahFungsiDeskripsi
Ctrl + A, lalu DDetach (Lepas)Keluar dari sesi screen dan membiarkannya berjalan di latar belakang (proses tetap hidup).
Ctrl + A, lalu CBuat Jendela BaruMembuka jendela (window) terminal kosong baru di dalam sesi screen saat ini.
Ctrl + A, lalu NJendela BerikutnyaPindah ke jendela berikutnya dalam urutan (Nomor + 1).
Ctrl + A, lalu PJendela SebelumnyaPindah ke jendela sebelumnya dalam urutan (Nomor - 1).
Ctrl + A, lalu [0-9]Pindah Berdasarkan NomorLangsung pindah ke jendela dengan nomor yang ditentukan (misalnya, Ctrl + A, lalu 1).
Ctrl + A, lalu WDaftar JendelaMenampilkan daftar semua jendela yang ada dalam sesi saat ini.
Ctrl + A, lalu KTutup JendelaMenutup jendela saat ini (jika itu adalah jendela terakhir, sesi screen akan berakhir).
Ctrl + A, lalu AGanti Nama JendelaMemungkinkan kamu memberi nama yang lebih deskriptif pada jendela saat ini.
3. Perintah Scrolling dan Copy
PerintahFungsiDeskripsi
Ctrl + A, lalu EscMode CopyMemasuki mode copy (scrollback mode). Kamu dapat menggunakan tombol panah (arrow keys) untuk menggulir ke atas dan melihat output sebelumnya.
Spacebar (dalam Mode Copy)Mulai CopySetelah masuk Mode Copy, tekan Spacebar untuk menandai awal area yang ingin kamu salin.
Spacebar (kedua kalinya)Akhiri CopyTekan Spacebar lagi untuk menyalin teks yang telah ditandai ke dalam buffer screen.
Ctrl + A, lalu ]PasteMenempelkan (paste) konten dari buffer screen ke terminal saat ini.

Alternatif Screen: tmux

tmux adalah alternatif modern dari screen dengan fitur lebih banyak:

# Install tmux
sudo apt install tmux -y

# Basic commands mirip screen
tmux                    # Buat session
tmux ls                 # List sessions
tmux attach            # Attach ke session
tmux attach -t name    # Attach ke session tertentu
Ctrl+B, D              # Detach

🆚 Komparasi: GNU Screen vs. tmux (Terminal Multiplexer)

FiturGNU Screentmux (Terminal Multiplexer)
Status PengembanganLebih Tua, pengembangan lebih lambat/stabil.Lebih Baru, pengembangan lebih aktif dan modern.
Fungsi UtamaMenjaga proses tetap berjalan (Detach/Reattach).Menjaga proses tetap berjalan, dengan manajemen sesi yang canggih.
Prefix Key DefaultCtrl + ACtrl + B
Split WindowHanya mendukung pembagian area vertikal atau horizontal penuh, kurang fleksibel.Mendukung pembagian pane vertikal dan horizontal yang dinamis dan fleksibel.
Pengelolaan Panel (Pane)Manajemen panel dan navigasi terasa lebih kuno.Manajemen panel sangat intuitif dan cepat, dengan navigasi yang mudah antar panel.
KonfigurasiUmumnya kurang kompleks, file konfigurasi lebih sederhana (.screenrc).Lebih fleksibel, kompleks, dan banyak opsi kustomisasi (.tmux.conf).
KetersediaanUniversal; hampir selalu terinstal secara default di sebagian besar distribusi Linux.Perlu diinstal, tetapi tersedia di repositori paket utama.
Kurva PembelajaranLebih cepat dipelajari untuk fungsi dasar (detach/reattach).Lebih curam, tetapi disukai oleh power user karena fleksibilitasnya.

Tips Keamanan Tambahan

1. Automatic Security Updates

# Install unattended-upgrades
sudo apt install unattended-upgrades -y

# Configure
sudo dpkg-reconfigure --priority=low unattended-upgrades

# Edit konfigurasi (opsional)
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

2. Setup Swap (Jika RAM Terbatas)

# Check existing swap
sudo swapon --show

# Create swap file (2GB)
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# Make permanent
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

# Verify
free -h

# Adjust swappiness (opsional, default 60)
# Nilai lebih rendah = lebih jarang swap
sudo sysctl vm.swappiness=10
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf

3. Regular Backups

# Backup penting:
# - Database dumps
# - Konfigurasi (/etc)
# - Application data
# - User home directories

# Contoh backup dengan tar
sudo tar -czf backup_$(date +%Y%m%d).tar.gz /path/to/data

# Backup dengan rsync
rsync -avz /path/to/data user@backup-server:/backup/

# Backup ke cloud (rclone)
# Install rclone
curl https://rclone.org/install.sh | sudo bash

# Configure rclone (Google Drive, Dropbox, dll)
rclone config

# Backup ke cloud
rclone sync /path/to/data remote:backup/

4. Monitoring Logs

# SSH login attempts
sudo tail -f /var/log/auth.log

# System logs
sudo tail -f /var/log/syslog

# Nginx logs
sudo tail -f /var/log/nginx/access.log
sudo tail -f /var/log/nginx/error.log

# Failed login attempts
sudo grep "Failed password" /var/log/auth.log

# Successful logins
sudo grep "Accepted" /var/log/auth.log

5. Disable IPv6 (Jika Tidak Digunakan)

# Edit sysctl
sudo nano /etc/sysctl.conf

# Tambahkan:
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1

# Apply
sudo sysctl -p

# Verify
cat /proc/sys/net/ipv6/conf/all/disable_ipv6
# Output: 1 (disabled)

6. Setup SSH Config di Local (Kemudahan Akses)

Di komputer lokal kamu, buat SSH config untuk akses lebih mudah:

# Edit SSH config
nano ~/.ssh/config

Tambahkan:

Host myserver
    HostName IP_ADDRESS_VPS
    User namauser
    Port 2222
    IdentityFile ~/.ssh/id_ed25519
    ServerAliveInterval 60
    ServerAliveCountMax 3

Sekarang kamu bisa login dengan:

ssh myserver

Jauh lebih mudah!


Troubleshooting Umum

1. Tidak Bisa Login SSH

Kamu bisa masuk ke panel yang disediakan penyedia SSH untuk bisa melakukan ini.

# Check SSH service status
sudo systemctl status sshd

# Restart SSH
sudo systemctl restart sshd

# Check firewall
sudo ufw status

# Check logs
sudo tail -f /var/log/auth.log

# Check SSH listening port
sudo ss -tulpn | grep ssh

# Verify SSH config syntax
sudo sshd -t

2. Lupa Password User

# Login sebagai root (via console provider), reset password
passwd namauser

3. Disk Penuh

# Check disk usage
df -h

# Find large files
sudo du -h / | sort -rh | head -20

# Find large files (lebih detail)
sudo find / -type f -size +100M -exec ls -lh {} \;

# Clean package cache
sudo apt clean
sudo apt autoremove

# Clean journal logs
sudo journalctl --vacuum-time=7d

# Clean old kernels (hati-hati!)
sudo apt autoremove --purge

4. High Memory Usage

# Check memory
free -h

# Find memory-hungry processes
ps aux --sort=-%mem | head

# Detailed memory info
sudo cat /proc/meminfo

# Restart service yang bermasalah
sudo systemctl restart service-name

# Clear cache (jika perlu)
sudo sync; echo 3 | sudo tee /proc/sys/vm/drop_caches

5. Port Sudah Digunakan

# Check port usage
sudo netstat -tulpn | grep :PORT
# atau
sudo ss -tulpn | grep :PORT

# Find process using port
sudo lsof -i :PORT

# Kill process
sudo kill -9 PID

# Atau kill by port
sudo fuser -k PORT/tcp

6. Terkunci dari Server (Lupa Port/Password)

# Akses via console provider (DigitalOcean, Vultr, dll)
# Biasanya ada fitur "Console" atau "VNC"

# Reset SSH config
sudo nano /etc/ssh/sshd_config
# Ubah kembali Port ke 22
# Ubah PermitRootLogin ke yes (sementara)

# Restart SSH
sudo systemctl restart sshd

# Atau reset via recovery mode

7. Screen Session Tidak Bisa Di-attach

# List sessions
screen -ls

# Jika ada session "Attached" tapi tidak bisa diakses
screen -dr session_name

# Jika masih bermasalah, wipe session
screen -wipe

# Kill session tertentu
screen -X -S session_name quit

Kesimpulan

Setup VPS pertama kali memang terlihat rumit, tapi setelah dilakukan beberapa kali akan menjadi rutinitas. Berikut checklist singkat:

Checklist Setup VPS:

  • Login ke VPS
  • Update sistem
  • Buat user non-root
  • Setup SSH key authentication
  • Ganti port SSH (termasuk ssh.socket di Ubuntu 24.04)
  • Hardening SSH config
  • Disable root login
  • Setup firewall (UFW)
  • Install software yang dibutuhkan
  • Install neofetch
  • Setup Docker (tambahkan user ke grup)
  • Install database (MySQL/MariaDB/PostgreSQL)
  • Setup backup database otomatis
  • Set timezone
  • Install Fail2Ban
  • Setup monitoring tools
  • Install dan pelajari Screen

Langkah Selanjutnya

Setelah setup dasar, kamu bisa:

  1. Deploy aplikasi (Node.js, Python, Go, dll)
  2. Setup web server (Nginx reverse proxy, Apache)
  3. Setup SSL certificate (Let’s Encrypt dengan Certbot)
  4. Configure domain (DNS settings, A record, CNAME)
  5. Setup CI/CD (GitHub Actions, GitLab CI, Jenkins)
  6. Monitoring advanced (Prometheus, Grafana, Netdata)
  7. Containerization (Docker Compose untuk multi-container apps)
  8. Load Balancing (Nginx load balancer)
  9. Database Replication (Master-slave setup)
  10. Backup Strategy (Automated backups ke cloud)

Referensi

Dokumentasi Resmi

Security & Hardening

Linux Administration

Tools & Software

Monitoring & Logging

Backup & Recovery

SSL/TLS

Community & Forum

YouTube Channels (Tutorial Indonesia)

YouTube Channels (English)

Cheat Sheets


Selamat mencoba! 🚀

💡 Pro Tip: Selalu dokumentasikan setiap perubahan yang kamu lakukan di VPS. Buat catatan di file server-notes.md atau gunakan tool seperti Notion/Obsidian untuk tracking konfigurasi. Ini akan sangat membantu saat troubleshooting atau setup VPS baru di masa depan.

🔖 Bookmark Tip: Simpan panduan ini dan referensi di atas. kamu akan sering kembali ke sini saat setup server baru atau troubleshooting!


  1. banghasan.com, Hasanudin H Syafaat atau bangHasan – penyusun tulisan ini.

  2. https://github.com/fastfetch-cli/fastfetch A maintained, feature-rich and performance oriented, neofetch like system information tool.

🚀 Instalasi Giscus di MdBook

Panduan ini memungkinkan Anda menyematkan widget komentar Giscus di bawah setiap bab mdBook dan menyinkronkan temanya secara dinamis.

Important

Update Metode: Setelah langkah 1) langsung meluncurlah LIHAT CARA DIBAWAH yang sudah berhasil dengan baik!

1. 🔑 Mendapatkan Data Giscus yang Diperlukan

  1. Kunjungi Giscus App.
  2. Konfigurasikan repository GitHub publik Anda, category yang akan digunakan untuk diskusi, dan pengaturan lainnya.
  3. Salin kode <script> yang dihasilkan. Anda akan memerlukan nilai untuk data-repo, data-repo-id, data-category, dan data-category-id.

2. ⚙️ Inisialisasi Tema Kustom

Langkah ini menyalin template default mdBook ke direktori theme/ agar dapat dimodifikasi.

mdbook init --theme

3. 📝 Modifikasi theme/index.hbs (Penyematan Giscus)

Sisipkan kode Giscus di dalam template halaman, tepat setelah konten utama ({{{ content }}}).

  1. Buka theme/index.hbs.
  2. Cari tag penutup </main>.
  3. Sisipkan kode Giscus yang dibungkus div (giscus-wrapper) di lokasi tersebut:
// ... 
        <main>
          {{{ content }}}
        </main>

                    <hr> 
                    <div id="giscus-wrapper">
                        <script src="https://giscus.app/client.js"
                                data-repo="USERNAME/REPO-NAME"
                                data-repo-id="R_kgDOXXXXXXXX"
                                data-category="CATEGORY-NAME"
                                data-category-id="DIC_kwDOXXXXXXXX"
                                data-mapping="pathname"
                                data-strict="0"
                                data-reactions-enabled="1"
                                data-emit-metadata="0"
                                data-input-position="bottom"
                                data-theme="preferred_color_scheme" 
                                data-lang="id"
                                data-loading="lazy"
                                crossorigin="anonymous"
                                async>
                        </script>
                    </div>
                    
                    <nav class="nav-wrapper" aria-label="Page navigation">

4. 🎨 Kontrol Lebar dengan theme/custom.css

Buat file CSS kustom untuk membatasi lebar widget Giscus dan memposisikannya di tengah (center).

  1. Buat file theme/custom.css.
  2. Tambahkan CSS berikut:
/* theme/custom.css */
#giscus-wrapper {
    max-width: 800px; /* Batasi lebar maksimum */
    margin-left: auto;
    margin-right: auto; /* Posisikan di tengah */
    margin-top: 2em;
    margin-bottom: 2em;
}

5. 🛠️ Konfigurasi book.toml

Tambahkan file CSS dan JS kustom Anda ke dalam output HTML mdBook.

  1. Buka book.toml.
  2. Tambahkan kedua file kustom di bagian [output.html]:
[output.html]
# ... konfigurasi lainnya
additional-css = ["theme/custom.css"]

6. ✅ Build dan Uji

  1. Jalankan mdbook build.
  2. Atau akses web buku melalui server web (mdbook serve) dan lihat hasilnya

⚠️ Catatan Penting Mengenai Sinkronisasi Tema

Saat ini, pergantian tema gelap atau terang pada widget Giscus secara dinamis (menggunakan tombol tema mdBook) belum berhasil. Sudah dicoba dengan cara meng-custom js tetap tidak berubah

Gunakan cara dibawah ini…


🚀 Skrip Giscus Terakhir yang Berhasil

Dengan metode Injeksi JavaScript, cara ini sungguh pamungkas euy!

Kode ini menyuntikkan widget Giscus setelah <main> dan menyinkronkan tema mdBook Anda dengan tema Giscus yang spesifik, menjaga theme/index.hbs tetap bersih.

1. 🛠️ Konfigurasi Aset

Pastikan file-file ini ada di folder theme/ Anda dan dimuat di book.toml.

A. Atur book.toml

Pastikan file kustom Anda dimuat:

[output.html]
# ... konfigurasi lainnya
additional-css = ["giscus.css"]
additional-js = ["giscus.js"]

B. Buat file giscus.css

CSS ini diperlukan untuk mengatur lebar wrapper yang dibuat secara dinamis oleh JavaScript.

#giscus-wrapper {
    /* Atur lebar maksimum agar tidak melebihi lebar tertentu */
    max-width: 800px;

    /* Atau atur lebar yang lebih kecil, misalnya 75% dari konten */
    /* width: 75%; */

    /* Gunakan margin: 0 auto; untuk menempatkannya di tengah halaman (center) */
    margin-left: auto;
    margin-right: auto;

    /* Berikan sedikit margin di bagian atas/bawah agar terpisah dari konten */
    margin-top: 2em;
    margin-bottom: 2em;
}

2. 🧠 Skrip Utama (giscus.js)

Kode ini mengurus pemuatan Giscus (injeksi ke DOM) dan sinkronisasi tema dinamis melalui MutationObserver dan postMessage

// giscus.js

// --- Konfigurasi Tema Giscus ---
// Pemetaan Tema Spesifik ke Tema Giscus:
// Light/Default: light
// Gelap Umum (Navy/Coal/Dark): dark
// Rust: gruvbox_dark
// Ayu: dark_dimmed

function getThemeName() {
    const htmlClass = document.documentElement.className;
    
    if (htmlClass.includes("ayu")) {
        return "dark_dimmed"; 
    } 
    
    if (htmlClass.includes("rust")) {
        return "gruvbox_dark";
    }

    if (htmlClass.includes("navy") || htmlClass.includes("coal") || htmlClass.includes("dark")) {
        return "dark"; 
    }
    
    return "light";
}

// --- Fungsi Pemuatan Giscus (Injeksi DOM) ---
function loadGiscus() {
    const mainElement = document.querySelector("main");
    if (!mainElement) {
        console.error("Main content area (<main>) not found. Cannot inject Giscus.");
        return;
    }

    // Buat HR (opsional, sebagai pemisah)
    const hr = document.createElement("hr");
    // Sisipkan elemen setelah <main>
    mainElement.insertAdjacentElement('afterend', hr); 

    // Buat DIV WRAPPER (untuk menerapkan CSS kustom)
    const wrapper = document.createElement("div");
    wrapper.id = "giscus-wrapper";
    mainElement.insertAdjacentElement('afterend', wrapper); 

    // Buat Script Giscus
    let giscusAttributes = {
        src: "https://giscus.app/client.js",
        "data-repo": "<USERNAME/REPO-ANDA>", // Ganti dengan data Anda
        "data-repo-id": "R_kgDOXXXXXXXX", // Ganti dengan data Anda
        "data-category": "<NAMA-KATEGORI>", // Ganti dengan data Anda
        "data-category-id": "DIC_kwDOXXXXXXXX", // Ganti dengan data Anda
        "data-mapping": "pathname",
        "data-strict": "0",
        "data-reactions-enabled": "1",
        "data-emit-metadata": "0",
        "data-input-position": "top",
        "data-theme": getThemeName(), 
        "data-lang": "id",
        "data-loading": "lazy",
        crossorigin: "anonymous",
        async: "",
    };

    let giscusScript = document.createElement("script");
    Object.entries(giscusAttributes).forEach(([key, value]) =>
        giscusScript.setAttribute(key, value),
    );
    wrapper.appendChild(giscusScript); 
}

// --- Sinkronisasi Tema Dinamis ---
function changeGiscusTheme() {
    const iframe = document.querySelector("iframe.giscus-frame");
    if (!iframe) {
        // Retry logic: Coba lagi hingga iframe ditemukan
        setTimeout(changeGiscusTheme, 500);
        return;
    }

    const theme = getThemeName();
    
    const sendMessage = (message) => {
        if (iframe.contentWindow) {
            iframe.contentWindow.postMessage(
                { giscus: message },
                "https://giscus.app",
            );
            console.log("Giscus theme sent via postMessage:", theme);
        }
    };

    sendMessage({ setConfig: { theme: theme } });
}

// --- Observer (Trigger Perubahan Tema) ---
document.addEventListener("DOMContentLoaded", () => {
    // 1. Muat Giscus saat DOM siap
    loadGiscus();

    const htmlElement = document.documentElement;

    // 2. Observer untuk mendeteksi pergantian tema mdBook
    const observer = new MutationObserver((mutationsList) => {
        for (const mutation of mutationsList) {
            if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
                // Jeda 100ms untuk stabilitas sebelum mengirim pesan postMessage
                setTimeout(changeGiscusTheme, 100); 
            }
        }
    });

    observer.observe(htmlElement, { attributes: true, attributeFilter: ['class'] });

    // 3. Fallback Pemuatan Awal (Wajib untuk mengatasi masalah timing)
    setTimeout(() => {
        console.log("Applying initial theme forcefully after 3s delay.");
        changeGiscusTheme(); 
    }, 3000);
});

3. Build dan Uji

Seperti metode sebelumnya.

Baiklah, segini dulu aja yak!

Tip

Semoga bermanfaat.

mdbook v0.5.1

Status Aplikasi Web

Halaman ini disediakan sebagai rujukan resmi mengenai kondisi terbaru aplikasi web yang berada di repositori ini. Seluruh informasi dirangkum secara ringkas dan sopan agar setiap kontributor dapat segera memahami situasi terkini tanpa harus menelusuri seluruh berkas proyek.

bang - Hasan maintained - yes contributions - welcome OS - Linux Netlify Status issues - ebook-bot-telegram

Utama

Plugins

Nunggu update agar support versi 0.5.x GitHub release

Support, tapi tidak terpakai:

Dengan adanya penjelasan ini, setiap pengunjung halaman dapat langsung mengetahui bahwa dokumen status memuat tiga area utama—repositori, build, dan plugin—yang menjadi acuan dalam memantau kesehatan proyek secara menyeluruh.

Halaman Uji Coba

Teks Pojok

Untuk Developer

  • Menguji command atau fitur baru tanpa mengganggu konten utama.
  • Menuliskan snippet kode untuk mengecek syntax highlighting.
  • Menyimpan catatan hasil uji coba sementara.

Untuk Pengunjung

  • Mencoba meninggalkan komentar sebagai bagian dari proses testing.
  • Mengeksplorasi contoh format markdown yang disediakan di bawah.

Contoh Format Markdown

Paragraf & Penegasan

Markdown mendukung italic, bold, dan inline code untuk memberi penekanan pada teks.

Daftar

  1. Langkah pertama
  2. Langkah kedua
  3. Langkah ketiga
  • Item bebas
  • Item dengan teks tebal
  • Item dengan tautan

Blockquote

Ini contoh blockquote untuk mencatat catatan singkat atau highlight komentar.

Tabel

FiturStatusCatatan
Command ASudah diuji
Command B⚠️Masih butuh verifikasi
Command CBelum berjalan sesuai ekspektasi

Kode

# Contoh command yang bisa dicoba developer
./serve.sh --open
function cobaFitur(nama) {
  return `Halo ${nama}, fitur berhasil dijalankan!`;
}

Checklist

  • Tulis komentar percobaan
  • Uji upload gambar di komentar
  • Laporkan hasilnya di kanal dev

Icons

<i class="fa-solid fa-book"></i>

Hasil

  • Buku

Alerts

Ada di admonitions

> [!NOTE]  
> Highlights information that users should take into account, even when skimming.

> [!TIP]
> Optional information to help a user be more successful.

> [!IMPORTANT]  
> Crucial information necessary for users to succeed.

> [!WARNING]  
> Critical content demanding immediate user attention due to potential risks.

> [!CAUTION]
> Negative potential consequences of an action.

Note

Highlights information that users should take into account, even when skimming.

Tip

Optional information to help a user be more successful.

Important

Crucial information necessary for users to succeed.

Warning

Critical content demanding immediate user attention due to potential risks.

Caution

Negative potential consequences of an action.

Rust

Hello World

Hello world nya bisa dijalankan di sini.

use std::time::{SystemTime, UNIX_EPOCH};

fn main() {
    println!("🌟 Hello World! 🌟");
    
    // Dapatkan waktu saat ini dari sistem
    let now = SystemTime::now();

    // Hitung durasi sejak epoch (1 Januari 1970)
    let duration_since_epoch = match now.duration_since(UNIX_EPOCH) {
        Ok(duration) => duration,
        Err(e) => {
            // Ini terjadi jika waktu sistem mundur sebelum epoch
            eprintln!("Waktu sistem mundur sebelum epoch: {}", e);
            return;
        }
    };

    // Tampilkan waktu mentah sebagai durasi
    println!("\nTotal detik sejak epoch: {} detik", duration_since_epoch.as_secs());
}