
Security News
Meet Socket at Black Hat and DEF CON 2025 in Las Vegas
Meet Socket at Black Hat & DEF CON 2025 for 1:1s, insider security talks at Allegiant Stadium, and a private dinner with top minds in software supply chain security.
chat-toolkit
Advanced tools
 <img alt="NPM Downloads" src="https://img.shields.io/npm/dy/chat-toolkit?link=https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fchat-tool
it's library/toolkit for easier chat-bot state managment/persistion
currently only telegram API supported, further extension for discrod API possible
Describe state using actions like say
, expect
, switchState
and others
export async function mainState() {
await say('Enter a')
const a = Number(await expect_())
await say('Enter b')
const b = Number(await expect_())
await say("Reuslt is " + (a + b))
await switchState('mainState')
// or
await stateSwitcher.mainState()
}
And then add that state to AllStates to safe typing
declare module 'chat-toolkit' {
interface AllStates {
mainState: typeof mainState
}
}
You need to specify what is the entry point state and what should run first
that's done at setup, see this for details
const handler
= createTelegramHandler({
bot,
allStates,
defaultState: 'mainState'
}, dbParams)
Currently this npm relies on prisma (in future planned ability to chose over other orms)
and it assumes you have enabled your prismaSchemaFolder
in schema.prisma
and it lies in prisma/schema/
folder
generator client {
provider = "prisma-client-js"
previewFeatures = ["typedSql", "prismaSchemaFolder"]
}
Then you need to run
npx chat-toolkit setup
which would create needed models in your project folder
After that you'll have to apply migration migrate
yarn prisma migrate dev --name add_chat_toolkit_models
Example with Telegraf:
const bot = new Telegraf(process.env.TG_TOKEN)
const prisma = new PrismaClient()
const dbParams = {
findOrCreateUser: findOrCreateUserPrisma(prisma as any),
stateManager: defaultPrismaStateManagerImplementation(prisma as any),
// unfrotunatelly cast to any needed, since local prisma is not the same as chat-toolkits
// right now idk how to avoid this but it's works just fine
}
const allStates = {
mainState
}
const handler
= createTelegramHandler({
bot,
allStates,
defaultState: 'mainState'
}, dbParams)
bot.start(async ctx => {
await handler.handlePrivateMessage(ctx, true)
})
bot.on('message', async ctx => {
await handler.handlePrivateMessage(ctx as any, false)
})
say :: String -> Effect ()
^ Just sends text message to user
expect_ :: () -> Effect (String)
^ Expects text message from user
expectAny :: (Message -> a) -> Effect a
^ In case if if need to wait for specific user message or combined
for example
await expectAny(msg => {
if ('photo' in msg) {
return msg.photo[0]
}
if ('text' in msg) {
return msg.text
}
})
random :: () -> Effect (Number)
^ since states can do anything it's better not to use Math.random directly so it's just wrapper over it (needed for restoring state)
suggest
suggestIt
_disableRecording _onRestoreDoRun
switchState escape_
Suppose case when you need inline keyboard for example [like, dislike]
then each button should execute some kind of logic
in this case you can get use of createCallbackHandle
:
await bot.sendMessage('you liked that post?', {
reply_markup: {
inline_keyboard: [[
{
text: "Like",
callback_data: await recordingObject.like({post_id: post.id}),
},
{
text: "Dislike",
callback_data: await recordingObject.dislike({post_id: post.id}),
}
]]
}
})
where recordingObject
would be defined like this:
const recordingObject = createCallbackHandle({
namespace: 'post-likes',
handler: ctx => ({
async like({post_id}: { post_id: number }) {
const user = await User.find(ctx.from.id)
await Post.find(post_id).likeBy(user)
await ctx.editMessageText //...
},
dislike({post_id}: { post_id: number }) {
const user = await User.find(ctx.from.id)
await Post.find(post_id).likeBy(user)
await ctx.editMessageText //...
}
})
})
To use this you need to enable handler
const redis = new Redis() // from ioredis npm
const bot = new Telegraf(process.env.TG_TOKEN)
/// ...
export const {
setupCallbackHandler,
createCallbackHandle,
} = createRedisInlineKeyboardHandler({
redis,
projectName: 'mybot',
ivalidateIn: duration(1, 'day'),
})
// ...
setupCallbackHandler(bot)
Each call to recordingObject generates a UUID that is stored in callback_data
on the Telegram side.
When a button is pressed, the corresponding function is invoked.
On our end, the arguments for the handler function are stored
in Redis under the key ${projectName}:callbackquery:${uuid}
for 24 hours
(this is the default duration and covers 99% of use cases).
declare module 'chat-toolkit' {
interface GlobalSharedAppContext {
}
}
declare module 'chat-toolkit' {
interface EscapeData {
user: User
}
}
FAQs
 <img alt="NPM Downloads" src="https://img.shields.io/npm/dy/chat-toolkit?link=https%3A%2F%2Fwww.npmjs.com%2Fpackage%2Fchat-tool
We found that chat-toolkit demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Meet Socket at Black Hat & DEF CON 2025 for 1:1s, insider security talks at Allegiant Stadium, and a private dinner with top minds in software supply chain security.
Security News
CAI is a new open source AI framework that automates penetration testing tasks like scanning and exploitation up to 3,600× faster than humans.
Security News
Deno 2.4 brings back bundling, improves dependency updates and telemetry, and makes the runtime more practical for real-world JavaScript projects.