Rate Limit Pengguna (ratelimiter
)
ratelimiter adalah sebuah middleware yang dibuat dari framework bot grammY ataupun Telegraf yang berfungsi untuk mengatur rate-limit pengguna bot. Simpelnya, plugin ini dapat membantu kamu dalam mencegah serangan spam ke bot. Supaya lebih paham, coba lihat ilustrasi berikut:
Bagaimana Cara Kerjanya?
Dalam keadaan normal, setiap request akan langsung diproses dan dijawab oleh bot kamu. Artinya, user bisa dengan mudah melakukan spam ke bot kamu. Mereka bisa saja mengirim banyak sekali request setiap detiknya, lalu bot kamu akan memproses semua request tersebut. Lantas, bagaimana cara kita menghentikannya? Solusinya adalah dengan menggunakan ratelimiter!
Batasi User, Bukan Server Telegram!
Perlu diketahui, package ini TIDAK membatasi request yang datang dari server Telegram. Sebaliknya, ia memantau from
dari setiap request yang diterima lalu mengabaikannya begitu saja. Dengan begitu, server kamu tidak terbebani oleh pemrosesan pesan yang tidak perlu.
Opsi Pengaturan
Plugin ini menyediakan 5 opsi yang bisa diatur:
time
: Rentang waktu pemantauan request (bawaanyaFrame 1000
ms).limit
: Jumlah request yang diperbolehkan untuk setiaptime
(bawaannyaFrame 1
).storage
: Jenis penyimpanan yang dipakai untuk menyimpan hasil pemantauan user beserta request-nya. Nilai bawaanya adalahClient MEMORY
yang mana ia akan memakai in-memory Map. Kamu juga bisa menggantinya dengan Redis, serta penyimpanan-penyimpanan lain yang telah dijelaskan di bagian Tentang storage_STORE Client .on
: Sebuah function yang menentukan aksi apa yang akan dilakukan ketika user melampaui batas (bawaanya mengabaikan request tersebut).Limit Exceeded key
: Sebuah function yang mengembalikan key unik yang dibuat untuk setiap user (bawaanya menggunakanGenerator from
). Key ini digunakan untuk mengidentifikasi user, oleh karenanya ia harus unik, spesifik untuk satu user, dan dalam format string..id
Tentang storageClient
MEMORY
atau in-memory tracking cocok digunakan di sebagian besar bot. Namun, kalau kamu menggunakan cluster untuk bot kamu, maka kamu tidak bisa menggunakan penyimpanan in-memory secara efektif. Itulah kenapa kami juga menyediakan opsi Redis. Kamu bisa menerapkan Redis dengan ioredis atau redis jika kamu menggunakan Deno. Semua driver Redis yang menggunakan method incr
dan pexpire
seharusnya juga dapat bekerja sama baiknya. ratelimiter tidak berorientasi pada driver.
Catatan: Kamu harus memiliki redis-server 2.6.0 ke atas untuk menggunakan penyimpanan Redis bersama dengan ratelimiter. Versi Redis yang di bawah itu tidak didukung.
Cara Penggunaan
Ada dua cara dalam menggunakan ratelimiter:
- Menggunakan pengaturan bawaan (Konfigurasi Bawaan),
- Menentukan object khusus yang berisi konfigurasimu (Konfigurasi Manual).
Konfigurasi Bawaan
Berikut cara termudah dalam menggunakan ratelimiter dengan menerapkan perilaku bawaan:
import { limit } from "@grammyjs/ratelimiter";
// Batasi menjadi 1 pesan per detik untuk setiap user.
bot.use(limit());
2
3
4
const { limit } = require("@grammyjs/ratelimiter");
// Batasi menjadi 1 pesan per detik untuk setiap user.
bot.use(limit());
2
3
4
import { limit } from "https://deno.land/x/grammy_ratelimiter@v1.2.1/mod.ts";
// Batasi menjadi 1 pesan per detik untuk setiap user.
bot.use(limit());
2
3
4
Konfigurasi Manual
Seperti yang sudah disebutkan di awal, kamu bisa menentukan object Options
ke method limit()
untuk mengatur perilaku limiter.
import Redis from "ioredis";
import { limit } from "@grammyjs/ratelimiter";
const redis = new Redis(...);
bot.use(
limit({
// Hanya 3 pesan yang akan diproses dalam rentang waktu 2 detik.
timeFrame: 2000,
limit: 3,
// "MEMORY_STORE" adalah nilai bawaanya.
// Kamu tidak perlu mengatur storageClient jika tidak ingin menggunakan Redis.
storageClient: redis,
// Berikut akan dijalankan ketika limit terlampaui.
onLimitExceeded: async (ctx) => {
await ctx.reply("Tolong jangan kirim request berlebihan!");
},
// Key ini harus berupa angka dalam format string, misal "123456".
keyGenerator: (ctx) => {
return ctx.from?.id.toString();
},
})
);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const Redis = require("ioredis");
const { limit } = require("@grammyjs/ratelimiter");
const redis = new Redis(...);
bot.use(
limit({
// Hanya 3 pesan yang akan diproses dalam rentang waktu 2 detik.
timeFrame: 2000,
limit: 3,
// "MEMORY_STORE" adalah nilai bawaanya.
// Kamu tidak perlu mengatur storageClient jika tidak ingin menggunakan Redis.
storageClient: redis,
// Berikut akan dijalankan ketika limit terlampaui.
onLimitExceeded: async (ctx) => {
await ctx.reply("Tolong jangan kirim request berlebihan!");
},
// Key ini harus berupa angka dalam format string, misal "123456".
keyGenerator: (ctx) => {
return ctx.from?.id.toString();
},
})
);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import { connect } from "https://deno.land/x/redis/mod.ts";
import { limit } from "https://deno.land/x/grammy_ratelimiter@v1.2.1/mod.ts";
const redis = await connect(...);
bot.use(
limit({
// Hanya 3 pesan yang akan diproses dalam rentang waktu 2 detik.
timeFrame: 2000,
limit: 3,
// "MEMORY_STORE" adalah nilai bawaanya.
// Kamu tidak perlu mengatur storageClient jika tidak ingin menggunakan Redis.
storageClient: redis,
// Berikut akan dijalankan ketika limit terlampaui.
onLimitExceeded: async (ctx) => {
await ctx.reply("Tolong jangan kirim request berlebihan!");
},
// Key ini harus berupa angka dalam format string, misal "123456".
keyGenerator: (ctx) => {
return ctx.from?.id.toString();
},
})
);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Seperti yang kamu lihat dari contoh di atas, setiap user hanya diperbolehkan mengirim 3 request setiap 2 detik. Jika user tersebut mengirim request melebihi batas yang telah kita tentukan, bot akan membalas dengan, “Tolong jangan kirim request berlebihan”. Request tersebut kemudian akan diabaikan begitu saja karena kita tidak memanggil next() di middleware.
Catatan: Untuk menghindari flooding ke server Telegram,
on
hanya akan dieksekusi sekali untuk setiapLimit Exceeded time
.Frame
Contoh penggunaan lainnya adalah dengan membatasi request yang datang dari sebuah chat, alih-alih dari user tertentu:
import { limit } from "@grammyjs/ratelimiter";
bot.use(
limit({
keyGenerator: (ctx) => {
if (ctx.hasChatType(["group", "supergroup"])) {
// Key ini harus berupa angka dalam format string, misal "123456".
return ctx.chat.id.toString();
}
},
}),
);
2
3
4
5
6
7
8
9
10
11
12
const { limit } = require("@grammyjs/ratelimiter");
bot.use(
limit({
keyGenerator: (ctx) => {
if (ctx.hasChatType(["group", "supergroup"])) {
// Key ini harus berupa angka dalam format string, misal "123456".
return ctx.chat.id.toString();
}
},
}),
);
2
3
4
5
6
7
8
9
10
11
12
import { limit } from "https://deno.land/x/grammy_ratelimiter@v1.2.1/mod.ts";
bot.use(
limit({
keyGenerator: (ctx) => {
if (ctx.hasChatType(["group", "supergroup"])) {
// Key ini harus berupa angka dalam format string, misal "123456".
return ctx.chat.id.toString();
}
},
}),
);
2
3
4
5
6
7
8
9
10
11
12
Dari contoh di atas, kita menggunakan chat
sebagai key unik untuk melakukan rate-limit.