Membuat Bot Telegram

Messenger telegram masih kurang populer di Indonesia, padahal Telegram memiliki banyak kelebihan dibanding messenger lain, misalnya: lebih cepat, bisa diakses via web, sinkronisasi pesan, dsb. Salah satu fitur yang baru diperkenalkan oleh Telegram adalah bot. Bot adalah software yang secara otomatis merespon pesan yang kita berikan.

Setelah saya membuat bot Bot Alkitab, beberapa orang bertanya bagaimana caranya membuat bot. Dengan harapan Telegram jad lebih populer, saya tuliskan di sini dasar pembuatan bot.

Sebelum membaca Artikel ini, silakan baca dulu artikel dari telegram yang memperkenalkan soal bot, lalu bereksperimen lah dengan bot-bot yang sudah ada, supaya bisa mengerti fitur bot dan interaksi dengan bot:

https://telegram.org/blog/bot-revolution

Mendaftarkan Bot

Sekarang setelah siap membuat bot, langkah pertama adalah mendaftarkan nama bot kita. Ini dilakukan dengan menggunakan BotFather.

Perintah yang perlu digunakan adalah /newbot. Perlu diperhatikan bahwa semua bot harus memiliki akhiran “Bot”. Setelah selesai, kita akan mendapatkan token, semacam ini: 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11. Token ini tidak boleh disebar (karena orang lain bisa mengambil alih bot Anda).

botfather

Setelah didaftarkan, kita bisa langsung menambahkan bot di daftar teman kita.

daftar-teman

Ketika mulai chat, ada tombol “Start”

tombol-start

Jika kita tekan itu, yang terjadi adalah kita mengirimkan perintah “/start” ke bot (semua perintah bot dimulai dengan “/”).

pesan-pertama

Tapi kita belum menulis kode untuk bot kita, jadi bot kita belum bisa membalas apapun.

Menerima Pesan

Bot bisa menerima pesan dengan dua cara: polling dan webhook.

Polling artinya kita yang akan meminta pesan ke server telegram. Kira-kira begini: eh ada nggak pesan buat bot saya, kalo nggak ada, bilang aja nggak ada setelah N detik ya. Kalau dalam N detik ada pesan masuk, langsung berikan ke saya pesannya.

Cara kedua adalah dengan webhook. Kira-kira begini: ini saya punya URL, kalau ada pesan masuk, segera posting ke URL ini ya, nanti saya proses. URL ini harus HTTPS.

Telegram hanya mau mengantarkan pesan dengan salah satu cara di atas, tidak bisa keduanya, defaultnya adalah cara pertama.

Cara pertama cocok jika server dijalankan secara internal. Misalnya jika dijalankan di raspberry pi di rumah. Kita tidak perlu IP publik, tidak perlu punya domain, tidak perlu setup HTTPS, dsb. Cara ini agak sedikit lebih lambat dari cara kedua jika penggunanya banyak.

Cara kedua cocok jika Anda sudah punya web server eksternal dan sudah punya HTTPS, atau memakai layanan yang sudah memakai HTTPS (contohnya Google App Engine).

Pertama saya bahas cara polling karena ini sangat praktis ketika development. Pertama kita coba akses pesan yang diterima bot. Kita bisa meminta menggunakan browser seperti ini:


https://api.telegram.org/botTOKEN/getUpdates

Contohnya seperti ini:

getupdates

Sebenarnya ada beberapa parameter ekstra yang bisa kita tambahkan. Pertama adalah timeout: menyatakan berapa lama kita akan menunggu sampai ada pesan. Kedua adalah limit yang menyatakan berapa pesan yang ingin kita terima (max 100). Dan ketiga yang penting adalah offset.

Jika Anda coba refresh URL sebelumnya (tanpa memberikan offset), maka telegram tidak tahu apakah Anda sudah memproses pesan itu atau tidak (batasnya 24 jam). Untuk memberi tahu telegram bahwa pesan tadi sudah kita baca, kita perlu memberikan offset berupa update_id terakhir plus 1, jadi untuk mendapatkan pesan-pesan setelah pesan di atas, saya bisa menambahkan offset seperti ini (sekalian saya berikan contoh memberikan timeout dan limit):


https://api.telegram.org/botTOKEN/getUpdates?offset=142757037&timeout=2&limit=1

Hasil kembalian getUpdates seperti ini:

