TypeScript и виды клавиатур
Что сделаем?
- Научимся запускать TypeScript файлы с помощью TSX
- Типизируем
process.env
- Познакомимся с клавиатурой и её видами
- Научимся отвечать на обычные сообщения и нажатия на инлайн клавиатуру
Запуск TypeScript файлов в Node.js
Не бойтесь. Никаких особенностей TypeScript кроме как подсказок мы сейчас использовать не будем.
На момент написания этого гайда в Node.js только-только появляется нативная поддержка запуска файлов TypeScript (Подробнее), но сейчас использовать это рано. Поэтому мы воспользуемся прекрасной библиотекой «TSX».
Для начала нам необходимо поменять расширение у файла index.js
с JavaScript на TypeScript (то есть переименовать в index.ts
). А после мы можем опробовать tsx
с помощью простой команды:
npx tsx watch --env-file=.env index.ts
Довольно просто) Теперь давайте заменим этой командой содержимое dev
команды в нашем package.json
файле.
Типизируем process.env
К сожалению, TypeScript не знает что у нас находится в файле .env
поэтому и подсказать не может. После переименования файла у вас должна была появиться ошибка у использования переменной среды BOT_TOKEN
, поэтому давайте поправим это, добавив в конце файла:
declare global {
namespace NodeJS {
interface ProcessEnv {
BOT_TOKEN: string;
}
}
}
Не пугайтесь, то что мы проделали называется Declaration merging
, то есть мы объединили TypeScript интерфейс типов для process.env
с необходимыми нам значениями в глобальной зоне видимости. Пока можете принять это как есть) Главное что ошибка исчезла и появились подсказки!
process.env.B;
Знакомство с клавиатурой и её видами
Keyboard
Давайте напишем обработчик команды /start
и отправим пользователю обычную клавиатуру.
import { Bot, Keyboard } from "gramio";
const bot = new Bot(process.env.BOT_TOKEN)
.command("start", (context) =>
context.send("Вы написали /start", {
reply_markup: new Keyboard().text("Пинг"),
})
)
.hears("Пинг", (context) => context.send("Понг"));
bot.start();
Давайте разберёмся что такое new Keyboard().text("Пинг")
.
new Keyboard().text("Пинг");
Эта конструкция написанная с удобный классом Keyboard
прячет за собой страшные вещи и на самом деле телеграм получает это уже так:
{
"keyboard": [
[
{
"text": "Пинг"
}
]
],
"one_time_keyboard": false,
"is_persistent": false,
"selective": false,
"resize_keyboard": true
}
А hears
это метод, который в отличие от command
слушает все сообщения.
InlineKeyboard
Теперь же давайте познаем всю мощь InlineKeyboard
! Давайте вместе с «Понг» будем отправлять пользователю инлайн клавиатуру!
import { Bot, Keyboard, InlineKeyboard } from "gramio";
const bot = new Bot(process.env.BOT_TOKEN)
.command("start", (context) =>
context.send("Вы написали /start", {
reply_markup: new Keyboard().text("Пинг"),
})
)
.hears("Пинг", (context) =>
context.send("Понг", {
reply_markup: new InlineKeyboard().text("Пинг", "ping"),
})
);
bot.start();
Вы спросите а что за 2 аргумент в функции text
, а я отвечу что это payload
. Грубо говоря, строка, которую нам вернёт телеграм, когда будет оповещать о нажатой кнопке. Так что давайте обработаем это событие. Оно называется callback_query
и у GramIO уже есть удобный шорт-хенд для этого!
import { Bot, Keyboard, InlineKeyboard } from "gramio";
const bot = new Bot(process.env.BOT_TOKEN)
.command("start", (context) =>
context.send("Вы написали /start", {
reply_markup: new Keyboard().text("Пинг"),
})
)
.hears("Пинг", (context) =>
context.send("Понг", {
reply_markup: new InlineKeyboard().text("Пинг", "ping"),
})
)
.callbackQuery("ping", (context) => {
await context.answer("По лбу понг");
return context.editText("Понг, но уже из callback_query!");
});
bot.start();
Теперь в ответ на нажатие кнопки с payload
равным ping редактируем текст сообщения (кнопки при этом удаляются) и показываем всплывающее окно.
RemoveKeyboard
Теперь давайте научимся удалять кнопки если пользователь напишем «Понг»
import { Bot, Keyboard, InlineKeyboard, RemoveKeyboard } from "gramio";
const bot = new Bot(process.env.BOT_TOKEN)
.command("start", (context) =>
context.send("Вы написали /start", {
reply_markup: new Keyboard().text("Пинг"),
})
)
.hears("Пинг", (context) =>
context.send("Понг", {
reply_markup: new InlineKeyboard().text("Пинг", "ping"),
})
)
.hears("Понг", (context) =>
context.send("А ты оригинален", {
reply_markup: new RemoveKeyboard(),
})
)
.callbackQuery("ping", async (context) => {
await context.answer("По лбу понг");
return context.editText("Понг, но уже из callback_query!");
});
bot.start();
ForceReply
С помощью этого вида кнопок (телеграм считает их кнопками) вы можете сделать так чтобы пользователь автоматически ответил на отправленное вами сообщение, а в поле placeholder
мы запишем значение, которое Телеграм покажет пользователю вместо стандартного «Написать сообщение...»
import {
Bot,
Keyboard,
InlineKeyboard,
RemoveKeyboard,
ForceReplyKeyboard,
} from "gramio";
const bot = new Bot(process.env.BOT_TOKEN)
.command("start", (context) =>
context.send("Вы написали /start", {
reply_markup: new Keyboard().text("Пинг").text("Вопрос"),
})
)
.hears("Вопрос", (context) => {
return context.send("Введите ответ", {
reply_markup: new ForceReplyKeyboard().placeholder(
"Введите своё ответ прямо сюда!!!"
),
});
})
.hears("Пинг", (context) =>
context.send("Понг", {
reply_markup: new InlineKeyboard().text("Пинг", "ping"),
})
)
.hears("Понг", (context) =>
context.send("А ты оригинален", {
reply_markup: new RemoveKeyboard(),
})
)
.callbackQuery("ping", async (context) => {
await context.answer("По лбу понг");
return context.editText("Понг, но уже из callback_query!");
});
bot.start();
На сегодня всё. Надеюсь ещё встретимся!