Режим форматування (parse-mode )
Як відомо, Telegram підтримує стилізовані повідомлення. Ця бібліотека надає спрощені утиліти форматування для grammY. Вона дозволяє створювати різноманітно оформлені повідомлення за допомогою декларативного, типобезпечного API.
У Telegram Bot API форматований текст представлено за допомогою сутностей — спеціальних маркерів, які визначають, як слід форматувати певні частини тексту. Кожна сутність має type (тип, наприклад, bold, italic тощо), offset (зсув, де сутність починається в тексті) та length (довжину, на скільки символів вона впливає).
Робота безпосередньо з цими сутностями може бути громіздкою, оскільки потрібно вручну відстежувати зсуви та довжини. Цей плагін вирішує цю проблему, надаючи простий, декларативний API для форматування тексту.
Два підходи: fmt та FormattedString
Ця бібліотека надає два основні підходи для форматування тексту:
Шаблонна функція
fmt: Шаблонна функція, яка дозволяє писати форматований текст природним чином за допомогою шаблонних виразів. Всередині вона керує зсувами та довжинами сутностей за вас.Клас
Formatted: Підхід на основі класів, який дозволяє створювати форматований текст через ланцюжок методів. Це особливо корисно для програмного створення складних форматованих повідомлень.String
Обидва підходи створюють уніфікований обʼєкт Formatted, який можна використовувати для маніпулювання форматованим текстом.
Використання (за допомогою fmt)
import { Bot } from "grammy";
import { b, fmt, u } from "@grammyjs/parse-mode";
const bot = new Bot("");
bot.command("demo", async (ctx) => {
// Використання значень, що повертаються функцією `fmt`.
const combined = fmt`${b}жирний${b} ${ctx.msg.text} ${u}підкреслений${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) => {
// Використання значень, що повертаються функцією `fmt`.
const combined = fmt`${b}жирний${b} ${ctx.msg.text} ${u}підкреслений${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) => {
// Використання значень, що повертаються функцією `fmt`.
const combined = fmt`${b}жирний${b} ${ctx.msg.text} ${u}підкреслений${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
Використання (за допомогою FormattedString )
import { Bot } from "grammy";
import { FormattedString } from "@grammyjs/parse-mode";
const bot = new Bot("");
bot.command("demo", async (ctx) => {
// Статичні методи.
const staticCombined = FormattedString.b("жирний").plain(` ${ctx.msg.text} `)
.u("підкреслений");
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,
},
);
// Або конструктор.
const constructorCombined = (new FormattedString("")).b("жирний").plain(
` ${ctx.msg.text} `,
).u("підкреслений");
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) => {
// Статичні методи.
const staticCombined = FormattedString.b("жирний").plain(` ${ctx.msg.text} `)
.u("підкреслений");
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,
},
);
// Або конструктор.
const constructorCombined = (new FormattedString("")).b("жирний").plain(
` ${ctx.msg.text} `,
).u("підкреслений");
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
import { Bot } from "https://deno.land/x/grammy@v1.41.1/mod.ts";
import { FormattedString } from "https://deno.land/x/grammy_parse_mode@2.2.1/mod.ts";
const bot = new Bot("");
bot.command("demo", async (ctx) => {
// Статичні методи.
const staticCombined = FormattedString.b("жирний").plain(` ${ctx.msg.text} `)
.u("підкреслений");
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,
},
);
// Або конструктор.
const constructorCombined = (new FormattedString("")).b("жирний").plain(
` ${ctx.msg.text} `,
).u("підкреслений");
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
Основні концепції
FormattedString як уніфікований тип повернення
Клас Formatted є основним компонентом плагіна режиму форматування (parse), що надає уніфікований інтерфейс для роботи з форматованим текстом. Значення, повернене fmt, new Formatted та Formatted, повертає екземпляр Formatted. Це означає, що можливо комбінувати різні стилі використання.
Наприклад, можна використати шаблонну функцію fmt, за якою слідує ланцюжок методів екземпляра Formatted, а потім передати результат в іншу шаблонну функцію fmt.
bot.on("msg:text", async (ctx) => {
// Результат fmt`${u}Памʼять оновлено!${u}` є екземпляром `FormattedString`,
// чий виклик методу екземпляра `.plain("\n")` також повертає `FormattedString`.
const header = fmt`${u}Памʼять оновлено!${u}`.plain("\n");
const body = FormattedString.plain("Я запамʼятаю це!");
const footer = "\n - від grammY ШІ";
// Також допустимо, що ви можете передати `FormattedString` та рядок до `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
Що приймає fmt
Шаблонна функція fmt приймає широкий спектр значень для створення вашого екземпляру Formatted, включно з:
Text, реалізованийWith Entities Formattedта звичайними текстовими повідомленнями Telegram.String Caption, реалізованийWith Entities Formattedта звичайними медіаповідомленнями Telegram з підписами.String Entity, як-от ваші функціїTag b()таa(url).- Функції без аргументів, що повертають
Entity(наприклад,Tag bтаi). - Будь-які типи, що реалізують
to(вони будуть оброблені як звичайний текст).String()
TextWithEntities
Інтерфейс Text представляє текст з необовʼязковими сутностями форматування.
interface TextWithEntities {
text: string;
entities?: MessageEntity[];
}2
3
4
Зауважте, що форма цього типу означає, що звичайні текстові повідомлення від Telegram також неявно реалізують Text. Це означає, що можна зробити наступне:
bot.on("msg:text", async (ctx) => {
const response = fmt`${ctx.msg}`.plain("\n---\n").bold("Це моя відповідь");
await ctx.reply(response.text, { entities: response.entities });
});2
3
4
CaptionWithEntities
Інтерфейс Caption представляє підпис з необовʼязковими сутностями форматування.
interface CaptionWithEntities {
caption: string;
caption_entities?: MessageEntity[];
}2
3
4
Так само зауважте, що форма цього типу означає, що звичайні медіаповідомлення з підписом від Telegram також неявно реалізують Caption. Це означає, що також можна зробити наступне:
bot.on("msg:caption", async (ctx) => {
const response = fmt`${ctx.msg}`.plain("\n---\n").bold("Це моя відповідь");
await ctx.reply(response.text, { entities: response.entities });
});2
3
4