Plugin Parse Mode (parse-mode )
Telegram menyediakan styled messages. Library ini menambahkan utilitas formatting yang lebih simpel buat grammY. Fitur ini memungkinkan kamu untuk menyusun pesan dengan format lengkap dengan API deklaratif yang type-safe.
Dalam Telegram Bot API, teks yang diformat ditandai dengan menggunakan entity — semacam marker khusus untuk nunjukin bagian mana teks yang diberikan format tertentu. Setiap entity memiliki tipe (contoh: bold, italic, dll), offset (mulai dari indeks keberapa), dan length (jumlah karakter yang terpengaruh).
Bekerja langsung dengan entity bisa merepotkan karena kita perlu melacak offset dan length secara manual. Plugin Parse Mode menyelesaikan permasalahan ini dengan menyediakan API deklaratif yang sederhana untuk memformat teks.
Dua Pendekatan: fmt dan FormattedString
Pustaka ini menawarkan dua pendekatan utama untuk performatan teks:
Fungsi Tagged Template
fmt: Sebuah template literal tag yang memungkinkan kamu menulis teks terformat dengan cara yang alami menggunakan ekspresi template. Secara internal, fungsi ini mengelola offset dan length untuk kamu.Kelas
Formatted: Pendekatan berbasis kelas yang memungkinkan kamu membuat teks terformat melalui method chaining. Ini sangat berguna untuk membuat secara terprogram menyusun pesan terformat yang kompleks.String
Kedua pendekatan menghasilkan objek Formatted yang terpadu, yang dapat digunakan untuk memanipulasi teks terformat.
Penggunaan (dengan fmt)
import { Bot } from "grammy";
import { b, fmt, u } from "@grammyjs/parse-mode";
const bot = new Bot("");
bot.command("demo", async (ctx) => {
// Menggunakan nilai kembalian dari fmt
const combined = fmt`${b}bolded${b} ${ctx.msg.text} ${u}underlined${u}`;
await ctx.reply(combined.text, { entities: combined.entities });
await ctx.replyWithPhoto(
"https://raw.githubusercontent.com/grammyjs/website/main/logos/grammY.png",
{ caption: combined.caption, caption_entities: combined.caption_entities },
);
});
bot.start();2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const { Bot } = require("grammy");
const { fmt, b, u } = require("@grammyjs/parse-mode");
const bot = new Bot("");
bot.command("demo", async (ctx) => {
// Menggunakan nilai kembalian dari fmt
const combined = fmt`${b}bolded${b} ${ctx.msg.text} ${u}underlined${u}`;
await ctx.reply(combined.text, { entities: combined.entities });
await ctx.replyWithPhoto(
"https://raw.githubusercontent.com/grammyjs/website/main/logos/grammY.png",
{ caption: combined.caption, caption_entities: combined.caption_entities },
);
});
bot.start();2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { Bot } from "https://deno.land/x/grammy@v1.41.1/mod.ts";
import { b, fmt, u } from "https://deno.land/x/grammy_parse_mode@2.2.1/mod.ts";
const bot = new Bot("");
bot.command("demo", async (ctx) => {
// Menggunakan nilai kembalian dari fmt
const combined = fmt`${b}bolded${b} ${ctx.msg.text} ${u}underlined${u}`;
await ctx.reply(combined.text, { entities: combined.entities });
await ctx.replyWithPhoto(
"https://raw.githubusercontent.com/grammyjs/website/main/logos/grammY.png",
{ caption: combined.caption, caption_entities: combined.caption_entities },
);
});
bot.start();2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Penggunaan (dengan FormattedString )
import { Bot } from "grammy";
import { FormattedString } from "@grammyjs/parse-mode";
const bot = new Bot("");
bot.command("demo", async (ctx) => {
// Static method
const staticCombined = FormattedString.b("bolded").plain(` ${ctx.msg.text} `)
.u("underlined");
await ctx.reply(staticCombined.text, { entities: staticCombined.entities });
await ctx.replyWithPhoto(
"https://raw.githubusercontent.com/grammyjs/website/main/logos/grammY.png",
{
caption: staticCombined.caption,
caption_entities: staticCombined.caption_entities,
},
);
// Atau dengan constructor
const constructorCombined = (new FormattedString("")).b("bolded").plain(
` ${ctx.msg.text} `,
).u("underlined");
await ctx.reply(constructorCombined.text, {
entities: constructorCombined.entities,
});
await ctx.replyWithPhoto(
"https://raw.githubusercontent.com/grammyjs/website/main/logos/grammY.png",
{
caption: constructorCombined.caption,
caption_entities: constructorCombined.caption_entities,
},
);
});
bot.start();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
const { Bot } = require("grammy");
const { FormattedString } = require("@grammyjs/parse-mode");
const bot = new Bot("");
bot.command("demo", async (ctx) => {
// Static method
const staticCombined = FormattedString.b("bolded").plain(` ${ctx.msg.text} `)
.u("underlined");
await ctx.reply(staticCombined.text, { entities: staticCombined.entities });
await ctx.replyWithPhoto(
"https://raw.githubusercontent.com/grammyjs/website/main/logos/grammY.png",
{
caption: staticCombined.caption,
caption_entities: staticCombined.caption_entities,
},
);
// Atau dengan constructor
const constructorCombined = (new FormattedString("")).b("bolded").plain(
` ${ctx.msg.text} `,
).u("underlined");
await ctx.reply(constructorCombined.text, {
entities: constructorCombined.entities,
});
await ctx.replyWithPhoto(
"https://raw.githubusercontent.com/grammyjs/website/main/logos/grammY.png",
{
caption: constructorCombined.caption,
caption_entities: constructorCombined.caption_entities,
},
);
});
bot.start();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
const { Bot } = require("grammy");
const { FormattedString } = require("@grammyjs/parse-mode");
const bot = new Bot("");
bot.command("demo", async (ctx) => {
// Static method
const staticCombined = FormattedString.b("bolded").plain(` ${ctx.msg.text} `)
.u("underlined");
await ctx.reply(staticCombined.text, { entities: staticCombined.entities });
await ctx.replyWithPhoto(
"https://raw.githubusercontent.com/grammyjs/website/main/logos/grammY.png",
{
caption: staticCombined.caption,
caption_entities: staticCombined.caption_entities,
},
);
// Atau dengan constructor
const constructorCombined = (new FormattedString("")).b("bolded").plain(
` ${ctx.msg.text} `,
).u("underlined");
await ctx.reply(constructorCombined.text, {
entities: constructorCombined.entities,
});
await ctx.replyWithPhoto(
"https://raw.githubusercontent.com/grammyjs/website/main/logos/grammY.png",
{
caption: constructorCombined.caption,
caption_entities: constructorCombined.caption_entities,
},
);
});
bot.start();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
Konsep Inti
FormattedString sebagai Unified Return Type
Kelas Formatted adalah komponen inti dari parse-mode plugin, yang menyediakan antarmuka terpadu untuk bekerja dengan teks terformat. Nilai kembalian dari fmt, new Formatted, maupun Formatted semuanya berupa instance Formatted. Ini berarti penggunaan gaya berbeda dapat digabungkan.
Contohnya kamu bisa menggunakan fmt, lalu menambahkan method chain dari Formatted, dan akhirnya meneruskan kembali ke template tag fmt.
bot.on("msg:text", async ctx => {
// Hasil dari fmt`${${u}Memory updated!${u}}` adalah FormattedString
// pemanggilan method `.plain("\n") juga mengembalikan FormattedString
const header = fmt`${${u}Memory updated!${u}}`.plain("\n");
const body = FormattedString.plain("I will remember this!");
const footer = "\n - by grammy AI";
// Ini juga valid - kamu bisa memberikan FormattedString dan string ke `fmt`
const response = fmt`${header}${body}${footer}`;
await ctx.reply(response.text, { entities: response.entities });
});2
3
4
5
6
7
8
9
10
11
Nilai yang diterima oleh fmt
Fungsi tagged template fmt menerima berbagai macam nilai untuk membangun Formatted kamu, termasuk:
Text(diimplementasikan olehWith Entities Formatteddan pesan teks Telegram biasa)String Caption(diimplementasikan olehWith Entities Formatteddan pesan media Telegram dengan caption)String - EntityTag (seperti fungsi
b()dana(url)) - Fungsi tanpa argumen (nullary functions) yang mengembalikan EntityTag (misalnya
bdani) - Tipe apapun yang mengimplementasikan
to(akan diperlakukan sebagai teks biasa)String()
TextWithEntities
Interface Text merepresentasikan teks dengan entity performatan opsional.
interface TextWithEntities {
text: string;
entities?: MessageEntity[];
}2
3
4
Perhatikan bahwa bentuk tipe ini menyiratkan bahwa pesan teks biasa dari Telegram juga mengimplementasikan Text secara implisit. Ini berarti bahwa sebenarnya memungkinkan untuk melakukan hal berikut:
bot.on("msg:text", async (ctx) => {
const response = fmt`${ctx.msg}`.plain("\n---\n").bold("Ini respon saya");
await ctx.reply(response.text, { entities: response.entities });
});2
3
4
CaptionWithEntities
Interface Caption merepresentasikan sebuah caption dengan entitas performatan opsional.
interface CaptionWithEntities {
caption: string;
caption_entities?: MessageEntity[];
}2
3
4
Demikian perhatikan bahwa bentuk tipe ini menyiratkan bahwa pesan media biasa dengan caption dari Telegram juga secara implisit mengimplementasikan Caption. Ini berarti bahwa sebenarnya juga memungkinkan untuk melakukan hal berikut:
bot.on("msg:caption", async (ctx) => {
const response = fmt`${ctx.msg}`.plain("\n---\n").bold("Ini respon saya");
await ctx.reply(response.text, { entities: response.entities });
});2
3
4