{"ok":true,"result":[{"update_id":142757036,
"message":{"message_id":3,"from":{"id":24912310,"first_name":"Yohanes","last_name":"Nugroho","username":"yohanesn"},"chat":{"id":24912310,"first_name":"Yohanes","last_name":"Nugroho","username":"yohanesn"},"date":1436950746,"text":"\/start"}}]}

Isi “result” adalah array of message (ada berbagai jenis message, bisa teks, video, dokumen, dsb, tapi dalam tutorial ini yang akan saya tangani hanya yang berisi “text”. Anda bisa membaca API Telegram untuk menangani jenis pesan yang lain.

Untuk membalas pesan, kita bisa menggunakan sendMessage. Anda bisa mencoba di browser (menggunakan token Anda) seperti ini (lihat chat_id di JSON di atas):


https://api.telegram.org/botTOKEN/sendMessage?chat_id=24912310&text=hello

Jika kita ingin menampilkan pesan sebagai balasan dari message tertentu, kita bisa menambahkan reply_to_message_id. Misalnya di atas tercantum message_id adalah 3:


https://api.telegram.org/botTOKEN/sendMessage?chat_id=24912310&text=hello&message_id=3

Jika kita menggunakan Python, kita bisa mendapatkan pesan updatenya dengan library requests (urllib juga bisa, tapi requests lebih enak). Karena URL requestnya sama semua prefixnya, saya membuat fungsi request_url untuk mempersingkat. Berikutnya agar singkat, saya hanya akan membahas PHP saja (dan Anda tetap bisa dengan mudah menerjemahkan ke Python).

def request_url(method):
    return  "https://api.telegram.org/bot"+TOKEN+"/" + method

def getUpdates(offset, limit=100, timeout=100):
    r = requests.get(request_url("getUpdates"),
                     params={"offset":offset,
                      "limit": limit,
                      "timeout": timeout
                      } )
    #asumsi semuanya OK
    result = json.loads(r.content)
    if result["ok"]:
        return result["result"]
    return []

Kode yang sama di PHP:

<?php

include("token.php");

function request_url($method)
{
	global $TOKEN;
	return "https://api.telegram.org/bot" . $TOKEN . "/". $method;
}

function get_updates() 
{
        $resp = file_get_contents(request_url("getUpdates"));
        $update = json_decode($resp, true);
         
?>

Kerangka sebuah program PHP command line (metode polling) yang menangani pesan adalah seperti ini:

<?php
include("token.php");

function request_url($method)
{
	global $TOKEN;
	return "https://api.telegram.org/bot" . $TOKEN . "/". $method;
}

function get_updates($offset) 
{
	$url = request_url("getUpdates")."?offset=".$offset;
        $resp = file_get_contents($url);
        $result = json_decode($resp, true);
        if ($result["ok"]==1)
            return $result["result"];
        return array();
}

function send_reply($chatid, $msgid, $text)
{
    $data = array(
        'chat_id' => $chatid,
        'text'  => $text,
        'reply_to_message_id' => $msgid

    );
    // use key 'http' even if you send the request to https://...
    $options = array(
    	'http' => array(
        	'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
        	'method'  => 'POST',
        	'content' => http_build_query($data),
    	),
    );
    $context  = stream_context_create($options);

    $result = file_get_contents(request_url('sendMessage'), false, $context);
    print_r($result);
}

function create_response($text)
{
   return "definisi " . $text;
}


function process_message($message)
{
    $updateid = $message["update_id"];
    $message_data = $message["message"];
    if (isset($message_data["text"])) {
	$chatid = $message_data["chat"]["id"];
        $message_id = $message_data["message_id"];
        $text = $message_data["text"];
        $response = create_response($text);
        send_reply($chatid, $message_id, $response);
    }
    return $updateid;
}


function process_one()
{
	$update_id  = 0;

	if (file_exists("last_update_id")) {
		$update_id = (int)file_get_contents("last_update_id");
	}

	$updates = get_updates($update_id);

	foreach ($updates as $message)
	{
     		$update_id = process_message($message);
	}
	file_put_contents("last_update_id", $update_id + 1);

}

while (true) {
	process_one();
}
          
?>

Anda bisa mengakses sourcenya di sini:

https://gist.github.com/yohanes/987e1d48cbca9fde9377

Perhatikan bahwa ini perlu dijalankan di command line seperit ini:

$ php telegram-poll.php

Dan selama program masih berjalan, maka pesan yang masuk akan dibalas. Jika dijalankan di web server, maka akan timeout setelah beberapa detik/menit.

Isi file token.php hanyalah seperti ini:

<?php
$TOKEN="TOKENANDA";
?>

Untuk metode webHook, perbedaannya hanya pada fungsi get_updates, dan process_one tidak diperlukan, loop while juga tidak diperlukan, karena pesan akan dikirim satu per satu dengan POST. Kita cukup membaca POST yang masuk (dengan membaca php//:input), dan mendecode JSON-nya.

<?php
//bagian awal sama dengan sebelumnya

$entityBody = file_get_contents('php://input');
$message = json_decode($entityBody, true);
process_message($message);

?>

Source lengkap di:

https://gist.github.com/yohanes/3181a5424d10ea5e2429

Untuk menggunakan methode webHook, Anda harus melakukan beberapa hal:

  1. Mempersiapkan URL HTTPS
  2. Menset urlWebhook

Untuk bagian pertama: Anda perlu memiliki hosting yang mendukung HTTPS, Anda juga bisa memakai layanan cloudflare.com yang otomatis membungkus web Anda dengan https. Berikutya kita perlu mensetup web hook. Contohnya jika URL file php tersebut adalah:

http://cintaprogramming.com/xx.php

maka kita set dengan cara mengunjungi (menggunakan browser atau curl):

https://api.telegram.org/botTOKEN/setWebhook?url=https://cintaprogramming.com/xxx.php

Anda akan mendapatkan balasan:

{"ok":true,"result":true,"description":"Webhook was set"}

Jika ingin kembali menggunakan metode polling, maka set URL menjadi kosong:

https://api.telegram.org/botTOKEN/setWebhook?url=

Anda akan mendapatkan balasan:

{"ok":true,"result":true,"description":"Webhook was deleted"}

Atau jika memang belum diset:

{"ok":true,"result":true,"description":"There is no webhook to delete"}

Berikutnya terserah Anda bagaimana ingin memproses data masukan dari pengguna, misalnya bisa query ke database, bisa melakukan komputasi, dsb.

Jika kode Anda jalan di versi lokal/polling, tapi tidak ketika menggunakan webhook, maka Anda perlu mendebug. Pertama test apakah: webhook dipanggil oleh telegram (bisa dicoba dengan menuliskan isi $entityBody ke file). Kedua cek apakah Anda bisa memanggil send_reply. Beberapa hosting mematikan file_get_contents untuk mengakses HTTP/HTTPS, atau mendisable modul SSL (untuk kasus ini, mungkin harus diganti memakai modul curl) . Coba skrip paling sederhana di atas sebelum menambahkan kode custom Anda untuk reply (misalnya Anda mengakses MySQL, siapa tahu kode Anda yang error karena salah database atau salah query).

Saran saya: gunakan polling dulu sampai yakin sudah benar, setelah itu baru gunakan webhook.

Contoh ini sebenarnya adalah penyederhanaan sebuah kamus. Seharusnya bot ini membalas dengan definisi dari database, tapi di contoh ini bot selalu membalas dengan “definisi ” + KATA.

Sebuah bot bisa memiliki banyak perintah yang diawali dengan “/” (slash), terserah pembuat bot yang mendefinisikan. Misalnya jika kita membuat bot cuaca, kita bisa membuat perintah: “/cuaca NAMAKOTA” (untuk mendapatkan cuaca saat ini) atau “/ramalan NAMAKOTA” (untuk mendapatkan ramalan seminggu). Untuk menangani perintah-perintah ini kita bisa menggunakan parsing teks sederhana. Contoh parsing yang bisa dilakukan split teks menjadi kata-kata: jadikan kata pertama menjadi lower case, dan trim (hapus spasinya), lalu cek apakah sama dengan “/cuaca” atau “/ramalan”. Dan berikutnya lakukan aksi sesuai dengan perintahnya.

Setelah kita memiliki perintah-perintah tersebut. Kita bisa mendaftarkan perintahnya ke BotFather supaya Telegram bisa melakukan autocomplete perintah ketika user mengetikkan karakter /.

Demikian tutorial singkat bot Telegram. Jika ada pertanyaan, silakan tinggalkan di bagiann komentar, dan akan berusaha saya jawab (atau mungkin akan saya buatkan tutorial bagian kedua untuk menjelaskan lebih detail).

16 thoughts on “Membuat Bot Telegram”

  1. Om Yo, terima kasih banyak sudah membagi ilmunya lewat artikel ini. Kebetulan saya sedang pusing belajar membuat bot telegram sebagai pemula banget. Dari artikel ini saya sudah mampu membedakan antara metode polling dengan webhook. Kesimpulan saya harus belajar dan memperdalam dulu metode polling (dari kemarin2 dapat tutorial yang webhook terus jadi mentok lagi).

    Ada beberapa pertanyaan terkait artikel ini:
    Untuk bot KBBIbot maupun Alkitab, dalam bayangan saya, si bot telegram mengambil “data” dari pusat data yang ditentukan. Jadi kalau user request (misalkan Matius 1:1), maka ditampilkan lah isi data sesuai request tersebut, yaitu ayat Matius 1:1. Demikian juga di KBBI, karena ditentukan selalu merespon dengan format “definisi + sentence” maka akan keluar nya format seperti itu juga.
    Saya sudah sesuaikan file telegram-poll.php dan token.php dan simpan di PC saya (lokal, terkoneksi ke internet). Namun, respon baru dikirim jika saya eksekusi file php nya. Sedangkan jika saya kirim pesan apapun ke bot yang saya buat (ngetes_bot), tidak ada respon apapun jikta tidak dieksekusi manual file php nya. Berbeda sekali dengan bot2 yang lain termasuk alkitab dan kbbi yang langsung merespon.

    Apakah ada bagian yang terlewati untuk pemula seperti saya ini?

    1. Untuk pendekatan polling, kalau PHP-nya dijalankan di command line dengan:

      php namaskrip.php

      Maka skripnya itu akan meloop terus, karena ada bagian while true, dan tidak akan timeout. Jadi selama skrip berjalan, dia akan merespon terus.

      Jika dijalankan via server (diakses via web browser), maka setelah beberapa detik/menit, skripnya akan timeout.

      Untuk memperjelas, artikel sudah saya update.

  2. Terima kasih, ternyata betul problemnya di situ. Script telegram-poll.php saya run via browser akhirnya time out karena rupanya harus running terus ya, standby nangkep request. Akhirnya dijalankan via dos command prompt (saya pakai windows7 + xampp) dan dibiarkan terbuka, si bot otomatis mereply seperti kbbibot.

    1. Pak Yosep atau admin,, boleh tau bagaimana skript utk bs bot reply atau kirim pesan dengan cara running via dos command? Saya mencoba membuat skriptnya gagal terus. Mohon pencerahannya terima kasih.

  3. Om Yo, maaf nanya lagi. Untuk mendaftarkan perintah baru ke @botfather, saya kirim perintah /setcommands, ikuti petunjuknya dengan kirim lagi command1 – desc1, dst. Dan sudah ada balasan dari botfather katanya sukses. Tapi di bot saya cek kok tidak ada ya? Apakah ada yang harus ditambahkan di file php nya? Trims lagi 😀

    1. Mohon maaf Master Yo, ternyata ada keanehan di telegram saya. Saya /setcommands via telegram di PC tidak sukses juga, setelah dicoba di telegram Android, berhasil! Terima kasih sekali lagi ^_^

  4. tutorial buat bot kbbi dong gan, ane juga pengen buat bot kamus bahasa daerah ane. DB nya disimpan diserver. ada referensinya gk gan?

  5. Mr. Yo, saya sudah coba menggunakan script yang bapak upload..
    1. pake polling.. dan hasilnya BOT bisa mereply yang saya chat.
    2. pake webhook dan BOT belum bisa mereply yang saya chat..
    padahal
    di setinganya sudah {“ok”:true,”result”:true,”description”:”Webhook is already set”}

    mohon pencerahanntya.. disisi mana ya yang salah..
    terima kasih.

  6. Maaf Pak, mau nanya mengenai perangkat lunak apa yang digunakan untuk memasukkan script php?dan merunningnya dimana?
    Dan juga misal mau mengirimkan pesan hello, keluarnya seperti ini {“ok”:false,”error_code”:403,”description”:”Forbidden: user is deactivated”}, itu apa yang salah ya Pak?
    Terimakasih banyak

Leave a Reply

Your email address will not be published. Required fields are marked *