create-bunspace 0.3.0 → 0.3.1
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/dist/templates/monorepo/apps/example/package.json +1 -1
- package/dist/templates/monorepo/core/packages/utils/rolldown.config.ts +30 -0
- package/dist/templates/monorepo/tsconfig.json +3 -1
- package/dist/templates/telegram-bot/bun.lock +6 -20
- package/dist/templates/telegram-bot/core/package.json +11 -0
- package/dist/templates/telegram-bot/core/rolldown.config.ts +11 -0
- package/dist/templates/telegram-bot/core/src/config/logging.ts +1 -3
- package/dist/templates/telegram-bot/core/src/handlers/config-export.ts +10 -9
- package/dist/templates/telegram-bot/core/src/handlers/control.ts +30 -21
- package/dist/templates/telegram-bot/core/src/handlers/demo-full.ts +58 -0
- package/dist/templates/telegram-bot/core/src/handlers/demo-keyboard.ts +49 -0
- package/dist/templates/telegram-bot/core/src/handlers/demo-media.ts +163 -0
- package/dist/templates/telegram-bot/core/src/handlers/demo-text.ts +27 -0
- package/dist/templates/telegram-bot/core/src/handlers/health.ts +22 -14
- package/dist/templates/telegram-bot/core/src/handlers/info.ts +21 -23
- package/dist/templates/telegram-bot/core/src/handlers/logs.ts +8 -6
- package/dist/templates/telegram-bot/core/src/index.ts +20 -1
- package/dist/templates/telegram-bot/core/src/utils/formatters.ts +5 -60
- package/dist/templates/telegram-bot/core/tsconfig.json +2 -0
- package/dist/templates/telegram-bot/package.json +3 -2
- package/dist/templates/telegram-bot/packages/utils/package.json +12 -1
- package/dist/templates/telegram-bot/packages/utils/rolldown.config.ts +11 -0
- package/dist/templates/telegram-bot/packages/utils/tsconfig.json +10 -0
- package/dist/templates/telegram-bot/tsconfig.json +7 -2
- package/package.json +1 -1
- package/templates/monorepo/apps/example/package.json +1 -1
- package/templates/monorepo/core/packages/utils/rolldown.config.ts +30 -0
- package/templates/monorepo/tsconfig.json +3 -1
- package/templates/telegram-bot/bun.lock +6 -20
- package/templates/telegram-bot/core/package.json +11 -0
- package/templates/telegram-bot/core/rolldown.config.ts +11 -0
- package/templates/telegram-bot/core/src/config/logging.ts +1 -3
- package/templates/telegram-bot/core/src/handlers/config-export.ts +10 -9
- package/templates/telegram-bot/core/src/handlers/control.ts +30 -21
- package/templates/telegram-bot/core/src/handlers/demo-full.ts +58 -0
- package/templates/telegram-bot/core/src/handlers/demo-keyboard.ts +49 -0
- package/templates/telegram-bot/core/src/handlers/demo-media.ts +163 -0
- package/templates/telegram-bot/core/src/handlers/demo-text.ts +27 -0
- package/templates/telegram-bot/core/src/handlers/health.ts +22 -14
- package/templates/telegram-bot/core/src/handlers/info.ts +21 -23
- package/templates/telegram-bot/core/src/handlers/logs.ts +8 -6
- package/templates/telegram-bot/core/src/index.ts +20 -1
- package/templates/telegram-bot/core/src/utils/formatters.ts +5 -60
- package/templates/telegram-bot/core/tsconfig.json +2 -0
- package/templates/telegram-bot/package.json +3 -2
- package/templates/telegram-bot/packages/utils/package.json +12 -1
- package/templates/telegram-bot/packages/utils/rolldown.config.ts +11 -0
- package/templates/telegram-bot/packages/utils/tsconfig.json +10 -0
- package/templates/telegram-bot/tsconfig.json +7 -2
- package/templates/telegram-bot/core/src/utils/message-builder.ts +0 -180
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"dev": "bun --watch src/index.ts",
|
|
8
|
-
"build": "bun build src/index.ts --outdir ./dist",
|
|
8
|
+
"build": "bun build src/index.ts --outdir ./dist --sourcemap && tsgo --emitDeclarationOnly",
|
|
9
9
|
"typecheck": "tsgo --noEmit",
|
|
10
10
|
"start": "bun run dist/index.js"
|
|
11
11
|
},
|
|
@@ -11,6 +11,16 @@ export default defineConfig([
|
|
|
11
11
|
},
|
|
12
12
|
external: ['@mks2508/better-logger', '@mks2508/no-throw'],
|
|
13
13
|
},
|
|
14
|
+
{
|
|
15
|
+
input: './src/index.ts',
|
|
16
|
+
output: {
|
|
17
|
+
file: './dist/index.cjs',
|
|
18
|
+
format: 'cjs',
|
|
19
|
+
exports: 'named',
|
|
20
|
+
sourcemap: true,
|
|
21
|
+
},
|
|
22
|
+
external: ['@mks2508/better-logger', '@mks2508/no-throw'],
|
|
23
|
+
},
|
|
14
24
|
{
|
|
15
25
|
input: './src/logger.ts',
|
|
16
26
|
output: {
|
|
@@ -21,6 +31,16 @@ export default defineConfig([
|
|
|
21
31
|
},
|
|
22
32
|
external: ['@mks2508/better-logger'],
|
|
23
33
|
},
|
|
34
|
+
{
|
|
35
|
+
input: './src/logger.ts',
|
|
36
|
+
output: {
|
|
37
|
+
file: './dist/logger.cjs',
|
|
38
|
+
format: 'cjs',
|
|
39
|
+
exports: 'named',
|
|
40
|
+
sourcemap: true,
|
|
41
|
+
},
|
|
42
|
+
external: ['@mks2508/better-logger'],
|
|
43
|
+
},
|
|
24
44
|
{
|
|
25
45
|
input: './src/result.ts',
|
|
26
46
|
output: {
|
|
@@ -31,4 +51,14 @@ export default defineConfig([
|
|
|
31
51
|
},
|
|
32
52
|
external: ['@mks2508/no-throw'],
|
|
33
53
|
},
|
|
54
|
+
{
|
|
55
|
+
input: './src/result.ts',
|
|
56
|
+
output: {
|
|
57
|
+
file: './dist/result.cjs',
|
|
58
|
+
format: 'cjs',
|
|
59
|
+
exports: 'named',
|
|
60
|
+
sourcemap: true,
|
|
61
|
+
},
|
|
62
|
+
external: ['@mks2508/no-throw'],
|
|
63
|
+
},
|
|
34
64
|
]);
|
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
"declaration": true,
|
|
30
30
|
"declarationMap": true,
|
|
31
31
|
"sourceMap": true,
|
|
32
|
-
"removeComments": false
|
|
32
|
+
"removeComments": false,
|
|
33
|
+
"outDir": "./dist",
|
|
34
|
+
"declarationDir": "./dist"
|
|
33
35
|
},
|
|
34
36
|
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.spec.ts"]
|
|
35
37
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"lockfileVersion": 1,
|
|
3
|
+
"configVersion": 0,
|
|
3
4
|
"workspaces": {
|
|
4
5
|
"": {
|
|
5
6
|
"name": "mks-telegram-bot",
|
|
6
7
|
"dependencies": {
|
|
7
|
-
"@flla/telegram-format": "^3.1.2",
|
|
8
8
|
"@inquirer/prompts": "^8.1.0",
|
|
9
|
+
"@mks2508/telegram-bot-utils": "workspace:*",
|
|
10
|
+
"@mks2508/telegram-message-builder": "0.3.1",
|
|
9
11
|
"chalk": "^5.6.2",
|
|
10
12
|
"commander": "^14.0.2",
|
|
11
13
|
"dotenv": "^17.2.3",
|
|
@@ -27,25 +29,11 @@
|
|
|
27
29
|
"version": "0.1.0",
|
|
28
30
|
"dependencies": {
|
|
29
31
|
"@mks2508/telegram-bot-utils": "workspace:*",
|
|
32
|
+
"@mks2508/telegram-message-builder": "0.3.1",
|
|
30
33
|
"telegraf": "^4.16.3",
|
|
31
34
|
"zod": "^3.24.0",
|
|
32
35
|
},
|
|
33
36
|
},
|
|
34
|
-
"packages/bootstrapper": {
|
|
35
|
-
"name": "@mks2508/bootstrapper",
|
|
36
|
-
"version": "0.1.0",
|
|
37
|
-
"dependencies": {
|
|
38
|
-
"@inquirer/prompts": "^8.1.0",
|
|
39
|
-
"@mks2508/better-logger": "^4.0.0",
|
|
40
|
-
"big-integer": "^1.6.52",
|
|
41
|
-
"telegraf": "^4.16.3",
|
|
42
|
-
"telegram": "^2.26.22",
|
|
43
|
-
},
|
|
44
|
-
"devDependencies": {
|
|
45
|
-
"@types/node": "^20",
|
|
46
|
-
"typescript": "^5",
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
37
|
"packages/utils": {
|
|
50
38
|
"name": "@mks2508/telegram-bot-utils",
|
|
51
39
|
"version": "0.1.0",
|
|
@@ -58,8 +46,6 @@
|
|
|
58
46
|
"packages": {
|
|
59
47
|
"@cryptography/aes": ["@cryptography/aes@0.1.1", "", {}, "sha512-PcYz4FDGblO6tM2kSC+VzhhK62vml6k6/YAkiWtyPvrgJVfnDRoHGDtKn5UiaRRUrvUTTocBpvc2rRgTCqxjsg=="],
|
|
60
48
|
|
|
61
|
-
"@flla/telegram-format": ["@flla/telegram-format@3.1.2", "", {}, "sha512-pmBcT0f2ay77WlVq0EX3KseFp07IXU7QYahsY/Halx4/YnsM70qYeLRBoKysukU/l0ZQ2u15xu9rMECm9ov2+A=="],
|
|
62
|
-
|
|
63
49
|
"@inquirer/ansi": ["@inquirer/ansi@2.0.2", "", {}, "sha512-SYLX05PwJVnW+WVegZt1T4Ip1qba1ik+pNJPDiqvk6zS5Y/i8PhRzLpGEtVd7sW0G8cMtkD8t4AZYhQwm8vnww=="],
|
|
64
50
|
|
|
65
51
|
"@inquirer/checkbox": ["@inquirer/checkbox@5.0.3", "", { "dependencies": { "@inquirer/ansi": "^2.0.2", "@inquirer/core": "^11.1.0", "@inquirer/figures": "^2.0.2", "@inquirer/type": "^4.0.2" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-xtQP2eXMFlOcAhZ4ReKP2KZvDIBb1AnCfZ81wWXG3DXLVH0f0g4obE0XDPH+ukAEMRcZT0kdX2AS1jrWGXbpxw=="],
|
|
@@ -98,14 +84,14 @@
|
|
|
98
84
|
|
|
99
85
|
"@mks2508/better-logger": ["@mks2508/better-logger@4.0.0", "", { "dependencies": { "chalk": "^5.6.2" } }, "sha512-39PYkAKg7kC0ncPjcN5zAwTsLIS+iXoL4294gl3Cm4OAI6sAT7YJ+RccD42Ve5ybRC/TGgJnD0AUH5M26w0pWA=="],
|
|
100
86
|
|
|
101
|
-
"@mks2508/bootstrapper": ["@mks2508/bootstrapper@workspace:packages/bootstrapper"],
|
|
102
|
-
|
|
103
87
|
"@mks2508/no-throw": ["@mks2508/no-throw@0.1.0", "", {}, "sha512-/CI8FqiO3oLw66XIQ07mw13b6PDNh1vit0cGzUBLq5MfJUTKDU0yaKFE0l9CqSpe6xv4n4+z4RWEytP5xePKZQ=="],
|
|
104
88
|
|
|
105
89
|
"@mks2508/telegram-bot-core": ["@mks2508/telegram-bot-core@workspace:core"],
|
|
106
90
|
|
|
107
91
|
"@mks2508/telegram-bot-utils": ["@mks2508/telegram-bot-utils@workspace:packages/utils"],
|
|
108
92
|
|
|
93
|
+
"@mks2508/telegram-message-builder": ["@mks2508/telegram-message-builder@0.3.1", "", {}, "sha512-i/BdbxVq13l8XzCUq8jMkFfYjrTXiCdErpzo9tEazLLqqEucAm2aY9HE5i8U+15mEWeSV4D6I9gfU8a5dSn1Cw=="],
|
|
94
|
+
|
|
109
95
|
"@oxlint/darwin-arm64": ["@oxlint/darwin-arm64@1.38.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-9rN3047QTyA4i73FKikDUBdczRcLtOsIwZ5TsEx5Q7jr5nBjolhYQOFQf9QdhBLdInxw1iX4+lgdMCf1g74zjg=="],
|
|
110
96
|
|
|
111
97
|
"@oxlint/darwin-x64": ["@oxlint/darwin-x64@1.38.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-Y1UHW4KOlg5NvyrSn/bVBQP8/LRuid7Pnu+BWGbAVVsFcK0b565YgMSO3Eu9nU3w8ke91dr7NFpUmS+bVkdkbw=="],
|
|
@@ -3,13 +3,24 @@
|
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
|
+
"build": "rolldown --config rolldown.config.ts && tsgo --emitDeclarationOnly",
|
|
6
7
|
"dev": "bun run --watch src/index.ts",
|
|
7
8
|
"start": "bun run src/index.ts",
|
|
8
9
|
"typecheck": "tsgo --noEmit"
|
|
9
10
|
},
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
10
17
|
"dependencies": {
|
|
11
18
|
"@mks2508/telegram-bot-utils": "workspace:*",
|
|
19
|
+
"@mks2508/telegram-message-builder": "0.3.1",
|
|
12
20
|
"telegraf": "^4.16.3",
|
|
13
21
|
"zod": "^3.24.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"rolldown": "^1.0.0-beta.58"
|
|
14
25
|
}
|
|
15
26
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { defineConfig } from 'rolldown';
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
input: './src/index.ts',
|
|
5
|
+
output: {
|
|
6
|
+
file: './dist/index.js',
|
|
7
|
+
format: 'esm',
|
|
8
|
+
sourcemap: true,
|
|
9
|
+
},
|
|
10
|
+
external: ['grammy', 'telegraf', '@mks2508/telegram-bot-utils', '@mks2508/telegram-message-builder', 'zod'],
|
|
11
|
+
});
|
|
@@ -54,9 +54,7 @@ let fileHandlersInitialized = false
|
|
|
54
54
|
* fileLogLevels: ['error', 'critical']
|
|
55
55
|
* })
|
|
56
56
|
*/
|
|
57
|
-
export function initializeFileLogging(
|
|
58
|
-
config: Partial<FileLoggingConfig> = {}
|
|
59
|
-
): void {
|
|
57
|
+
export function initializeFileLogging(config: Partial<FileLoggingConfig> = {}): void {
|
|
60
58
|
// Setup logger with debug/logLevel options
|
|
61
59
|
const appConfig = getConfig()
|
|
62
60
|
setupLogger({ debug: appConfig.debug, logLevel: appConfig.logLevel })
|
|
@@ -2,7 +2,7 @@ import type { Context } from 'telegraf'
|
|
|
2
2
|
import { badge, kv, colors, colorText } from '../middleware/logging.js'
|
|
3
3
|
import { getConfig } from '../config/index.js'
|
|
4
4
|
import { configLogger } from '@mks2508/telegram-bot-utils'
|
|
5
|
-
import {
|
|
5
|
+
import { TelegramMessageBuilder } from '@mks2508/telegram-message-builder'
|
|
6
6
|
|
|
7
7
|
const collectedTopics = new Map<number, string>()
|
|
8
8
|
|
|
@@ -19,14 +19,14 @@ export async function handleExportConfig(ctx: Context): Promise<void> {
|
|
|
19
19
|
)
|
|
20
20
|
|
|
21
21
|
const config = getConfig()
|
|
22
|
-
const builder =
|
|
22
|
+
const builder = TelegramMessageBuilder.text()
|
|
23
23
|
|
|
24
24
|
// Title
|
|
25
25
|
builder.title('🔧 Current Configuration')
|
|
26
26
|
builder.newline()
|
|
27
27
|
|
|
28
28
|
// Environment
|
|
29
|
-
builder.section('Environment
|
|
29
|
+
builder.section('Environment')
|
|
30
30
|
builder.line('TG_ENV', config.environment, { code: true })
|
|
31
31
|
builder.line('TG_INSTANCE_NAME', config.instanceName, { code: true })
|
|
32
32
|
builder.line('TG_MODE', config.mode, { code: true })
|
|
@@ -35,13 +35,13 @@ export async function handleExportConfig(ctx: Context): Promise<void> {
|
|
|
35
35
|
// Bot Token (masked)
|
|
36
36
|
if (config.botToken) {
|
|
37
37
|
const masked = config.botToken.slice(0, 6) + '...' + config.botToken.slice(-6)
|
|
38
|
-
builder.section('Bot
|
|
38
|
+
builder.section('Bot')
|
|
39
39
|
builder.line('TG_BOT_TOKEN', masked, { code: true })
|
|
40
40
|
builder.newline()
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
// Control
|
|
44
|
-
builder.section('Control Commands
|
|
44
|
+
builder.section('Control Commands')
|
|
45
45
|
if (config.controlChatId) {
|
|
46
46
|
builder.line('TG_CONTROL_CHAT_ID', String(config.controlChatId), { code: true })
|
|
47
47
|
} else {
|
|
@@ -61,7 +61,7 @@ export async function handleExportConfig(ctx: Context): Promise<void> {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
// Logging
|
|
64
|
-
builder.section('Logging
|
|
64
|
+
builder.section('Logging')
|
|
65
65
|
if (config.logChatId) {
|
|
66
66
|
builder.line('TG_LOG_CHAT_ID', String(config.logChatId), { code: true })
|
|
67
67
|
} else {
|
|
@@ -77,7 +77,7 @@ export async function handleExportConfig(ctx: Context): Promise<void> {
|
|
|
77
77
|
|
|
78
78
|
// Webhook
|
|
79
79
|
if (config.mode === 'webhook') {
|
|
80
|
-
builder.section('Webhook
|
|
80
|
+
builder.section('Webhook')
|
|
81
81
|
builder.line('TG_WEBHOOK_URL', config.webhookUrl || 'not_set', { code: true })
|
|
82
82
|
builder.line('TG_WEBHOOK_SECRET', config.webhookSecret || 'not_set', { code: true })
|
|
83
83
|
builder.newline()
|
|
@@ -89,13 +89,14 @@ export async function handleExportConfig(ctx: Context): Promise<void> {
|
|
|
89
89
|
builder.newline()
|
|
90
90
|
|
|
91
91
|
// Instructions
|
|
92
|
-
builder.section('📋 Quick Setup
|
|
92
|
+
builder.section('📋 Quick Setup')
|
|
93
93
|
builder.listItem('Create topics: General, Control, Logs')
|
|
94
94
|
builder.listItem('Mention @bot_username in each topic')
|
|
95
95
|
builder.listItem('Use /getinfo to get Thread IDs')
|
|
96
96
|
builder.listItem('Update .env with the IDs')
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
const message = builder.build()
|
|
99
|
+
await ctx.reply(message.text || '', { parse_mode: (message.parse_mode || 'HTML') as any })
|
|
99
100
|
configLogger.success(`Config exported for user ${userId}`)
|
|
100
101
|
}
|
|
101
102
|
|
|
@@ -2,7 +2,7 @@ import type { Context } from 'telegraf'
|
|
|
2
2
|
import { updateConfig, getConfig } from '../config/index.js'
|
|
3
3
|
import { botLogger, controlLogger, badge, kv, colors, colorText } from '../middleware/logging.js'
|
|
4
4
|
import { botManager } from '../utils/bot-manager.js'
|
|
5
|
-
import {
|
|
5
|
+
import { TelegramMessageBuilder } from '@mks2508/telegram-message-builder'
|
|
6
6
|
|
|
7
7
|
export async function handleStop(ctx: Context): Promise<void> {
|
|
8
8
|
const userId = ctx.from?.id ?? 'unknown'
|
|
@@ -14,8 +14,10 @@ export async function handleStop(ctx: Context): Promise<void> {
|
|
|
14
14
|
})}`
|
|
15
15
|
)
|
|
16
16
|
|
|
17
|
-
const message =
|
|
18
|
-
|
|
17
|
+
const message = TelegramMessageBuilder.text()
|
|
18
|
+
.text('🛑 Shutting down bot...')
|
|
19
|
+
.build()
|
|
20
|
+
ctx.reply(message.text || '', { parse_mode: (message.parse_mode || 'HTML') as any })
|
|
19
21
|
process.exit(0)
|
|
20
22
|
}
|
|
21
23
|
|
|
@@ -29,15 +31,17 @@ export async function handleRestart(ctx: Context): Promise<void> {
|
|
|
29
31
|
})}`
|
|
30
32
|
)
|
|
31
33
|
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
const message1 = TelegramMessageBuilder.text()
|
|
35
|
+
.text('🔄 Restarting bot...')
|
|
36
|
+
.build()
|
|
37
|
+
ctx.reply(message1.text || '', { parse_mode: (message1.parse_mode || 'HTML') as any })
|
|
35
38
|
|
|
36
39
|
botManager.resetStats()
|
|
37
40
|
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
const message2 = TelegramMessageBuilder.text()
|
|
42
|
+
.text('✅ Bot stats reset. Restarting...')
|
|
43
|
+
.build()
|
|
44
|
+
ctx.reply(message2.text || '', { parse_mode: (message2.parse_mode || 'HTML') as any })
|
|
41
45
|
process.exit(0)
|
|
42
46
|
}
|
|
43
47
|
|
|
@@ -48,34 +52,37 @@ export async function handleMode(ctx: Context): Promise<void> {
|
|
|
48
52
|
|
|
49
53
|
if (!mode || (mode !== 'polling' && mode !== 'webhook')) {
|
|
50
54
|
const config = getConfig()
|
|
51
|
-
const
|
|
52
|
-
.title('📡 Current Mode
|
|
55
|
+
const message = TelegramMessageBuilder.text()
|
|
56
|
+
.title('📡 Current Mode')
|
|
53
57
|
.newline()
|
|
54
58
|
.line('Mode', config.mode, { code: true })
|
|
55
59
|
.newline()
|
|
56
60
|
.text('Usage: /mode <polling|webhook>')
|
|
61
|
+
.build()
|
|
57
62
|
|
|
58
|
-
ctx.reply(
|
|
63
|
+
ctx.reply(message.text || '', { parse_mode: (message.parse_mode || 'HTML') as any })
|
|
59
64
|
return
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
if (mode === 'webhook') {
|
|
63
68
|
const config = getConfig()
|
|
64
69
|
if (!config.webhookUrl) {
|
|
65
|
-
const
|
|
70
|
+
const message = TelegramMessageBuilder.text()
|
|
66
71
|
.text('❌ Webhook URL not configured. Set TG_WEBHOOK_URL environment variable.')
|
|
67
|
-
|
|
72
|
+
.build()
|
|
73
|
+
ctx.reply(message.text || '', { parse_mode: (message.parse_mode || 'HTML') as any })
|
|
68
74
|
return
|
|
69
75
|
}
|
|
70
76
|
}
|
|
71
77
|
|
|
72
78
|
updateConfig({ mode })
|
|
73
79
|
|
|
74
|
-
const
|
|
80
|
+
const message = TelegramMessageBuilder.text()
|
|
75
81
|
.text('✅ Mode changed to:')
|
|
76
82
|
.line('Mode', mode, { code: true })
|
|
83
|
+
.build()
|
|
77
84
|
|
|
78
|
-
ctx.reply(
|
|
85
|
+
ctx.reply(message.text || '', { parse_mode: (message.parse_mode || 'HTML') as any })
|
|
79
86
|
|
|
80
87
|
controlLogger.info(
|
|
81
88
|
`${badge('MODE', 'rounded')} ${kv({
|
|
@@ -89,18 +96,20 @@ export async function handleWebhook(ctx: Context): Promise<void> {
|
|
|
89
96
|
const config = getConfig()
|
|
90
97
|
|
|
91
98
|
if (config.mode !== 'webhook') {
|
|
92
|
-
const
|
|
99
|
+
const message = TelegramMessageBuilder.text()
|
|
93
100
|
.text('❌ Bot is not in webhook mode. Use /mode webhook first.')
|
|
94
|
-
|
|
101
|
+
.build()
|
|
102
|
+
ctx.reply(message.text || '', { parse_mode: (message.parse_mode || 'HTML') as any })
|
|
95
103
|
return
|
|
96
104
|
}
|
|
97
105
|
|
|
98
|
-
const
|
|
99
|
-
.title('🔗 Webhook Configuration
|
|
106
|
+
const message = TelegramMessageBuilder.text()
|
|
107
|
+
.title('🔗 Webhook Configuration')
|
|
100
108
|
.newline()
|
|
101
109
|
.line('URL', config.webhookUrl || 'Not set', { code: true })
|
|
110
|
+
.build()
|
|
102
111
|
|
|
103
|
-
ctx.reply(
|
|
112
|
+
ctx.reply(message.text || '', { parse_mode: (message.parse_mode || 'HTML') as any })
|
|
104
113
|
|
|
105
114
|
controlLogger.info(
|
|
106
115
|
`${badge('WEBHOOK', 'rounded')} ${kv({
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { TelegramMessageBuilder, TelegramKeyboardBuilder } from '@mks2508/telegram-message-builder'
|
|
2
|
+
import type { Context } from 'telegraf'
|
|
3
|
+
import { handleMediaDemo } from './demo-media.js'
|
|
4
|
+
import { handleKeyboardDemo } from './demo-keyboard.js'
|
|
5
|
+
|
|
6
|
+
export async function handleFullDemo(ctx: Context): Promise<void> {
|
|
7
|
+
const message = TelegramMessageBuilder.text()
|
|
8
|
+
.title('🚀 telegram-message-builder v0.3.0')
|
|
9
|
+
.newline()
|
|
10
|
+
.section('Features')
|
|
11
|
+
.listItem('✨ Fluent API for text formatting')
|
|
12
|
+
.listItem('⌨️ Inline and reply keyboards')
|
|
13
|
+
.listItem('📸 5 media types support')
|
|
14
|
+
.listItem('🎨 HTML, Markdown, MarkdownV2')
|
|
15
|
+
.listItem('🔒 Type-safe with TypeScript')
|
|
16
|
+
.listItem('📦 Zero runtime dependencies')
|
|
17
|
+
.newline()
|
|
18
|
+
.section('Installation')
|
|
19
|
+
.codeBlock('bun add @mks2508/telegram-message-builder', 'bash')
|
|
20
|
+
.newline()
|
|
21
|
+
.section('Quick Start')
|
|
22
|
+
.codeBlock(`import { TelegramMessageBuilder } from '@mks2508/telegram-message-builder'
|
|
23
|
+
|
|
24
|
+
const message = TelegramMessageBuilder.text()
|
|
25
|
+
.title('Hello World')
|
|
26
|
+
.line('Status', 'Active', { bold: true })
|
|
27
|
+
.build()
|
|
28
|
+
|
|
29
|
+
ctx.reply(message.text, { parse_mode: message.parse_mode })`, 'typescript')
|
|
30
|
+
.build()
|
|
31
|
+
|
|
32
|
+
const keyboard = TelegramKeyboardBuilder.inline()
|
|
33
|
+
.urlButton('📦 npm Package', 'https://www.npmjs.com/package/@mks2508/telegram-message-builder')
|
|
34
|
+
.urlButton('📖 GitHub', 'https://github.com/MKS2508/telegram-message-builder')
|
|
35
|
+
.row()
|
|
36
|
+
.callbackButton('📸 Media Demo', 'full_demo_media')
|
|
37
|
+
.callbackButton('⌨️ Keyboard Demo', 'full_demo_keyboard')
|
|
38
|
+
.buildMarkup()
|
|
39
|
+
|
|
40
|
+
await ctx.reply(message.text || '', {
|
|
41
|
+
parse_mode: (message.parse_mode || 'HTML') as any,
|
|
42
|
+
reply_markup: keyboard as any,
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function handleFullDemoCallback(ctx: Context): Promise<void> {
|
|
47
|
+
const callbackData = (ctx.callbackQuery as any)?.data
|
|
48
|
+
await ctx.answerCbQuery()
|
|
49
|
+
|
|
50
|
+
switch (callbackData) {
|
|
51
|
+
case 'full_demo_media':
|
|
52
|
+
await handleMediaDemo(ctx)
|
|
53
|
+
break
|
|
54
|
+
case 'full_demo_keyboard':
|
|
55
|
+
await handleKeyboardDemo(ctx)
|
|
56
|
+
break
|
|
57
|
+
}
|
|
58
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { TelegramMessageBuilder, TelegramKeyboardBuilder } from '@mks2508/telegram-message-builder'
|
|
2
|
+
import type { Context } from 'telegraf'
|
|
3
|
+
|
|
4
|
+
export async function handleKeyboardDemo(ctx: Context): Promise<void> {
|
|
5
|
+
const message = TelegramMessageBuilder.text()
|
|
6
|
+
.title('⌨️ Keyboard Demo')
|
|
7
|
+
.newline()
|
|
8
|
+
.text('Try the buttons below:')
|
|
9
|
+
.build()
|
|
10
|
+
|
|
11
|
+
const keyboard = TelegramKeyboardBuilder.inline()
|
|
12
|
+
.urlButton('🌐 Visit Website', 'https://github.com/MKS2508/telegram-message-builder')
|
|
13
|
+
.callbackButton('✅ Yes', 'demo_yes')
|
|
14
|
+
.callbackButton('❌ No', 'demo_no')
|
|
15
|
+
.row()
|
|
16
|
+
.callbackButton('🔄 Refresh', 'demo_refresh')
|
|
17
|
+
.callbackButton('🔍 Search', 'demo_search')
|
|
18
|
+
.row()
|
|
19
|
+
.switchInlineQueryButton('🔍 Inline Query', 'query')
|
|
20
|
+
.buildMarkup()
|
|
21
|
+
|
|
22
|
+
await ctx.reply(message.text || '', {
|
|
23
|
+
parse_mode: (message.parse_mode || 'HTML') as any,
|
|
24
|
+
reply_markup: keyboard as any,
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function handleKeyboardCallback(ctx: Context): Promise<void> {
|
|
29
|
+
const callbackData = (ctx.callbackQuery as any)?.data
|
|
30
|
+
let response = 'Unknown action'
|
|
31
|
+
|
|
32
|
+
switch (callbackData) {
|
|
33
|
+
case 'demo_yes':
|
|
34
|
+
response = '✅ You clicked YES!'
|
|
35
|
+
break
|
|
36
|
+
case 'demo_no':
|
|
37
|
+
response = '❌ You clicked NO!'
|
|
38
|
+
break
|
|
39
|
+
case 'demo_refresh':
|
|
40
|
+
response = '🔄 Content refreshed!'
|
|
41
|
+
break
|
|
42
|
+
case 'demo_search':
|
|
43
|
+
response = '🔍 Searching...'
|
|
44
|
+
break
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
await ctx.answerCbQuery(response)
|
|
48
|
+
await ctx.reply(response)
|
|
49
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { TelegramMessageBuilder, TelegramMediaBuilder, TelegramKeyboardBuilder } from '@mks2508/telegram-message-builder'
|
|
2
|
+
import type { Context } from 'telegraf'
|
|
3
|
+
|
|
4
|
+
export async function handleMediaDemo(ctx: Context): Promise<void> {
|
|
5
|
+
const message = TelegramMessageBuilder.text()
|
|
6
|
+
.title('📸 Media Builder Demo')
|
|
7
|
+
.newline()
|
|
8
|
+
.text('Choose a media type to test:')
|
|
9
|
+
.listItem('Photo with caption')
|
|
10
|
+
.listItem('Video with options')
|
|
11
|
+
.listItem('Document with metadata')
|
|
12
|
+
.listItem('Audio with performer info')
|
|
13
|
+
.listItem('Voice message')
|
|
14
|
+
.build()
|
|
15
|
+
|
|
16
|
+
const keyboard = TelegramKeyboardBuilder.inline()
|
|
17
|
+
.callbackButton('📷 Photo', 'media_photo')
|
|
18
|
+
.callbackButton('🎥 Video', 'media_video')
|
|
19
|
+
.row()
|
|
20
|
+
.callbackButton('📄 Document', 'media_document')
|
|
21
|
+
.callbackButton('🎵 Audio', 'media_audio')
|
|
22
|
+
.row()
|
|
23
|
+
.callbackButton('🎤 Voice', 'media_voice')
|
|
24
|
+
.buildMarkup()
|
|
25
|
+
|
|
26
|
+
await ctx.reply(message.text || '', {
|
|
27
|
+
parse_mode: (message.parse_mode || 'HTML') as any,
|
|
28
|
+
reply_markup: keyboard as any,
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export async function handleMediaCallback(ctx: Context): Promise<void> {
|
|
33
|
+
const callbackData = (ctx.callbackQuery as any)?.data
|
|
34
|
+
await ctx.answerCbQuery()
|
|
35
|
+
|
|
36
|
+
switch (callbackData) {
|
|
37
|
+
case 'media_photo':
|
|
38
|
+
await sendPhotoDemo(ctx)
|
|
39
|
+
break
|
|
40
|
+
case 'media_video':
|
|
41
|
+
await sendVideoDemo(ctx)
|
|
42
|
+
break
|
|
43
|
+
case 'media_document':
|
|
44
|
+
await sendDocumentDemo(ctx)
|
|
45
|
+
break
|
|
46
|
+
case 'media_audio':
|
|
47
|
+
await sendAudioDemo(ctx)
|
|
48
|
+
break
|
|
49
|
+
case 'media_voice':
|
|
50
|
+
await sendVoiceDemo(ctx)
|
|
51
|
+
break
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function sendPhotoDemo(ctx: Context): Promise<void> {
|
|
56
|
+
const photo = TelegramMediaBuilder.photo('https://picsum.photos/800/600')
|
|
57
|
+
.caption('📷 Photo Demo\n\nThis is a photo with caption formatting support!')
|
|
58
|
+
.setParseMode('html')
|
|
59
|
+
.build()
|
|
60
|
+
|
|
61
|
+
const media = typeof photo.media === 'string' ? photo.media : undefined
|
|
62
|
+
|
|
63
|
+
if (!media) {
|
|
64
|
+
await ctx.reply('❌ Media source must be a URL or file_id')
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
await ctx.replyWithPhoto(media, {
|
|
69
|
+
caption: photo.caption || undefined,
|
|
70
|
+
parse_mode: photo.parse_mode as any,
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function sendVideoDemo(ctx: Context): Promise<void> {
|
|
75
|
+
const video = TelegramMediaBuilder.video('https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_1mb.mp4')
|
|
76
|
+
.caption('🎥 Video Demo\n\nDuration: 10s\nResolution: 1280x720')
|
|
77
|
+
.duration(10)
|
|
78
|
+
.width(1280)
|
|
79
|
+
.height(720)
|
|
80
|
+
.enableStreaming()
|
|
81
|
+
.setParseMode('html')
|
|
82
|
+
.build()
|
|
83
|
+
|
|
84
|
+
const media = typeof video.media === 'string' ? video.media : undefined
|
|
85
|
+
|
|
86
|
+
if (!media) {
|
|
87
|
+
await ctx.reply('❌ Media source must be a URL or file_id')
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
await ctx.replyWithVideo(media, {
|
|
92
|
+
caption: video.caption || undefined,
|
|
93
|
+
parse_mode: video.parse_mode as any,
|
|
94
|
+
width: video.width as number,
|
|
95
|
+
height: video.height as number,
|
|
96
|
+
duration: video.duration as number,
|
|
97
|
+
supports_streaming: true,
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function sendDocumentDemo(ctx: Context): Promise<void> {
|
|
102
|
+
const doc = TelegramMediaBuilder.document('https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf')
|
|
103
|
+
.caption('📄 Document Demo\n\nThis is a PDF document with custom filename.')
|
|
104
|
+
.fileName('sample-document.pdf')
|
|
105
|
+
.mimeType('application/pdf')
|
|
106
|
+
.build()
|
|
107
|
+
|
|
108
|
+
const media = typeof doc.media === 'string' ? doc.media : undefined
|
|
109
|
+
|
|
110
|
+
if (!media) {
|
|
111
|
+
await ctx.reply('❌ Media source must be a URL or file_id')
|
|
112
|
+
return
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
await ctx.replyWithDocument(media, {
|
|
116
|
+
caption: doc.caption || undefined,
|
|
117
|
+
parse_mode: doc.parse_mode as any,
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function sendAudioDemo(ctx: Context): Promise<void> {
|
|
122
|
+
const audio = TelegramMediaBuilder.audio('https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3')
|
|
123
|
+
.caption('🎵 Audio Demo\n\nArtist: Demo Artist\nTitle: Demo Song')
|
|
124
|
+
.performer('Demo Artist')
|
|
125
|
+
.title('Demo Song')
|
|
126
|
+
.duration(180)
|
|
127
|
+
.build()
|
|
128
|
+
|
|
129
|
+
const media = typeof audio.media === 'string' ? audio.media : undefined
|
|
130
|
+
|
|
131
|
+
if (!media) {
|
|
132
|
+
await ctx.reply('❌ Media source must be a URL or file_id')
|
|
133
|
+
return
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
await ctx.replyWithAudio(media, {
|
|
137
|
+
caption: audio.caption || undefined,
|
|
138
|
+
parse_mode: audio.parse_mode as any,
|
|
139
|
+
performer: audio.performer as string,
|
|
140
|
+
title: audio.title as string,
|
|
141
|
+
duration: audio.duration as number,
|
|
142
|
+
})
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async function sendVoiceDemo(ctx: Context): Promise<void> {
|
|
146
|
+
const voice = TelegramMediaBuilder.voice('https://sample-videos.com/audio/mp3/crowd-cheering.mp3')
|
|
147
|
+
.caption('🎤 Voice Demo\n\nThis is a voice message.')
|
|
148
|
+
.duration(5)
|
|
149
|
+
.build()
|
|
150
|
+
|
|
151
|
+
const media = typeof voice.media === 'string' ? voice.media : undefined
|
|
152
|
+
|
|
153
|
+
if (!media) {
|
|
154
|
+
await ctx.reply('❌ Media source must be a URL or file_id')
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
await ctx.replyWithVoice(media, {
|
|
159
|
+
caption: voice.caption || undefined,
|
|
160
|
+
parse_mode: voice.parse_mode as any,
|
|
161
|
+
duration: voice.duration as number,
|
|
162
|
+
})
|
|
163
|
+
}
|