Плагин сессий
Плагин сессий для GramIO.
Установка
npm install @gramio/sessionyarn add @gramio/sessionpnpm add @gramio/sessionbun add @gramio/sessionИспользование
import { Bot } from "gramio";
import { session } from "@gramio/session";
const bot = new Bot(process.env.BOT_TOKEN as string)
.extend(
session({
key: "sessionKey",
initial: () => ({ apple: 1 }),
})
)
.on("message", (context) => {
context.send(`количество яблок: ${++context.sessionKey.apple}`);
})
.onStart(console.log);
bot.start();Этот плагин можно использовать с любым хранилищем (Подробнее)
Пример с Redis
import { Bot } from "gramio";
import { session } from "@gramio/session";
import { redisStorage } from "@gramio/storage-redis";
const bot = new Bot(process.env.BOT_TOKEN as string)
.extend(
session({
key: "sessionKey",
initial: () => ({ apple: 1 }),
storage: redisStorage(),
})
)
.on("message", (context) => {
context.send(`количество яблок: ${++context.sessionKey.apple}`);
})
.onStart(console.log);
bot.start();Ленивые сессии
По умолчанию сессия загружается из хранилища при каждом обновлении, даже если обработчик к ней не обращается. Опция lazy: true откладывает загрузку до момента первого обращения к сессии, что позволяет значительно сократить число лишних запросов к хранилищу на высоконагруженных ботах.
import { Bot } from "gramio";
import { session } from "@gramio/session";
const bot = new Bot(process.env.BOT_TOKEN as string)
.extend(
session({
key: "sessionKey",
lazy: true,
initial: () => ({ count: 0 }),
})
)
.on("message", async (context) => {
// Хранилище не читается до этой строки:
const s = await context.sessionKey;
s.count++;
await context.send(`счётчик: ${s.count}`);
});В ленивом режиме context.sessionKey является Promise — всегда используйте await перед обращением к данным.
Очистка сессии
Вызов $clear() на объекте сессии удаляет её из хранилища и сбрасывает к начальному состоянию при следующем обращении.
bot.on("message", async (context) => {
if (context.text === "/reset") {
await context.sessionKey.$clear();
}
});В ленивом режиме сначала нужно разрешить промис:
bot.on("message", async (context) => {
if (context.text === "/reset") {
const s = await context.sessionKey;
await s.$clear();
}
});Произвольные ключи сессий
По умолчанию сессии хранятся по senderId. Используйте getSessionKey, чтобы изменить стратегию именования.
// Сессия на уровне чата
session({
getSessionKey: (ctx) => `chat:${ctx.chatId}`,
initial: () => ({ topic: "" }),
})
// Сессия на уровне пользователь + чат
session({
getSessionKey: (ctx) => `${ctx.senderId}:${ctx.chatId}`,
initial: () => ({ preferences: {} }),
})TypeScript
Тип данных сессии выводится автоматически из возвращаемого типа функции initial. При необходимости можно задать явный интерфейс.
interface MySessionData {
apple: number;
some?: "maybe-empty";
}
// Обычный режим — ctx.sessionKey: MySessionData & { $clear(): Promise<void> }
bot.extend(
session({
key: "sessionKey",
initial: (): MySessionData => ({ apple: 1 }),
})
);
// Ленивый режим — ctx.sessionKey: Promise<MySessionData & { $clear(): Promise<void> }>
bot.extend(
session({
key: "sessionKey",
lazy: true,
initial: (): MySessionData => ({ apple: 1 }),
})
);