Created
April 2, 2021 12:23
-
-
Save waptik/ae5926418222a7d8687720b72353699a to your computer and use it in GitHub Desktop.
implementation of telegraf-session using Prisma as datastore based on https://github.com/alexnzarov/telegraf-session-mongodb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Context, Telegraf } from 'telegraf' | |
import { PrismaClient } from '@prisma/client' | |
import { session } from 'utils/telegraf-session-prisma' // path to session module | |
const prisma = new PrismaClient() | |
interface SessionData { | |
messageCount: number | |
// ... more session data go here | |
} | |
// Define your own context type | |
interface MyContext extends Context { | |
session?: SessionData | |
// ... more props go here | |
} | |
if (process.env.BOT_TOKEN === undefined) { | |
throw new TypeError('BOT_TOKEN must be provided!') | |
} | |
// Create your bot and tell it about your context type | |
const bot = new Telegraf<MyContext>(process.env.BOT_TOKEN) | |
// Make session data available | |
bot.use(session(prisma)) | |
// Register middleware | |
bot.on('message', async (ctx) => { | |
// set a default value | |
ctx.session ??= { messageCount: 0 } | |
ctx.session.messageCount++ | |
await ctx.reply(`Seen ${ctx.session.messageCount} messages.`) | |
}) | |
// Launch bot | |
// eslint-disable-next-line @typescript-eslint/no-floating-promises | |
bot.launch() | |
// Enable graceful stop | |
process.once('SIGINT', () => bot.stop('SIGINT')) | |
process.once('SIGTERM', () => bot.stop('SIGTERM')) | |
Terms |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Context } from "telegraf" | |
export type SessionKeyFunction = (ctx: Context) => string | null | |
// Mocking the behaviour from the default memory session implementation. | |
// Source: https://telegraf.js.org/modules.html#session | |
// This is possible due to getters that fetch 'from' and 'chat' values from different sources. | |
export const getSessionKey = ({ from, chat }: Context) => { | |
if (from == null || chat == null) { | |
return null | |
} | |
return `${from.id}:${chat.id}` | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# above are previous models | |
model Session { | |
id String @unique @default(uuid()) | |
key String @unique | |
data Json | |
createdAt DateTime @default(now()) | |
updatedAt DateTime @updatedAt | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Telegraf session using Prisma as datastore | |
* @author gh:waptik | |
**/ | |
import { Context, MiddlewareFn } from "telegraf" | |
import { getSessionKey, SessionKeyFunction } from "./keys" | |
import { PrismaClient } from "@prisma/client" | |
export type SessionOptions = { | |
sessionName: string | |
sessionKeyFn: SessionKeyFunction | |
} | |
export const session = <C extends Context = Context>( | |
db: PrismaClient, | |
sessionOptions?: Partial<SessionOptions> | |
): MiddlewareFn<C> => { | |
const options: SessionOptions = { | |
sessionName: "session", | |
sessionKeyFn: getSessionKey, | |
...sessionOptions, | |
} | |
const model = db[options.sessionName] | |
const saveSession = async (key: string, data: any) => | |
await model.upsert({ | |
where: { | |
key, | |
}, | |
update: { data }, | |
create: { key, data }, | |
}) | |
const getSession = async (key: string) => { | |
const res = await model.findUnique({ where: { key } }) | |
return res?.data | |
} | |
const { sessionKeyFn: getKey, sessionName } = options | |
return async (ctx: Context, next) => { | |
const key = getKey(ctx) | |
const data = key == null ? undefined : await getSession(key) | |
ctx[sessionName] = data | |
await next() | |
if (ctx[sessionName] != null && key !== null) { | |
await saveSession(key, ctx[sessionName]) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
repo at https://github.com/waptik/telegraf-session-prisma