telemeister 0.1.21 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +55 -13
- package/bin/telemeister-cli.js +1220 -0
- package/bin/telemeister.js +2 -1
- package/dist/bot/index.d.ts +10 -0
- package/dist/bot/index.d.ts.map +1 -0
- package/dist/bot/index.js +9 -0
- package/dist/bot/index.js.map +1 -0
- package/dist/bot/polling.d.ts +20 -0
- package/dist/bot/polling.d.ts.map +1 -0
- package/dist/bot/polling.js +129 -0
- package/dist/bot/polling.js.map +1 -0
- package/dist/bot/session.d.ts +54 -0
- package/dist/bot/session.d.ts.map +1 -0
- package/dist/bot/session.js +89 -0
- package/dist/bot/session.js.map +1 -0
- package/dist/bot/webhook.d.ts +36 -0
- package/dist/bot/webhook.d.ts.map +1 -0
- package/dist/bot/webhook.js +213 -0
- package/dist/bot/webhook.js.map +1 -0
- package/dist/bot-state-types.d.ts.map +1 -0
- package/dist/bot-state-types.js +3 -0
- package/dist/bot-state-types.js.map +1 -0
- package/dist/cli/create-bot.d.ts.map +1 -1
- package/dist/cli/create-bot.js +32 -10
- package/dist/cli/create-bot.js.map +1 -1
- package/dist/cli/state-manager.d.ts.map +1 -1
- package/dist/cli/state-manager.js +14 -1
- package/dist/cli/state-manager.js.map +1 -1
- package/dist/core/app-states.d.ts +8 -0
- package/dist/core/app-states.d.ts.map +1 -0
- package/dist/core/app-states.js +8 -0
- package/dist/core/app-states.js.map +1 -0
- package/dist/core/bot/polling.d.ts.map +1 -1
- package/dist/core/bot/polling.js +4 -7
- package/dist/core/bot/polling.js.map +1 -1
- package/dist/core/bot/webhook.d.ts.map +1 -1
- package/dist/core/bot/webhook.js +28 -9
- package/dist/core/bot/webhook.js.map +1 -1
- package/dist/core/builder.d.ts +1 -1
- package/dist/core/builder.d.ts.map +1 -1
- package/dist/core/builder.js +2 -2
- package/dist/core/builder.js.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/types.d.ts +3 -2
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/database.d.ts +43 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +127 -0
- package/dist/database.js.map +1 -0
- package/dist/generated/prisma/browser.d.ts +15 -0
- package/dist/generated/prisma/browser.d.ts.map +1 -0
- package/dist/generated/prisma/browser.js +18 -0
- package/dist/generated/prisma/browser.js.map +1 -0
- package/dist/generated/prisma/client.d.ts +32 -0
- package/dist/generated/prisma/client.d.ts.map +1 -0
- package/dist/generated/prisma/client.js +33 -0
- package/dist/generated/prisma/client.js.map +1 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +166 -0
- package/dist/generated/prisma/commonInputTypes.d.ts.map +1 -0
- package/dist/generated/prisma/commonInputTypes.js +11 -0
- package/dist/generated/prisma/commonInputTypes.js.map +1 -0
- package/dist/generated/prisma/enums.d.ts +2 -0
- package/dist/generated/prisma/enums.d.ts.map +1 -0
- package/dist/generated/prisma/enums.js +11 -0
- package/dist/generated/prisma/enums.js.map +1 -0
- package/dist/generated/prisma/internal/class.d.ts +138 -0
- package/dist/generated/prisma/internal/class.d.ts.map +1 -0
- package/dist/generated/prisma/internal/class.js +50 -0
- package/dist/generated/prisma/internal/class.js.map +1 -0
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +591 -0
- package/dist/generated/prisma/internal/prismaNamespace.d.ts.map +1 -0
- package/dist/generated/prisma/internal/prismaNamespace.js +96 -0
- package/dist/generated/prisma/internal/prismaNamespace.js.map +1 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +56 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts.map +1 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +67 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js.map +1 -0
- package/dist/generated/prisma/models/User.d.ts +1169 -0
- package/dist/generated/prisma/models/User.d.ts.map +1 -0
- package/dist/generated/prisma/models/User.js +2 -0
- package/dist/generated/prisma/models/User.js.map +1 -0
- package/dist/generated/prisma/models/UserInfo.d.ts +1101 -0
- package/dist/generated/prisma/models/UserInfo.d.ts.map +1 -0
- package/dist/generated/prisma/models/UserInfo.js +2 -0
- package/dist/generated/prisma/models/UserInfo.js.map +1 -0
- package/dist/generated/prisma/models.d.ts +4 -0
- package/dist/generated/prisma/models.d.ts.map +1 -0
- package/dist/generated/prisma/models.js +2 -0
- package/dist/generated/prisma/models.js.map +1 -0
- package/dist/handlers/idle/index.d.ts +2 -0
- package/dist/handlers/idle/index.d.ts.map +1 -0
- package/dist/handlers/idle/index.js +22 -0
- package/dist/handlers/idle/index.js.map +1 -0
- package/dist/handlers/index.d.ts +12 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +14 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/handlers/menu/index.d.ts +2 -0
- package/dist/handlers/menu/index.d.ts.map +1 -0
- package/dist/handlers/menu/index.js +35 -0
- package/dist/handlers/menu/index.js.map +1 -0
- package/dist/handlers/menu.d.ts +2 -0
- package/dist/handlers/menu.d.ts.map +1 -0
- package/dist/handlers/menu.js +37 -0
- package/dist/handlers/menu.js.map +1 -0
- package/dist/handlers/welcome/index.d.ts +2 -0
- package/dist/handlers/welcome/index.d.ts.map +1 -0
- package/dist/handlers/welcome/index.js +22 -0
- package/dist/handlers/welcome/index.js.map +1 -0
- package/dist/handlers/welcome.d.ts +2 -0
- package/dist/handlers/welcome.d.ts.map +1 -0
- package/dist/handlers/welcome.js +30 -0
- package/dist/handlers/welcome.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/templates/README.md.ejs +6 -5
- package/dist/templates/handler.ts.ejs +71 -8
- package/dist/templates/package.json.ejs +7 -0
- package/dist/templates/templates/README.md.ejs +12 -11
- package/dist/templates/templates/handler.ts.ejs +70 -8
- package/dist/templates/templates/package.json.ejs +7 -0
- package/package.json +17 -38
- package/src/templates/README.md.ejs +12 -11
- package/src/templates/handler.ts.ejs +70 -8
- package/src/templates/package.json.ejs +7 -0
package/bin/telemeister.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Telemeister CLI Entry Point
|
|
5
|
+
* Uses bundled CLI with all dependencies included
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
8
|
import { fileURLToPath } from 'url';
|
|
@@ -10,7 +11,7 @@ import { dirname, join } from 'path';
|
|
|
10
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
12
|
const __dirname = dirname(__filename);
|
|
12
13
|
|
|
13
|
-
const cliPath = join(__dirname, '
|
|
14
|
+
const cliPath = join(__dirname, 'telemeister-cli.js');
|
|
14
15
|
|
|
15
16
|
import(cliPath).catch((err) => {
|
|
16
17
|
console.error('Failed to load CLI:', err.message);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bot module exports
|
|
3
|
+
*
|
|
4
|
+
* Provides polling and webhook modes for running the bot.
|
|
5
|
+
*/
|
|
6
|
+
export { startPollingMode, createBot } from './polling.js';
|
|
7
|
+
export { startWebhookMode } from './webhook.js';
|
|
8
|
+
export { PrismaSessionAdapter, getOrCreateSession } from './session.js';
|
|
9
|
+
export type { SessionData } from './session.js';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bot/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACxE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bot module exports
|
|
3
|
+
*
|
|
4
|
+
* Provides polling and webhook modes for running the bot.
|
|
5
|
+
*/
|
|
6
|
+
export { startPollingMode, createBot } from './polling.js';
|
|
7
|
+
export { startWebhookMode } from './webhook.js';
|
|
8
|
+
export { PrismaSessionAdapter, getOrCreateSession } from './session.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/bot/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grammy-based Polling Mode Implementation
|
|
3
|
+
*
|
|
4
|
+
* Uses Grammy Bot API library with database-backed sessions.
|
|
5
|
+
*/
|
|
6
|
+
import { Bot, type Context } from 'grammy';
|
|
7
|
+
import { type SessionData } from './session.js';
|
|
8
|
+
interface BotContext extends Context {
|
|
9
|
+
session: SessionData;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Create and configure the Grammy bot
|
|
13
|
+
*/
|
|
14
|
+
export declare function createBot(botToken: string): Bot<BotContext>;
|
|
15
|
+
/**
|
|
16
|
+
* Start the bot in polling mode
|
|
17
|
+
*/
|
|
18
|
+
export declare function startPollingMode(botToken: string): Promise<void>;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=polling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polling.d.ts","sourceRoot":"","sources":["../../src/bot/polling.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,GAAG,EAAW,KAAK,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEpD,OAAO,EAA4C,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAI1F,UAAU,UAAW,SAAQ,OAAO;IAClC,OAAO,EAAE,WAAW,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC,CA2E3D;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAWtE"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grammy-based Polling Mode Implementation
|
|
3
|
+
*
|
|
4
|
+
* Uses Grammy Bot API library with database-backed sessions.
|
|
5
|
+
*/
|
|
6
|
+
import { Bot, session } from 'grammy';
|
|
7
|
+
import { appBuilder } from '../core/index.js';
|
|
8
|
+
import { PrismaSessionAdapter, getOrCreateSession } from './session.js';
|
|
9
|
+
/**
|
|
10
|
+
* Create and configure the Grammy bot
|
|
11
|
+
*/
|
|
12
|
+
export function createBot(botToken) {
|
|
13
|
+
const bot = new Bot(botToken);
|
|
14
|
+
// Install session middleware with Prisma adapter
|
|
15
|
+
bot.use(session({
|
|
16
|
+
initial: () => ({
|
|
17
|
+
currentState: 'idle',
|
|
18
|
+
stateData: {},
|
|
19
|
+
}),
|
|
20
|
+
storage: new PrismaSessionAdapter(),
|
|
21
|
+
getSessionKey: (ctx) => ctx.from?.id.toString(),
|
|
22
|
+
}));
|
|
23
|
+
// Ensure user exists in database on each update
|
|
24
|
+
bot.use(async (ctx, next) => {
|
|
25
|
+
if (!ctx.from || !ctx.chat) {
|
|
26
|
+
return next();
|
|
27
|
+
}
|
|
28
|
+
const telegramId = ctx.from.id.toString();
|
|
29
|
+
const chatId = ctx.chat.id.toString();
|
|
30
|
+
// Get or create user session
|
|
31
|
+
const { session: userSession, isNew } = await getOrCreateSession(telegramId, chatId);
|
|
32
|
+
ctx.session = userSession;
|
|
33
|
+
// Call onEnter for initial state if this is a new session
|
|
34
|
+
if (isNew) {
|
|
35
|
+
const handlerContext = createHandlerContext(ctx, userSession);
|
|
36
|
+
const nextState = await appBuilder.executeOnEnter(userSession.currentState, handlerContext);
|
|
37
|
+
// Handle transition from onEnter
|
|
38
|
+
if (nextState && nextState !== userSession.currentState) {
|
|
39
|
+
await transitionToState(ctx, userSession, nextState, handlerContext);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
// Save any state data changes
|
|
43
|
+
userSession.stateData =
|
|
44
|
+
handlerContext.getData('__all') || userSession.stateData;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return next();
|
|
48
|
+
});
|
|
49
|
+
// Handle text messages
|
|
50
|
+
bot.on('message:text', async (ctx) => {
|
|
51
|
+
const text = ctx.message.text;
|
|
52
|
+
const session = ctx.session;
|
|
53
|
+
// Create handler context compatible with existing handlers
|
|
54
|
+
const handlerContext = createHandlerContext(ctx, session);
|
|
55
|
+
// Execute onResponse handler for current state
|
|
56
|
+
const nextState = await appBuilder.executeOnResponse(session.currentState, handlerContext, text);
|
|
57
|
+
// Handle state transition (call onEnter even for same state)
|
|
58
|
+
if (nextState) {
|
|
59
|
+
await transitionToState(ctx, session, nextState, handlerContext);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
// Save any state data changes
|
|
63
|
+
session.stateData =
|
|
64
|
+
handlerContext.getData('__all') || session.stateData;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
return bot;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Start the bot in polling mode
|
|
71
|
+
*/
|
|
72
|
+
export async function startPollingMode(botToken) {
|
|
73
|
+
const bot = createBot(botToken);
|
|
74
|
+
console.log('🤖 Bot started in polling mode');
|
|
75
|
+
// Start polling
|
|
76
|
+
await bot.start({
|
|
77
|
+
onStart: () => {
|
|
78
|
+
console.log('✅ Bot is running and polling for updates...');
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Create a handler context compatible with existing handlers
|
|
84
|
+
*/
|
|
85
|
+
function createHandlerContext(ctx, session) {
|
|
86
|
+
// Local state data copy for modifications
|
|
87
|
+
const localStateData = { ...session.stateData };
|
|
88
|
+
return {
|
|
89
|
+
userId: session.userId || 0,
|
|
90
|
+
telegramId: ctx.from?.id || 0,
|
|
91
|
+
chatId: ctx.chat?.id || 0,
|
|
92
|
+
currentState: session.currentState,
|
|
93
|
+
send: async (text) => {
|
|
94
|
+
await ctx.reply(text, { parse_mode: 'Markdown' });
|
|
95
|
+
},
|
|
96
|
+
setData: (key, value) => {
|
|
97
|
+
localStateData[key] = value;
|
|
98
|
+
},
|
|
99
|
+
getData: (key) => {
|
|
100
|
+
if (key === '__all') {
|
|
101
|
+
return localStateData;
|
|
102
|
+
}
|
|
103
|
+
return localStateData[key];
|
|
104
|
+
},
|
|
105
|
+
transition: async (toState) => {
|
|
106
|
+
await transitionToState(ctx, session, toState, createHandlerContext(ctx, session));
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Transition to a new state and execute onEnter handler
|
|
112
|
+
*/
|
|
113
|
+
async function transitionToState(ctx, session, toState, handlerContext) {
|
|
114
|
+
// Update session state
|
|
115
|
+
session.currentState = toState;
|
|
116
|
+
// Execute onEnter handler for new state
|
|
117
|
+
const enterNextState = await appBuilder.executeOnEnter(toState, handlerContext);
|
|
118
|
+
// Save state data changes
|
|
119
|
+
session.stateData = handlerContext.getData('__all') || session.stateData;
|
|
120
|
+
// Handle chained transition from onEnter
|
|
121
|
+
if (enterNextState && enterNextState !== toState) {
|
|
122
|
+
// Create fresh context for the next state
|
|
123
|
+
const nextContext = createHandlerContext(ctx, session);
|
|
124
|
+
const nextState = enterNextState;
|
|
125
|
+
nextContext.currentState = nextState;
|
|
126
|
+
await transitionToState(ctx, session, nextState, nextContext);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=polling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polling.js","sourceRoot":"","sources":["../../src/bot/polling.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grammy Session Adapter for Prisma Database
|
|
3
|
+
*
|
|
4
|
+
* This adapter integrates Grammy's session system with the Prisma database,
|
|
5
|
+
* allowing user state to persist across restarts.
|
|
6
|
+
*/
|
|
7
|
+
import type { StorageAdapter } from 'grammy';
|
|
8
|
+
/**
|
|
9
|
+
* Session data stored per user
|
|
10
|
+
*/
|
|
11
|
+
export interface SessionData {
|
|
12
|
+
/** Current FSM state */
|
|
13
|
+
currentState: string;
|
|
14
|
+
/** User-specific data storage */
|
|
15
|
+
stateData: Record<string, unknown>;
|
|
16
|
+
/** Internal user ID from database */
|
|
17
|
+
userId?: number;
|
|
18
|
+
/** Telegram chat ID */
|
|
19
|
+
chatId?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Prisma-backed session storage adapter for Grammy
|
|
23
|
+
*
|
|
24
|
+
* This adapter loads/saves session data from/to the database,
|
|
25
|
+
* keyed by Telegram user ID.
|
|
26
|
+
*/
|
|
27
|
+
export declare class PrismaSessionAdapter implements StorageAdapter<SessionData> {
|
|
28
|
+
/**
|
|
29
|
+
* Read session data from database
|
|
30
|
+
* @param key - Telegram user ID (as string)
|
|
31
|
+
*/
|
|
32
|
+
read(key: string): Promise<SessionData | undefined>;
|
|
33
|
+
/**
|
|
34
|
+
* Write session data to database
|
|
35
|
+
* @param key - Telegram user ID (as string)
|
|
36
|
+
* @param value - Session data to save
|
|
37
|
+
*/
|
|
38
|
+
write(key: string, value: SessionData): Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Delete session data (not typically used in bots)
|
|
41
|
+
* @param key - Telegram user ID (as string)
|
|
42
|
+
*/
|
|
43
|
+
delete(key: string): Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
export interface SessionResult {
|
|
46
|
+
session: SessionData;
|
|
47
|
+
isNew: boolean;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get or create user session
|
|
51
|
+
* This helper ensures a user exists in the database before processing
|
|
52
|
+
*/
|
|
53
|
+
export declare function getOrCreateSession(telegramId: string, chatId: string): Promise<SessionResult>;
|
|
54
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/bot/session.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAG7C;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,wBAAwB;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,qBAAa,oBAAqB,YAAW,cAAc,CAAC,WAAW,CAAC;IACtE;;;OAGG;IACG,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAgBzD;;;;OAIG;IACG,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3D;;;OAGG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAOzC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,aAAa,CAAC,CAoCxB"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grammy Session Adapter for Prisma Database
|
|
3
|
+
*
|
|
4
|
+
* This adapter integrates Grammy's session system with the Prisma database,
|
|
5
|
+
* allowing user state to persist across restarts.
|
|
6
|
+
*/
|
|
7
|
+
import { getUserByTelegramId, createOrUpdateUser, updateUserState } from '../database.js';
|
|
8
|
+
/**
|
|
9
|
+
* Prisma-backed session storage adapter for Grammy
|
|
10
|
+
*
|
|
11
|
+
* This adapter loads/saves session data from/to the database,
|
|
12
|
+
* keyed by Telegram user ID.
|
|
13
|
+
*/
|
|
14
|
+
export class PrismaSessionAdapter {
|
|
15
|
+
/**
|
|
16
|
+
* Read session data from database
|
|
17
|
+
* @param key - Telegram user ID (as string)
|
|
18
|
+
*/
|
|
19
|
+
async read(key) {
|
|
20
|
+
const user = await getUserByTelegramId(key);
|
|
21
|
+
if (!user)
|
|
22
|
+
return undefined;
|
|
23
|
+
const stateData = user.info?.stateData
|
|
24
|
+
? JSON.parse(user.info.stateData)
|
|
25
|
+
: {};
|
|
26
|
+
return {
|
|
27
|
+
currentState: user.currentState,
|
|
28
|
+
stateData,
|
|
29
|
+
userId: user.id,
|
|
30
|
+
chatId: user.chatId,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Write session data to database
|
|
35
|
+
* @param key - Telegram user ID (as string)
|
|
36
|
+
* @param value - Session data to save
|
|
37
|
+
*/
|
|
38
|
+
async write(key, value) {
|
|
39
|
+
await updateUserState(key, value.currentState, value.stateData);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Delete session data (not typically used in bots)
|
|
43
|
+
* @param key - Telegram user ID (as string)
|
|
44
|
+
*/
|
|
45
|
+
async delete(key) {
|
|
46
|
+
// Sessions are not deleted - user records persist
|
|
47
|
+
// This could be implemented if needed for GDPR compliance
|
|
48
|
+
// Reset to idle state instead of deleting
|
|
49
|
+
await updateUserState(key, 'idle', {});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get or create user session
|
|
54
|
+
* This helper ensures a user exists in the database before processing
|
|
55
|
+
*/
|
|
56
|
+
export async function getOrCreateSession(telegramId, chatId) {
|
|
57
|
+
const existing = await getUserByTelegramId(telegramId);
|
|
58
|
+
if (existing) {
|
|
59
|
+
const stateData = existing.info?.stateData
|
|
60
|
+
? JSON.parse(existing.info.stateData)
|
|
61
|
+
: {};
|
|
62
|
+
return {
|
|
63
|
+
session: {
|
|
64
|
+
currentState: existing.currentState,
|
|
65
|
+
stateData,
|
|
66
|
+
userId: existing.id,
|
|
67
|
+
chatId: existing.chatId,
|
|
68
|
+
},
|
|
69
|
+
isNew: false,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// Create new user
|
|
73
|
+
const newUser = await createOrUpdateUser({
|
|
74
|
+
telegramId,
|
|
75
|
+
chatId,
|
|
76
|
+
currentState: 'idle',
|
|
77
|
+
stateData: {},
|
|
78
|
+
});
|
|
79
|
+
return {
|
|
80
|
+
session: {
|
|
81
|
+
currentState: 'idle',
|
|
82
|
+
stateData: {},
|
|
83
|
+
userId: newUser.id,
|
|
84
|
+
chatId: newUser.chatId,
|
|
85
|
+
},
|
|
86
|
+
isNew: true,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/bot/session.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAgB1F;;;;;GAKG;AACH,MAAM,OAAO,oBAAoB;IAC/B;;;OAGG;IACH,KAAK,CAAC,IAAI,CAAC,GAAW;QACpB,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,GAAG,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI;YAAE,OAAO,SAAS,CAAC;QAE5B,MAAM,SAAS,GAA4B,IAAI,CAAC,IAAI,EAAE,SAAS;YAC7D,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAmB,CAAC;YAC3C,CAAC,CAAC,EAAE,CAAC;QAEP,OAAO;YACL,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,SAAS;YACT,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAAK,CAAC,GAAW,EAAE,KAAkB;QACzC,MAAM,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAClE,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,kDAAkD;QAClD,0DAA0D;QAE1D,0CAA0C;QAC1C,MAAM,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC;IACzC,CAAC;CACF;AAOD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,UAAkB,EAClB,MAAc;IAEd,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAEvD,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,SAAS,GAA4B,QAAQ,CAAC,IAAI,EAAE,SAAS;YACjE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAmB,CAAC;YAC/C,CAAC,CAAC,EAAE,CAAC;QAEP,OAAO;YACL,OAAO,EAAE;gBACP,YAAY,EAAE,QAAQ,CAAC,YAAY;gBACnC,SAAS;gBACT,MAAM,EAAE,QAAQ,CAAC,EAAE;gBACnB,MAAM,EAAE,QAAQ,CAAC,MAAM;aACxB;YACD,KAAK,EAAE,KAAK;SACb,CAAC;IACJ,CAAC;IAED,kBAAkB;IAClB,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC;QACvC,UAAU;QACV,MAAM;QACN,YAAY,EAAE,MAAM;QACpB,SAAS,EAAE,EAAE;KACd,CAAC,CAAC;IAEH,OAAO;QACL,OAAO,EAAE;YACP,YAAY,EAAE,MAAM;YACpB,SAAS,EAAE,EAAE;YACb,MAAM,EAAE,OAAO,CAAC,EAAE;YAClB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB;QACD,KAAK,EAAE,IAAI;KACZ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grammy-based Webhook Mode Implementation
|
|
3
|
+
*
|
|
4
|
+
* Uses Grammy Bot API library with Express for webhook handling.
|
|
5
|
+
*/
|
|
6
|
+
import { Bot, type Context } from 'grammy';
|
|
7
|
+
import { type SessionData } from './session.js';
|
|
8
|
+
interface BotContext extends Context {
|
|
9
|
+
session: SessionData;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Create and configure the Grammy bot (shared with polling)
|
|
13
|
+
*/
|
|
14
|
+
export declare function createBot(botToken: string): Bot<BotContext>;
|
|
15
|
+
/**
|
|
16
|
+
* Start the bot in webhook mode
|
|
17
|
+
*
|
|
18
|
+
* @param botToken - Telegram bot token
|
|
19
|
+
* @param webhookUrl - Public URL where Telegram will send updates
|
|
20
|
+
* @param port - Port to listen on
|
|
21
|
+
*/
|
|
22
|
+
export declare function startWebhookMode(botToken: string, webhookUrl: string, port: number): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Set webhook URL manually (for scripts)
|
|
25
|
+
*/
|
|
26
|
+
export declare function setWebhook(botToken: string, webhookUrl: string): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Delete webhook (stop receiving updates)
|
|
29
|
+
*/
|
|
30
|
+
export declare function deleteWebhook(botToken: string): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Get webhook info
|
|
33
|
+
*/
|
|
34
|
+
export declare function getWebhookInfo(botToken: string): Promise<unknown>;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=webhook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/bot/webhook.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,GAAG,EAA4B,KAAK,OAAO,EAAE,MAAM,QAAQ,CAAC;AAGrE,OAAO,EAA4C,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAI1F,UAAU,UAAW,SAAQ,OAAO;IAClC,OAAO,EAAE,WAAW,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC,CAsF3D;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAoCf;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAepF;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUnE;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUvE"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grammy-based Webhook Mode Implementation
|
|
3
|
+
*
|
|
4
|
+
* Uses Grammy Bot API library with Express for webhook handling.
|
|
5
|
+
*/
|
|
6
|
+
import express from 'express';
|
|
7
|
+
import { Bot, session, webhookCallback } from 'grammy';
|
|
8
|
+
import { appBuilder } from '../core/index.js';
|
|
9
|
+
import { PrismaSessionAdapter, getOrCreateSession } from './session.js';
|
|
10
|
+
/**
|
|
11
|
+
* Create and configure the Grammy bot (shared with polling)
|
|
12
|
+
*/
|
|
13
|
+
export function createBot(botToken) {
|
|
14
|
+
const bot = new Bot(botToken);
|
|
15
|
+
// Install session middleware with Prisma adapter
|
|
16
|
+
bot.use(session({
|
|
17
|
+
initial: () => ({
|
|
18
|
+
currentState: 'idle',
|
|
19
|
+
stateData: {},
|
|
20
|
+
}),
|
|
21
|
+
storage: new PrismaSessionAdapter(),
|
|
22
|
+
getSessionKey: (ctx) => ctx.from?.id.toString(),
|
|
23
|
+
}));
|
|
24
|
+
// Ensure user exists in database on each update
|
|
25
|
+
bot.use(async (ctx, next) => {
|
|
26
|
+
if (!ctx.from || !ctx.chat) {
|
|
27
|
+
return next();
|
|
28
|
+
}
|
|
29
|
+
const telegramId = ctx.from.id.toString();
|
|
30
|
+
const chatId = ctx.chat.id.toString();
|
|
31
|
+
// Get or create user session
|
|
32
|
+
const { session: userSession, isNew } = await getOrCreateSession(telegramId, chatId);
|
|
33
|
+
ctx.session = userSession;
|
|
34
|
+
// Call onEnter for initial state if this is a new session
|
|
35
|
+
if (isNew) {
|
|
36
|
+
const handlerContext = createHandlerContext(ctx, userSession);
|
|
37
|
+
const nextState = await appBuilder.executeOnEnter(userSession.currentState, handlerContext);
|
|
38
|
+
// Handle transition from onEnter
|
|
39
|
+
if (nextState && nextState !== userSession.currentState) {
|
|
40
|
+
await transitionToState(ctx, userSession, nextState, handlerContext);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
// Save any state data changes
|
|
44
|
+
userSession.stateData =
|
|
45
|
+
handlerContext.getData('__all') || userSession.stateData;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return next();
|
|
49
|
+
});
|
|
50
|
+
// Handle text messages
|
|
51
|
+
bot.on('message:text', async (ctx) => {
|
|
52
|
+
const text = ctx.message.text;
|
|
53
|
+
const session = ctx.session;
|
|
54
|
+
// Create handler context compatible with existing handlers
|
|
55
|
+
const handlerContext = createHandlerContext(ctx, session);
|
|
56
|
+
// Execute onResponse handler for current state
|
|
57
|
+
const nextState = await appBuilder.executeOnResponse(session.currentState, handlerContext, text);
|
|
58
|
+
// Handle state transition (call onEnter even for same state)
|
|
59
|
+
if (nextState) {
|
|
60
|
+
await transitionToState(ctx, session, nextState, handlerContext);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// Save any state data changes
|
|
64
|
+
session.stateData =
|
|
65
|
+
handlerContext.getData('__all') || session.stateData;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
// Handle /start command
|
|
69
|
+
bot.command('start', async (ctx) => {
|
|
70
|
+
const session = ctx.session;
|
|
71
|
+
// Create handler context
|
|
72
|
+
const handlerContext = createHandlerContext(ctx, session);
|
|
73
|
+
// Transition to welcome state
|
|
74
|
+
await transitionToState(ctx, session, 'welcome', handlerContext);
|
|
75
|
+
});
|
|
76
|
+
return bot;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Start the bot in webhook mode
|
|
80
|
+
*
|
|
81
|
+
* @param botToken - Telegram bot token
|
|
82
|
+
* @param webhookUrl - Public URL where Telegram will send updates
|
|
83
|
+
* @param port - Port to listen on
|
|
84
|
+
*/
|
|
85
|
+
export async function startWebhookMode(botToken, webhookUrl, port) {
|
|
86
|
+
const bot = createBot(botToken);
|
|
87
|
+
// Create Express app
|
|
88
|
+
const app = express();
|
|
89
|
+
// Health check endpoint
|
|
90
|
+
app.get('/health', (_req, res) => {
|
|
91
|
+
res.json({
|
|
92
|
+
status: 'ok',
|
|
93
|
+
mode: 'webhook',
|
|
94
|
+
timestamp: new Date().toISOString(),
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
// Set up webhook endpoint using Grammy's webhookCallback
|
|
98
|
+
// This handles the Telegram update parsing automatically
|
|
99
|
+
app.use('/webhook', webhookCallback(bot, 'express'));
|
|
100
|
+
// Start server
|
|
101
|
+
app.listen(port, async () => {
|
|
102
|
+
console.log(`🤖 Bot started in webhook mode`);
|
|
103
|
+
console.log(`📡 Webhook URL: ${webhookUrl}`);
|
|
104
|
+
console.log(`🖥️ Server listening on port ${port}`);
|
|
105
|
+
// Set webhook with Telegram
|
|
106
|
+
try {
|
|
107
|
+
await bot.api.setWebhook(webhookUrl, {
|
|
108
|
+
allowed_updates: ['message'],
|
|
109
|
+
});
|
|
110
|
+
console.log('✅ Webhook set successfully with Telegram');
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.error('❌ Failed to set webhook:', error);
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Set webhook URL manually (for scripts)
|
|
120
|
+
*/
|
|
121
|
+
export async function setWebhook(botToken, webhookUrl) {
|
|
122
|
+
const bot = new Bot(botToken);
|
|
123
|
+
try {
|
|
124
|
+
await bot.api.setWebhook(webhookUrl, {
|
|
125
|
+
allowed_updates: ['message'],
|
|
126
|
+
});
|
|
127
|
+
console.log('✅ Webhook set successfully');
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
console.error('❌ Failed to set webhook:', error);
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
// Don't start the bot, just set the webhook
|
|
135
|
+
await bot.api.deleteWebhook({ drop_pending_updates: true });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Delete webhook (stop receiving updates)
|
|
140
|
+
*/
|
|
141
|
+
export async function deleteWebhook(botToken) {
|
|
142
|
+
const bot = new Bot(botToken);
|
|
143
|
+
try {
|
|
144
|
+
await bot.api.deleteWebhook({ drop_pending_updates: true });
|
|
145
|
+
console.log('✅ Webhook deleted successfully');
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
console.error('❌ Failed to delete webhook:', error);
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Get webhook info
|
|
154
|
+
*/
|
|
155
|
+
export async function getWebhookInfo(botToken) {
|
|
156
|
+
const bot = new Bot(botToken);
|
|
157
|
+
try {
|
|
158
|
+
const info = await bot.api.getWebhookInfo();
|
|
159
|
+
return info;
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
console.error('Error getting webhook info:', error);
|
|
163
|
+
throw error;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Create a handler context compatible with existing handlers
|
|
168
|
+
*/
|
|
169
|
+
function createHandlerContext(ctx, session) {
|
|
170
|
+
// Local state data copy for modifications
|
|
171
|
+
const localStateData = { ...session.stateData };
|
|
172
|
+
return {
|
|
173
|
+
userId: session.userId || 0,
|
|
174
|
+
telegramId: ctx.from?.id || 0,
|
|
175
|
+
chatId: ctx.chat?.id || 0,
|
|
176
|
+
currentState: session.currentState,
|
|
177
|
+
send: async (text) => {
|
|
178
|
+
await ctx.reply(text, { parse_mode: 'Markdown' });
|
|
179
|
+
},
|
|
180
|
+
setData: (key, value) => {
|
|
181
|
+
localStateData[key] = value;
|
|
182
|
+
},
|
|
183
|
+
getData: (key) => {
|
|
184
|
+
if (key === '__all') {
|
|
185
|
+
return localStateData;
|
|
186
|
+
}
|
|
187
|
+
return localStateData[key];
|
|
188
|
+
},
|
|
189
|
+
transition: async (toState) => {
|
|
190
|
+
await transitionToState(ctx, session, toState, createHandlerContext(ctx, session));
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Transition to a new state and execute onEnter handler
|
|
196
|
+
*/
|
|
197
|
+
async function transitionToState(ctx, session, toState, handlerContext) {
|
|
198
|
+
// Update session state
|
|
199
|
+
session.currentState = toState;
|
|
200
|
+
// Execute onEnter handler for new state
|
|
201
|
+
const enterNextState = await appBuilder.executeOnEnter(toState, handlerContext);
|
|
202
|
+
// Save state data changes
|
|
203
|
+
session.stateData = handlerContext.getData('__all') || session.stateData;
|
|
204
|
+
// Handle chained transition from onEnter
|
|
205
|
+
if (enterNextState && enterNextState !== toState) {
|
|
206
|
+
// Create fresh context for the next state
|
|
207
|
+
const nextContext = createHandlerContext(ctx, session);
|
|
208
|
+
const nextState = enterNextState;
|
|
209
|
+
nextContext.currentState = nextState;
|
|
210
|
+
await transitionToState(ctx, session, nextState, nextContext);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=webhook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/bot/webhook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot-state-types.d.ts","sourceRoot":"","sources":["../src/bot-state-types.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAEpD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,SAAS,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAChC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;AAChE,MAAM,MAAM,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC;AAChE,MAAM,MAAM,kBAAkB,GAAG,OAAO,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bot-state-types.js","sourceRoot":"","sources":["../src/bot-state-types.ts"],"names":[],"mappings":"AAAA,6CAA6C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-bot.d.ts","sourceRoot":"","sources":["../../src/cli/create-bot.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"create-bot.d.ts","sourceRoot":"","sources":["../../src/cli/create-bot.ts"],"names":[],"mappings":"AAAA;;GAEG;AA4CH,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CA6G1E"}
|