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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Context } from 'telegraf'
|
|
2
2
|
import { infoLogger, badge, kv, colors, colorText } from '../middleware/logging.js'
|
|
3
|
-
import {
|
|
3
|
+
import { TelegramMessageBuilder } from '@mks2508/telegram-message-builder'
|
|
4
4
|
|
|
5
5
|
export async function handleGetInfo(ctx: Context): Promise<void> {
|
|
6
6
|
const userId = ctx.from?.id ?? 'unknown'
|
|
@@ -17,16 +17,14 @@ export async function handleGetInfo(ctx: Context): Promise<void> {
|
|
|
17
17
|
const from = ctx.from
|
|
18
18
|
const chat = ctx.chat
|
|
19
19
|
|
|
20
|
-
const builder =
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
builder.title('📋 Your Information')
|
|
24
|
-
builder.newline()
|
|
20
|
+
const builder = TelegramMessageBuilder.text()
|
|
21
|
+
.title('📋 Your Information')
|
|
22
|
+
.newline()
|
|
25
23
|
|
|
26
24
|
// User info
|
|
27
25
|
if (from) {
|
|
28
26
|
builder.section('👤 User Info:')
|
|
29
|
-
|
|
27
|
+
.line('User ID', String(from.id), { code: true })
|
|
30
28
|
if (from.username) builder.line('Username', `@${from.username}`)
|
|
31
29
|
if (from.first_name) builder.line('First Name', from.first_name)
|
|
32
30
|
if (from.last_name) builder.line('Last Name', from.last_name)
|
|
@@ -38,8 +36,8 @@ export async function handleGetInfo(ctx: Context): Promise<void> {
|
|
|
38
36
|
// Chat info
|
|
39
37
|
if (chat) {
|
|
40
38
|
builder.section('💬 Chat Info:')
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
.line('Chat ID', String(chat.id), { code: true })
|
|
40
|
+
.line('Type', chat.type)
|
|
43
41
|
if ('title' in chat && chat.title) builder.line('Title', chat.title)
|
|
44
42
|
if ('username' in chat && chat.username) builder.line('Username', `@${chat.username}`)
|
|
45
43
|
if (chat.type === 'supergroup' || chat.type === 'group') {
|
|
@@ -53,7 +51,7 @@ export async function handleGetInfo(ctx: Context): Promise<void> {
|
|
|
53
51
|
const botMention = detectBotMention(msg as unknown as MaybeMessage, botUsername)
|
|
54
52
|
if (botMention.isMentioned) {
|
|
55
53
|
builder.section('🤖 Bot Mention:')
|
|
56
|
-
|
|
54
|
+
.line('Bot mentioned', 'Yes')
|
|
57
55
|
if (botMention.type) builder.line('Mention type', botMention.type)
|
|
58
56
|
if (botMention.replyToBot) builder.text('Replying to bot message')
|
|
59
57
|
builder.newline()
|
|
@@ -64,7 +62,7 @@ export async function handleGetInfo(ctx: Context): Promise<void> {
|
|
|
64
62
|
// Message/Topic info
|
|
65
63
|
if (msg) {
|
|
66
64
|
builder.section('📮 Message Info:')
|
|
67
|
-
|
|
65
|
+
.line('Message ID', String(msg.message_id))
|
|
68
66
|
if ('reply_to_message' in msg && msg.reply_to_message) {
|
|
69
67
|
const replyTo = msg.reply_to_message
|
|
70
68
|
builder.line('Reply to message ID', String(replyTo.message_id))
|
|
@@ -75,31 +73,31 @@ export async function handleGetInfo(ctx: Context): Promise<void> {
|
|
|
75
73
|
const threadId = getThreadId(msg as unknown as MaybeMessage)
|
|
76
74
|
if (threadId) {
|
|
77
75
|
builder.newline()
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
76
|
+
.section('🧵 Thread/Topic:')
|
|
77
|
+
.line('Thread ID', String(threadId), { code: true })
|
|
78
|
+
.text('This message is in a topic')
|
|
79
|
+
.newline()
|
|
82
80
|
infoLogger.info(`Message sent in thread ${threadId} by user ${userId}`)
|
|
83
81
|
}
|
|
84
82
|
|
|
85
83
|
// Configuration tips
|
|
86
84
|
builder.newline()
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
85
|
+
.section('🔧 Configuration:')
|
|
86
|
+
.line('TG_CONTROL_CHAT_ID', String(chat?.id ?? 'N/A'), { code: true })
|
|
87
|
+
.line('TG_AUTHORIZED_USER_IDS', String(from?.id ?? 'N/A'))
|
|
90
88
|
if (threadId) {
|
|
91
89
|
builder.line('TG_CONTROL_TOPIC_ID', String(threadId), { code: true })
|
|
92
90
|
}
|
|
93
91
|
|
|
94
92
|
builder.newline()
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
.text('💡 Copy these values to your .env file')
|
|
94
|
+
.newline()
|
|
95
|
+
.newline()
|
|
96
|
+
.text('💡 Tip: In groups, you can also mention the bot with @username to get this info')
|
|
99
97
|
|
|
100
98
|
const message = builder.build()
|
|
101
99
|
infoLogger.info(`Replying to user ${userId} with info`)
|
|
102
|
-
await ctx.reply(message, { parse_mode:
|
|
100
|
+
await ctx.reply(message.text || '', { parse_mode: (message.parse_mode || 'HTML') as any })
|
|
103
101
|
infoLogger.success(`Info sent to user ${userId}`)
|
|
104
102
|
}
|
|
105
103
|
|
|
@@ -2,7 +2,7 @@ import type { Context, Telegraf } from 'telegraf'
|
|
|
2
2
|
import { getConfig, hasLoggingConfigured } from '../config/index.js'
|
|
3
3
|
import { streamLogger, botLogger, badge, kv, colors, colorText } from '../middleware/logging.js'
|
|
4
4
|
import { formatLogEntry } from '../utils/formatters.js'
|
|
5
|
-
import {
|
|
5
|
+
import { TelegramMessageBuilder } from '@mks2508/telegram-message-builder'
|
|
6
6
|
|
|
7
7
|
const LOG_BUFFER_SIZE = 10
|
|
8
8
|
const LOG_BUFFER_TIMEOUT = 5000
|
|
@@ -103,9 +103,10 @@ export async function handleLogsCommand(ctx: Context): Promise<void> {
|
|
|
103
103
|
const config = getConfig()
|
|
104
104
|
|
|
105
105
|
if (!hasLoggingConfigured()) {
|
|
106
|
-
const
|
|
106
|
+
const message = TelegramMessageBuilder.text()
|
|
107
107
|
.text('❌ Logging is not configured. Set TG_LOG_CHAT_ID environment variable.')
|
|
108
|
-
|
|
108
|
+
.build()
|
|
109
|
+
ctx.reply(message.text || '', { parse_mode: (message.parse_mode || 'HTML') as any })
|
|
109
110
|
return
|
|
110
111
|
}
|
|
111
112
|
|
|
@@ -120,8 +121,8 @@ export async function handleLogsCommand(ctx: Context): Promise<void> {
|
|
|
120
121
|
})}`
|
|
121
122
|
)
|
|
122
123
|
|
|
123
|
-
const builder =
|
|
124
|
-
.title('📝 Log Streaming Status
|
|
124
|
+
const builder = TelegramMessageBuilder.text()
|
|
125
|
+
.title('📝 Log Streaming Status')
|
|
125
126
|
.newline()
|
|
126
127
|
.line('Status', status, { code: true })
|
|
127
128
|
.line('Chat ID', String(config.logChatId), { code: true })
|
|
@@ -129,5 +130,6 @@ export async function handleLogsCommand(ctx: Context): Promise<void> {
|
|
|
129
130
|
builder.line('Topic ID', String(config.logTopicId), { code: true })
|
|
130
131
|
}
|
|
131
132
|
|
|
132
|
-
|
|
133
|
+
const message = builder.build()
|
|
134
|
+
ctx.reply(message.text || '', { parse_mode: (message.parse_mode || 'HTML') as any })
|
|
133
135
|
}
|
|
@@ -10,6 +10,10 @@ import { handleGetInfo } from './handlers/info.js'
|
|
|
10
10
|
import { handleStop, handleRestart, handleMode, handleWebhook } from './handlers/control.js'
|
|
11
11
|
import { handleLogsCommand, initializeLogStreamer } from './handlers/logs.js'
|
|
12
12
|
import { handleExportConfig } from './handlers/config-export.js'
|
|
13
|
+
import { handleTextDemo } from './handlers/demo-text.js'
|
|
14
|
+
import { handleKeyboardDemo, handleKeyboardCallback } from './handlers/demo-keyboard.js'
|
|
15
|
+
import { handleMediaDemo, handleMediaCallback } from './handlers/demo-media.js'
|
|
16
|
+
import { handleFullDemo, handleFullDemoCallback } from './handlers/demo-full.js'
|
|
13
17
|
import { auth } from './middleware/auth.js'
|
|
14
18
|
import { initializeFileLogging } from './config/logging.js'
|
|
15
19
|
|
|
@@ -75,7 +79,12 @@ async function main(): Promise<void> {
|
|
|
75
79
|
'/stats - Show statistics\n' +
|
|
76
80
|
'/logs - Check log streaming status\n' +
|
|
77
81
|
'/getinfo - Get your user/chat info for configuration\n' +
|
|
78
|
-
'/mode - Check or change bot mode'
|
|
82
|
+
'/mode - Check or change bot mode\n\n' +
|
|
83
|
+
'*🎨 Demo Commands (telegram-message-builder):*\n' +
|
|
84
|
+
'/textdemo - Text formatting showcase\n' +
|
|
85
|
+
'/keybdemo - Keyboard builder showcase\n' +
|
|
86
|
+
'/mediademo - Media types showcase\n' +
|
|
87
|
+
'/fulldemo - Complete feature demo',
|
|
79
88
|
{ parse_mode: 'Markdown' }
|
|
80
89
|
)
|
|
81
90
|
botManager.incrementMessages()
|
|
@@ -137,6 +146,16 @@ async function main(): Promise<void> {
|
|
|
137
146
|
|
|
138
147
|
bot.command('logs', handleLogsCommand)
|
|
139
148
|
|
|
149
|
+
// Demo commands for telegram-message-builder showcase
|
|
150
|
+
bot.command('textdemo', handleTextDemo)
|
|
151
|
+
bot.command('keybdemo', handleKeyboardDemo)
|
|
152
|
+
bot.command('mediademo', handleMediaDemo)
|
|
153
|
+
bot.command('fulldemo', handleFullDemo)
|
|
154
|
+
|
|
155
|
+
// Callback handlers for demo keyboards
|
|
156
|
+
bot.action(/^(demo_yes|demo_no|demo_refresh|demo_search|full_demo_keyboard)$/, handleKeyboardCallback)
|
|
157
|
+
bot.action(/^(media_photo|media_video|media_document|media_audio|media_voice|full_demo_media)$/, handleMediaCallback)
|
|
158
|
+
|
|
140
159
|
process.once('SIGINT', async () => {
|
|
141
160
|
botLogger.info(`${badge('SHUTDOWN', 'pill')} ${colorText('SIGINT received', colors.warning)}`)
|
|
142
161
|
await instanceManager.releaseLock()
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { TimeConstants } from '../types/constants.js'
|
|
2
2
|
import type { BotStatus } from '../types/bot.js'
|
|
3
|
-
import {
|
|
3
|
+
import { TelegramMessageBuilder, fmt } from '@mks2508/telegram-message-builder'
|
|
4
4
|
|
|
5
|
-
// Re-export
|
|
6
|
-
export {
|
|
7
|
-
export type { FormatType }
|
|
8
|
-
|
|
9
|
-
// Default format mode for the bot (HTML is simpler and more reliable than MarkdownV2)
|
|
10
|
-
export const DEFAULT_FORMAT_MODE: FormatType = 'html'
|
|
5
|
+
// Re-export fmt from telegram-message-builder for convenience
|
|
6
|
+
export { fmt }
|
|
11
7
|
|
|
12
8
|
/**
|
|
13
9
|
* Format uptime in human-readable format
|
|
@@ -45,41 +41,7 @@ export function formatMemory(memoryUsage: {
|
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
/**
|
|
48
|
-
* Format
|
|
49
|
-
*/
|
|
50
|
-
export function formatHealthMessage(status: BotStatus): string {
|
|
51
|
-
return MessageBuilder.markdown()
|
|
52
|
-
.title('🏥 Bot Health Status')
|
|
53
|
-
.newline()
|
|
54
|
-
.line('Status', status.status.toUpperCase(), { bold: true })
|
|
55
|
-
.line('Mode', status.mode.toUpperCase())
|
|
56
|
-
.line('Uptime', formatUptime(status.uptime))
|
|
57
|
-
.newline()
|
|
58
|
-
.title('Memory Usage')
|
|
59
|
-
.text(formatMemory(status.memoryUsage))
|
|
60
|
-
.build()
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Format bot statistics using MessageBuilder
|
|
65
|
-
*/
|
|
66
|
-
export function formatStats(stats: {
|
|
67
|
-
messagesProcessed: number
|
|
68
|
-
commandsExecuted: number
|
|
69
|
-
errorsEncountered: number
|
|
70
|
-
}): string {
|
|
71
|
-
return MessageBuilder.markdown()
|
|
72
|
-
.title('📊 Bot Statistics')
|
|
73
|
-
.newline()
|
|
74
|
-
.section('Performance')
|
|
75
|
-
.line('Messages Processed', String(stats.messagesProcessed))
|
|
76
|
-
.line('Commands Executed', String(stats.commandsExecuted))
|
|
77
|
-
.line('Errors Encountered', String(stats.errorsEncountered))
|
|
78
|
-
.build()
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Format a log entry message
|
|
44
|
+
* Format a log entry message for Telegram
|
|
83
45
|
*/
|
|
84
46
|
export function formatLogEntry(
|
|
85
47
|
timestamp: string,
|
|
@@ -97,22 +59,5 @@ export function formatLogEntry(
|
|
|
97
59
|
|
|
98
60
|
const emoji = levelEmoji[level as keyof typeof levelEmoji] || 'ℹ️'
|
|
99
61
|
|
|
100
|
-
return
|
|
101
|
-
.text(`${emoji} [${component}] `)
|
|
102
|
-
.text(message)
|
|
103
|
-
.newline()
|
|
104
|
-
.text(fmt.italic(timestamp))
|
|
105
|
-
.build()
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Format error message
|
|
110
|
-
*/
|
|
111
|
-
export function formatError(error: Error | string): string {
|
|
112
|
-
const message = error instanceof Error ? error.message : String(error)
|
|
113
|
-
return MessageBuilder.markdown()
|
|
114
|
-
.text('❌ ')
|
|
115
|
-
.title('Error:')
|
|
116
|
-
.text(message)
|
|
117
|
-
.build()
|
|
62
|
+
return `${emoji} [${component}] ${message}\n${fmt.italic(timestamp)}`
|
|
118
63
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"type": "module",
|
|
6
6
|
"workspaces": [
|
|
7
7
|
"core",
|
|
8
|
-
"
|
|
8
|
+
"packages/*"
|
|
9
9
|
],
|
|
10
10
|
"scripts": {
|
|
11
11
|
"dev": "bun run --filter @mks2508/telegram-bot-core dev",
|
|
@@ -39,7 +39,8 @@
|
|
|
39
39
|
"typescript": "^5"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@
|
|
42
|
+
"@mks2508/telegram-message-builder": "0.3.1",
|
|
43
|
+
"@mks2508/telegram-bot-utils": "workspace:*",
|
|
43
44
|
"@inquirer/prompts": "^8.1.0",
|
|
44
45
|
"chalk": "^5.6.2",
|
|
45
46
|
"commander": "^14.0.2",
|
|
@@ -2,11 +2,22 @@
|
|
|
2
2
|
"name": "@mks2508/telegram-bot-utils",
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "rolldown --config rolldown.config.ts && tsgo --emitDeclarationOnly",
|
|
7
|
+
"dev": "bun run --watch src/index.ts",
|
|
8
|
+
"typecheck": "tsgo --noEmit"
|
|
9
|
+
},
|
|
5
10
|
"exports": {
|
|
6
|
-
".":
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
}
|
|
7
15
|
},
|
|
8
16
|
"dependencies": {
|
|
9
17
|
"@mks2508/better-logger": "^4.0.0",
|
|
10
18
|
"@mks2508/no-throw": "^0.1.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"rolldown": "^1.0.0-beta.58"
|
|
11
22
|
}
|
|
12
23
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"moduleResolution": "bundler",
|
|
9
9
|
"allowImportingTsExtensions": true,
|
|
10
10
|
"verbatimModuleSyntax": true,
|
|
11
|
-
"noEmit":
|
|
11
|
+
"noEmit": false,
|
|
12
12
|
"strict": true,
|
|
13
13
|
"skipLibCheck": true,
|
|
14
14
|
"noFallthroughCasesInSwitch": true,
|
|
@@ -16,7 +16,12 @@
|
|
|
16
16
|
"noImplicitOverride": true,
|
|
17
17
|
"noUnusedLocals": false,
|
|
18
18
|
"noUnusedParameters": false,
|
|
19
|
-
"noPropertyAccessFromIndexSignature": false
|
|
19
|
+
"noPropertyAccessFromIndexSignature": false,
|
|
20
|
+
"declaration": true,
|
|
21
|
+
"declarationMap": true,
|
|
22
|
+
"sourceMap": true,
|
|
23
|
+
"outDir": "./dist",
|
|
24
|
+
"declarationDir": "./dist"
|
|
20
25
|
},
|
|
21
26
|
"exclude": ["node_modules", "**/node_modules", "**/dist"]
|
|
22
27
|
}
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import telegramFormat from '@flla/telegram-format'
|
|
2
|
-
import type { Formatter } from '@flla/telegram-format'
|
|
3
|
-
|
|
4
|
-
// Get the formatters from the main module
|
|
5
|
-
const { html } = telegramFormat
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* MessageBuilder - Fluent API for building formatted Telegram messages
|
|
9
|
-
*
|
|
10
|
-
* Provides a consistent way to build messages without worrying about:
|
|
11
|
-
* - Proper escaping of special characters
|
|
12
|
-
* - Format consistency (Markdown vs HTML)
|
|
13
|
-
* - Parse errors from malformed entities
|
|
14
|
-
*
|
|
15
|
-
* @example
|
|
16
|
-
* ```typescript
|
|
17
|
-
* const message = MessageBuilder.markdown()
|
|
18
|
-
* .title('User Information')
|
|
19
|
-
* .newline()
|
|
20
|
-
* .line('User ID', '123456', { code: true })
|
|
21
|
-
* .line('Username', '@john_doe')
|
|
22
|
-
* .build()
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
export class MessageBuilder {
|
|
26
|
-
private parts: string[] = []
|
|
27
|
-
private listDepth = 0
|
|
28
|
-
|
|
29
|
-
private constructor(
|
|
30
|
-
private formatter: Formatter,
|
|
31
|
-
private parseModeValue: 'Markdown' | 'HTML' | 'MarkdownV2'
|
|
32
|
-
) {}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Create an HTML message builder (default)
|
|
36
|
-
* HTML is simpler and more reliable than MarkdownV2
|
|
37
|
-
*/
|
|
38
|
-
static markdown(): MessageBuilder {
|
|
39
|
-
return new MessageBuilder(html as unknown as Formatter, 'HTML')
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Create an HTML message builder
|
|
44
|
-
*/
|
|
45
|
-
static html(): MessageBuilder {
|
|
46
|
-
return new MessageBuilder(html as unknown as Formatter, 'HTML')
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Add a title/heading (bold)
|
|
51
|
-
*/
|
|
52
|
-
title(text: string): this {
|
|
53
|
-
this.parts.push(this.formatter.bold(text))
|
|
54
|
-
return this
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Add a section heading (underline/italic)
|
|
59
|
-
*/
|
|
60
|
-
section(text: string): this {
|
|
61
|
-
this.parts.push(this.formatter.underline(text))
|
|
62
|
-
return this
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Add a key-value line
|
|
67
|
-
* @param key - The label/key
|
|
68
|
-
* @param value - The value
|
|
69
|
-
* @param opts - Options for formatting the value
|
|
70
|
-
*/
|
|
71
|
-
line(key: string, value: string, opts?: { code?: boolean; bold?: boolean }): this {
|
|
72
|
-
let formattedValue = value
|
|
73
|
-
if (opts?.code) {
|
|
74
|
-
formattedValue = this.formatter.monospace(value)
|
|
75
|
-
} else if (opts?.bold) {
|
|
76
|
-
formattedValue = this.formatter.bold(value)
|
|
77
|
-
}
|
|
78
|
-
this.parts.push(`${key}: ${formattedValue}`)
|
|
79
|
-
return this
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Add a code block
|
|
84
|
-
*/
|
|
85
|
-
codeBlock(text: string, language?: string): this {
|
|
86
|
-
this.parts.push(this.formatter.monospaceBlock(text, language))
|
|
87
|
-
return this
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Add a list item
|
|
92
|
-
*/
|
|
93
|
-
listItem(text: string, depth: number = 0): this {
|
|
94
|
-
const indent = ' '.repeat(depth)
|
|
95
|
-
const bullet = this.listDepth > 0 ? '•' : `${this.listDepth + 1}.`
|
|
96
|
-
this.parts.push(`${indent}${bullet} ${text}`)
|
|
97
|
-
return this
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Add a sublist (increase indentation)
|
|
102
|
-
*/
|
|
103
|
-
startSublist(): this {
|
|
104
|
-
this.listDepth++
|
|
105
|
-
return this
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* End sublist (decrease indentation)
|
|
110
|
-
*/
|
|
111
|
-
endSublist(): this {
|
|
112
|
-
if (this.listDepth > 0) this.listDepth--
|
|
113
|
-
return this
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Add a newline
|
|
118
|
-
*/
|
|
119
|
-
newline(): this {
|
|
120
|
-
this.parts.push('\n')
|
|
121
|
-
return this
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Add raw text (escaped, no formatting)
|
|
126
|
-
*/
|
|
127
|
-
text(text: string): this {
|
|
128
|
-
this.parts.push(this.formatter.escape(text))
|
|
129
|
-
return this
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Add a horizontal rule (separator)
|
|
134
|
-
*/
|
|
135
|
-
separator(): this {
|
|
136
|
-
this.parts.push(this.parseModeValue === 'HTML' ? '<hr>' : '---')
|
|
137
|
-
return this
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Build the final message string
|
|
142
|
-
* @returns The formatted message ready to send
|
|
143
|
-
*/
|
|
144
|
-
build(): string {
|
|
145
|
-
return this.parts.join('\n').trim()
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Get the parse_mode for Telegraf
|
|
150
|
-
* Note: Telegraf accepts 'Markdown' for both Markdown and MarkdownV2
|
|
151
|
-
*/
|
|
152
|
-
getParseMode(): 'Markdown' | 'HTML' {
|
|
153
|
-
return this.parseModeValue === 'MarkdownV2' ? 'Markdown' : this.parseModeValue
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Quick escape helper for raw text
|
|
159
|
-
*/
|
|
160
|
-
export function escapeText(text: string): string {
|
|
161
|
-
const formatter = html as unknown as Formatter
|
|
162
|
-
return formatter.escape(text)
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Format mode type
|
|
167
|
-
*/
|
|
168
|
-
export type FormatType = 'html'
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Quick format helpers
|
|
172
|
-
*/
|
|
173
|
-
export const fmt = {
|
|
174
|
-
bold: (text: string) => (html as unknown as Formatter).bold(text),
|
|
175
|
-
italic: (text: string) => (html as unknown as Formatter).italic(text),
|
|
176
|
-
underline: (text: string) => (html as unknown as Formatter).underline(text),
|
|
177
|
-
code: (text: string) => (html as unknown as Formatter).monospace(text),
|
|
178
|
-
link: (text: string, url: string) => (html as unknown as Formatter).url(text, url),
|
|
179
|
-
escape: (text: string) => (html as unknown as Formatter).escape(text),
|
|
180
|
-
}
|