Router (router
)
Class Router
(Referensi API) berfungsi untuk mengatur rute suatu object context ke berbagai tempat di kode kamu. Plugin ini serupa dengan bot
di Composer
(grammY API Reference), namun ia jauh lebih canggih.
Contoh
Berikut contoh penggunaan router:
const router = new Router((ctx) => {
// Tentukan rute yang akan dipilih di sini.
return "key";
});
router.route("key", async (ctx) => {/* ... */});
router.route("key-lainnya", async (ctx) => {/* ... */});
router.otherwise((ctx) => {/* ... */}); // Akan dipanggil jika tidak ada rute yang sesuai
bot.use(router);
2
3
4
5
6
7
8
9
10
Integrasi ke Middleware
Plugin router dapat diintegrasikan dengan middleware tree grammY. Contohnya, kamu bisa mem-filter update setelah mengatur rute mereka.
router.route("key").on("message:text", async (ctx) => {/* ... */});
const other = router.otherwise();
other.on(":text", async (ctx) => {/* ... */});
other.use((ctx) => {/* ... */});
2
3
4
5
Kamu mungkin juga tertarik untuk membaca materi lain mengenai pengombinasian handler middleware
Mengombinasikan Router dengan Session
Router juga bisa dikombinasikan dengan session. Misalnya, kamu dapat membuat kembali form di interface chat dengan mengombinasikan keduanya.
Catatan: Plugin conversations menyediakan metode yang lebih baik dari plugin ini. Oleh karena itu, isi dari halaman ini sebenarnya sudah tidak berlaku lagi. Namun, kami tetap menyediakan dokumentasi ini sebagai rujukan untuk para pengguna yang masih menggunakan plugin router untuk membuat form.
Anggaplah kamu ingin membuat sebuah bot yang memberitahu user berapa hari yang tersisa menuju ulang tahun mereka. Untuk menghitung sisa hari tersebut, bot harus mengetahui tanggal serta bulan ulang tahun mereka.
Untuk mendapatkan informasi tersebut, bot perlu mengajukan dua pertanyaan:
- User lahir di bulan apa?
- User lahir di tanggal berapa?
Bot bisa memberi tahu user jumlah hari yang tersisa jika kedua hal tersebut diketahui.
Berikut cara implementasinya:
import { Bot, Context, Keyboard, session, SessionFlavor } from "grammy";
import { Router } from "@grammyjs/router";
interface SessionData {
step: "idle" | "day" | "month"; // di tahap form mana kita berada
dayOfMonth?: number; // tanggal ulang tahun
month?: number; // bulan ulang tahun
}
type MyContext = Context & SessionFlavor<SessionData>;
const bot = new Bot<MyContext>("");
// Gunakan session.
bot.use(session({ initial: (): SessionData => ({ step: "idle" }) }));
// Tentukan beberapa command.
bot.command("start", async (ctx) => {
await ctx.reply(`Selamat datang!
Aku bisa memberi tahu kamu jumlah hari yang tersisa menuju hari ulang tahunmu!
Kirim /ulangtahun untuk memulai.`);
});
bot.command("ulangtahun", async (ctx) => {
const day = ctx.session.dayOfMonth;
const month = ctx.session.month;
if (day !== undefined && month !== undefined) {
// Informasi sudah tersedia!
await ctx.reply(
`Ulang tahun kamu tinggal ${getDays(month, day)} hari lagi!`,
);
} else {
// Informasi tidak tersedia, masuk ke mode form router
ctx.session.step = "day";
await ctx.reply(
"Kirim hari \
ulang tahunmu dalam format angka!",
);
}
});
// Gunakan router.
const router = new Router<MyContext>((ctx) => ctx.session.step);
// Tentukan aksi yang akan dilakukan ketika berada di tahap form "day".
const day = router.route("day");
day.on("message:text", async (ctx) => {
const day = parseInt(ctx.msg.text, 10);
if (isNaN(day) || day < 1 || 31 < day) {
await ctx.reply("Ups, itu bukan tanggal yang valid. Silahkan coba lagi!");
return;
}
ctx.session.dayOfMonth = day;
// Form lanjutan untuk step "month"
ctx.session.step = "month";
await ctx.reply("Baik! Sekarang, kirim bulannya!", {
reply_markup: {
one_time_keyboard: true,
keyboard: new Keyboard()
.text("Jan").text("Feb").text("Mar").row()
.text("Apr").text("May").text("Jun").row()
.text("Jul").text("Aug").text("Sep").row()
.text("Oct").text("Nov").text("Dec").build(),
},
});
});
day.use((ctx) =>
ctx.reply("Kirim tanggal ulang tahunmu dalam bentuk pesan teks!")
);
// Tentukan aksi yang akan dilakukan ketika menangani step "month".
const month = router.route("month");
month.on("message:text", async (ctx) => {
// Kemungkinan besar tidak akan terjadi, kecuali data session-nya corrupt.
const day = ctx.session.dayOfMonth;
if (day === undefined) {
await ctx.reply("Kirimkan kembali tanggal ulang tahunmu!");
ctx.session.step = "day";
return;
}
const month = months.indexOf(ctx.msg.text);
if (month === -1) {
await ctx.reply(
"Ups, itu bukan bulan yang valid. \
Silahkan gunakan tombol berikut!",
);
return;
}
ctx.session.month = month;
const diff = getDays(month, day);
await ctx.reply(
`Kamu berulang tahun pada ${day} ${months[month]}.
Berarti, ulang tahunmu sisa ${diff} hari lagi!`,
{ reply_markup: { remove_keyboard: true } },
);
ctx.session.step = "idle";
});
month.use((ctx) => ctx.reply("Silahkan tekan salah satu tombol berikut!"));
// Tentukan aksi yang akan diambil untuk situasi lainnya.
router.otherwise(async (ctx) => { // idle
await ctx.reply(
"Kirim /ulangtahun untuk mengetahui jumlah hari yang tersisa menuju hari ulang tahunmu.",
);
});
bot.use(router); // register router-nya
bot.start();
// Konversi tanggal
const months = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
];
function getDays(month: number, day: number) {
const bday = new Date();
const now = Date.now();
bday.setMonth(month);
bday.setDate(day);
if (bday.getTime() < now) bday.setFullYear(bday.getFullYear() + 1);
const diff = (bday.getTime() - now) / (1000 * 60 * 60 * 24);
return diff;
}
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
const { Bot, Context, Keyboard, session, SessionFlavor } = require("grammy");
const { Router } = require("@grammyjs/router");
const bot = new Bot("");
// Gunakan session.
bot.use(session({ initial: () => ({ step: "idle" }) }));
// Tentukan beberapa command.
bot.command("start", async (ctx) => {
await ctx.reply(`Selamat datang!
Aku bisa memberi tahu kamu jumlah hari yang tersisa menuju hari ulang tahunmu!
Kirim /ulangtahun untuk memulai.`);
});
bot.command("ulangtahun", async (ctx) => {
const day = ctx.session.dayOfMonth;
const month = ctx.session.month;
if (day !== undefined && month !== undefined) {
// Informasi sudah tersedia!
await ctx.reply(
`Ulang tahun kamu tinggal ${getDays(month, day)} hari lagi!`,
);
} else {
// Informasi tidak tersedia, masuk ke mode form router
ctx.session.step = "day";
await ctx.reply(
"Kirim tanggal \
ulang tahunmu dalam format angka!",
);
}
});
// Gunakan router.
const router = new Router((ctx) => ctx.session.step);
// Tentukan aksi yang akan dilakukan ketika berada di tahap form "day".
const day = router.route("day");
day.on("message:text", async (ctx) => {
const day = parseInt(ctx.msg.text, 10);
if (isNaN(day) || day < 1 || 31 < day) {
await ctx.reply("Ups, itu bukan tanggal yang valid. Silahkan coba lagi!");
return;
}
ctx.session.dayOfMonth = day;
// Form lanjutan untuk step "month"
ctx.session.step = "month";
await ctx.reply("Baik! Sekarang, kirim bulannya!", {
reply_markup: {
one_time_keyboard: true,
keyboard: new Keyboard()
.text("Jan").text("Feb").text("Mar").row()
.text("Apr").text("May").text("Jun").row()
.text("Jul").text("Aug").text("Sep").row()
.text("Oct").text("Nov").text("Dec").build(),
},
});
});
day.use((ctx) =>
ctx.reply("Kirim tanggal ulang tahunmu dalam bentuk pesan teks!")
);
// Tentukan aksi yang akan dilakukan ketika menangani step "month".
const month = router.route("month");
month.on("message:text", async (ctx) => {
// Kemungkinan besar tidak akan terjadi, kecuali data session-nya corrupt.
const day = ctx.session.dayOfMonth;
if (day === undefined) {
await ctx.reply("Kirimkan kembali tanggal ulang tahunmu!");
ctx.session.step = "day";
return;
}
const month = months.indexOf(ctx.msg.text);
if (month === -1) {
await ctx.reply(
"Ups, itu bukan bulan yang valid. \
Gunakan tombol berikut!",
);
return;
}
ctx.session.month = month;
const diff = getDays(month, day);
await ctx.reply(
`Kamu berulang tahun pada ${day} ${months[month]}.
Berarti, ulang tahunmu sisa ${diff} hari lagi!`,
{ reply_markup: { remove_keyboard: true } },
);
ctx.session.step = "idle";
});
month.use((ctx) => ctx.reply("Tekan salah satu tombol berikut!"));
// Tentukan aksi yang akan diambil untuk situasi lainnya.
router.otherwise(async (ctx) => { // idle
await ctx.reply(
"Kirim /ulangtahun untuk mengetahui jumlah hari yang tersisa menuju hari ulang tahunmu.",
);
});
bot.use(router); // register router-nya
bot.start();
// Konversi tanggal
const months = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
];
function getDays(month, day) {
const bday = new Date();
const now = Date.now();
bday.setMonth(month);
bday.setDate(day);
if (bday.getTime() < now) bday.setFullYear(bday.getFullYear() + 1);
const diff = (bday.getTime() - now) / (1000 * 60 * 60 * 24);
return diff;
}
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import {
Bot,
Context,
Keyboard,
session,
SessionFlavor,
} from "https://deno.land/x/grammy@v1.27.0/mod.ts";
import { Router } from "https://deno.land/x/grammy_router@v2.0.0/router.ts";
interface SessionData {
step: "idle" | "day" | "month"; // di tahap form mana kita berada
dayOfMonth?: number; // tanggal ulang tahun
month?: number; // bulan ulang tahun
}
type MyContext = Context & SessionFlavor<SessionData>;
const bot = new Bot<MyContext>("");
// Gunakan session.
bot.use(session({ initial: (): SessionData => ({ step: "idle" }) }));
// Tentukan beberapa command.
bot.command("start", async (ctx) => {
await ctx.reply(`Selamat datang!
Aku bisa memberi tahu kamu jumlah hari yang tersisa menuju hari ulang tahunmu!
Kirim /ulangtahun untuk memulai.`);
});
bot.command("ulangtahun", async (ctx) => {
const day = ctx.session.dayOfMonth;
const month = ctx.session.month;
if (day !== undefined && month !== undefined) {
// Informasi sudah tersedia!
await ctx.reply(
`Ulang tahun kamu tinggal ${getDays(month, day)} hari lagi!`,
);
} else {
// Informasi tidak tersedia, masuk ke mode form router
ctx.session.step = "day";
await ctx.reply(
"Kirim tanggal \
ulang tahunmu dalam format angka!",
);
}
});
// Gunakan router.
const router = new Router<MyContext>((ctx) => ctx.session.step);
// Tentukan aksi yang akan dilakukan ketika berada di tahap form "day".
const day = router.route("day");
day.on("message:text", async (ctx) => {
const day = parseInt(ctx.msg.text, 10);
if (isNaN(day) || day < 1 || 31 < day) {
await ctx.reply("Ups, itu bukan tanggal yang valid. Silahkan coba lagi!");
return;
}
ctx.session.dayOfMonth = day;
// Form lanjutan untuk step "month"
ctx.session.step = "month";
await ctx.reply("Baik! Sekarang, kirim bulannya!", {
reply_markup: {
one_time_keyboard: true,
keyboard: new Keyboard()
.text("Jan").text("Feb").text("Mar").row()
.text("Apr").text("May").text("Jun").row()
.text("Jul").text("Aug").text("Sep").row()
.text("Oct").text("Nov").text("Dec").build(),
},
});
});
day.use((ctx) =>
ctx.reply("Kirim tanggal ulang tahunmu dalam bentuk pesan teks!")
);
// Tentukan aksi yang akan dilakukan ketika menangani step "month".
const month = router.route("month");
month.on("message:text", async (ctx) => {
// Kemungkinan besar tidak akan terjadi, kecuali data session-nya corrupt.
const day = ctx.session.dayOfMonth;
if (day === undefined) {
await ctx.reply("Kirimkan kembali tanggal ulang tahunmu!");
ctx.session.step = "day";
return;
}
const month = months.indexOf(ctx.msg.text);
if (month === -1) {
await ctx.reply(
"Ups, itu bukan bulan yang valid. \
Silahkan gunakan tombol berikut!",
);
return;
}
ctx.session.month = month;
const diff = getDays(month, day);
await ctx.reply(
`Kamu berulang tahun pada ${day} ${months[month]}.
Berarti, ulang tahunmu sisa ${diff} hari lagi!`,
{ reply_markup: { remove_keyboard: true } },
);
ctx.session.step = "idle";
});
month.use((ctx) => ctx.reply("Silahkan tekan salah satu tombol berikut!"));
// Tentukan aksi yang akan diambil untuk situasi lainnya.
router.otherwise(async (ctx) => { // idle
await ctx.reply(
"Kirim /ulangtahun untuk mengetahui jumlah hari yang tersisa menuju hari ulang tahunmu.",
);
});
bot.use(router); // register router-nya
bot.start();
// Konversi tanggal
const months = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
];
function getDays(month: number, day: number) {
const bday = new Date();
const now = Date.now();
bday.setMonth(month);
bday.setDate(day);
if (bday.getTime() < now) bday.setFullYear(bday.getFullYear() + 1);
const diff = (bday.getTime() - now) / (1000 * 60 * 60 * 24);
return diff;
}
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
Perhatikan session di atas memiliki property step
untuk menyimpan step dari form tersebut, misalnya untuk mengetahui value mana yang sedang diisi. Router digunakan untuk berpindah antara middleware satu dengan lainnya ketika kedua isian month
dan day
telah terisi. Ketika kedua nilai tersebut diketahui, bot akan menghitung sisa harinya lalu mengirim hasil perhitungan ke user.