create-bunspace 0.1.0

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.
Files changed (182) hide show
  1. package/README.md +181 -0
  2. package/dist/bin.js +5755 -0
  3. package/dist/templates/monorepo/CLAUDE.md +164 -0
  4. package/dist/templates/monorepo/LICENSE +21 -0
  5. package/dist/templates/monorepo/MUST-FOLLOW-GUIDELINES.md +269 -0
  6. package/dist/templates/monorepo/README.md +74 -0
  7. package/dist/templates/monorepo/SYNC_VERIFICATION.md +1 -0
  8. package/dist/templates/monorepo/apps/example/package.json +19 -0
  9. package/dist/templates/monorepo/apps/example/src/index.ts +23 -0
  10. package/dist/templates/monorepo/apps/example/src/types/index.ts +7 -0
  11. package/dist/templates/monorepo/apps/example/src/utils/index.ts +7 -0
  12. package/dist/templates/monorepo/core/packages/main/package.json +41 -0
  13. package/dist/templates/monorepo/core/packages/main/rolldown.config.ts +24 -0
  14. package/dist/templates/monorepo/core/packages/main/src/index.ts +80 -0
  15. package/dist/templates/monorepo/core/packages/main/src/types/constants.ts +15 -0
  16. package/dist/templates/monorepo/core/packages/main/src/types/index.ts +8 -0
  17. package/dist/templates/monorepo/core/packages/main/src/types/main.types.ts +25 -0
  18. package/dist/templates/monorepo/core/packages/main/src/utils/index.ts +5 -0
  19. package/dist/templates/monorepo/core/packages/utils/package.json +43 -0
  20. package/dist/templates/monorepo/core/packages/utils/rolldown.config.ts +34 -0
  21. package/dist/templates/monorepo/core/packages/utils/src/index.ts +2 -0
  22. package/dist/templates/monorepo/core/packages/utils/src/logger.ts +68 -0
  23. package/dist/templates/monorepo/core/packages/utils/src/result.ts +146 -0
  24. package/dist/templates/monorepo/core/packages/utils/src/types/constants.ts +15 -0
  25. package/dist/templates/monorepo/core/packages/utils/src/types/index.ts +8 -0
  26. package/dist/templates/monorepo/core/packages/utils/src/types/utils.types.ts +32 -0
  27. package/dist/templates/monorepo/core/packages/utils/src/utils/index.ts +5 -0
  28. package/dist/templates/monorepo/oxlint.json +14 -0
  29. package/dist/templates/monorepo/package.json +39 -0
  30. package/dist/templates/monorepo/tsconfig.json +35 -0
  31. package/dist/templates/telegram-bot/.oxlintrc.json +33 -0
  32. package/dist/templates/telegram-bot/.prettierignore +5 -0
  33. package/dist/templates/telegram-bot/.prettierrc +26 -0
  34. package/dist/templates/telegram-bot/CLAUDE.deploy.md +356 -0
  35. package/dist/templates/telegram-bot/CLAUDE.dev.md +266 -0
  36. package/dist/templates/telegram-bot/CLAUDE.md +280 -0
  37. package/dist/templates/telegram-bot/Dockerfile +46 -0
  38. package/dist/templates/telegram-bot/README.md +245 -0
  39. package/dist/templates/telegram-bot/apps/.gitkeep +0 -0
  40. package/dist/templates/telegram-bot/bun.lock +208 -0
  41. package/dist/templates/telegram-bot/core/.env.example +71 -0
  42. package/dist/templates/telegram-bot/core/README.md +1067 -0
  43. package/dist/templates/telegram-bot/core/package.json +15 -0
  44. package/dist/templates/telegram-bot/core/src/config/env.ts +131 -0
  45. package/dist/templates/telegram-bot/core/src/config/index.ts +97 -0
  46. package/dist/templates/telegram-bot/core/src/config/logging.ts +110 -0
  47. package/dist/templates/telegram-bot/core/src/handlers/control.ts +85 -0
  48. package/dist/templates/telegram-bot/core/src/handlers/health.ts +83 -0
  49. package/dist/templates/telegram-bot/core/src/handlers/logs.ts +126 -0
  50. package/dist/templates/telegram-bot/core/src/index.ts +161 -0
  51. package/dist/templates/telegram-bot/core/src/middleware/auth.ts +41 -0
  52. package/dist/templates/telegram-bot/core/src/middleware/error-handler.ts +41 -0
  53. package/dist/templates/telegram-bot/core/src/middleware/logging.ts +1 -0
  54. package/dist/templates/telegram-bot/core/src/middleware/topics.ts +55 -0
  55. package/dist/templates/telegram-bot/core/src/types/bot.ts +92 -0
  56. package/dist/templates/telegram-bot/core/src/types/constants.ts +50 -0
  57. package/dist/templates/telegram-bot/core/src/types/result.ts +1 -0
  58. package/dist/templates/telegram-bot/core/src/utils/bot-manager.test.ts +111 -0
  59. package/dist/templates/telegram-bot/core/src/utils/bot-manager.ts +201 -0
  60. package/dist/templates/telegram-bot/core/src/utils/commands.ts +63 -0
  61. package/dist/templates/telegram-bot/core/src/utils/formatters.ts +82 -0
  62. package/dist/templates/telegram-bot/core/src/utils/instance-manager.ts +189 -0
  63. package/dist/templates/telegram-bot/core/src/utils/memory.ts +33 -0
  64. package/dist/templates/telegram-bot/core/src/utils/result.ts +26 -0
  65. package/dist/templates/telegram-bot/core/src/utils/telegram.ts +31 -0
  66. package/dist/templates/telegram-bot/core/src/utils/type-guards.ts +71 -0
  67. package/dist/templates/telegram-bot/core/tsconfig.json +9 -0
  68. package/dist/templates/telegram-bot/docker-compose.yml +37 -0
  69. package/dist/templates/telegram-bot/docs/cli-commands.md +377 -0
  70. package/dist/templates/telegram-bot/docs/development.md +363 -0
  71. package/dist/templates/telegram-bot/docs/environment.md +460 -0
  72. package/dist/templates/telegram-bot/docs/examples/middleware-auth.md +335 -0
  73. package/dist/templates/telegram-bot/docs/examples/simple-command.md +207 -0
  74. package/dist/templates/telegram-bot/docs/examples/webhook-setup.md +362 -0
  75. package/dist/templates/telegram-bot/docs/getting-started.md +223 -0
  76. package/dist/templates/telegram-bot/docs/troubleshooting.md +489 -0
  77. package/dist/templates/telegram-bot/package.json +49 -0
  78. package/dist/templates/telegram-bot/packages/utils/package.json +12 -0
  79. package/dist/templates/telegram-bot/packages/utils/src/index.ts +2 -0
  80. package/dist/templates/telegram-bot/packages/utils/src/logger.ts +72 -0
  81. package/dist/templates/telegram-bot/packages/utils/src/result.ts +80 -0
  82. package/dist/templates/telegram-bot/tools/README.md +47 -0
  83. package/dist/templates/telegram-bot/tools/commands/doctor.ts +460 -0
  84. package/dist/templates/telegram-bot/tools/commands/index.ts +35 -0
  85. package/dist/templates/telegram-bot/tools/commands/ngrok.ts +207 -0
  86. package/dist/templates/telegram-bot/tools/commands/setup.ts +368 -0
  87. package/dist/templates/telegram-bot/tools/commands/status.ts +140 -0
  88. package/dist/templates/telegram-bot/tools/index.ts +16 -0
  89. package/dist/templates/telegram-bot/tools/package.json +12 -0
  90. package/dist/templates/telegram-bot/tools/utils/index.ts +13 -0
  91. package/dist/templates/telegram-bot/tsconfig.json +22 -0
  92. package/dist/templates/telegram-bot/vitest.config.ts +29 -0
  93. package/package.json +35 -0
  94. package/templates/monorepo/CLAUDE.md +164 -0
  95. package/templates/monorepo/LICENSE +21 -0
  96. package/templates/monorepo/MUST-FOLLOW-GUIDELINES.md +269 -0
  97. package/templates/monorepo/README.md +74 -0
  98. package/templates/monorepo/apps/example/package.json +19 -0
  99. package/templates/monorepo/apps/example/src/index.ts +23 -0
  100. package/templates/monorepo/apps/example/src/types/index.ts +7 -0
  101. package/templates/monorepo/apps/example/src/utils/index.ts +7 -0
  102. package/templates/monorepo/core/packages/main/package.json +41 -0
  103. package/templates/monorepo/core/packages/main/rolldown.config.ts +24 -0
  104. package/templates/monorepo/core/packages/main/src/index.ts +80 -0
  105. package/templates/monorepo/core/packages/main/src/types/constants.ts +15 -0
  106. package/templates/monorepo/core/packages/main/src/types/index.ts +8 -0
  107. package/templates/monorepo/core/packages/main/src/types/main.types.ts +25 -0
  108. package/templates/monorepo/core/packages/main/src/utils/index.ts +5 -0
  109. package/templates/monorepo/core/packages/utils/package.json +43 -0
  110. package/templates/monorepo/core/packages/utils/rolldown.config.ts +34 -0
  111. package/templates/monorepo/core/packages/utils/src/index.ts +2 -0
  112. package/templates/monorepo/core/packages/utils/src/logger.ts +68 -0
  113. package/templates/monorepo/core/packages/utils/src/result.ts +146 -0
  114. package/templates/monorepo/core/packages/utils/src/types/constants.ts +15 -0
  115. package/templates/monorepo/core/packages/utils/src/types/index.ts +8 -0
  116. package/templates/monorepo/core/packages/utils/src/types/utils.types.ts +32 -0
  117. package/templates/monorepo/core/packages/utils/src/utils/index.ts +5 -0
  118. package/templates/monorepo/oxlint.json +14 -0
  119. package/templates/monorepo/package.json +39 -0
  120. package/templates/monorepo/tsconfig.json +35 -0
  121. package/templates/telegram-bot/.oxlintrc.json +33 -0
  122. package/templates/telegram-bot/.prettierignore +5 -0
  123. package/templates/telegram-bot/.prettierrc +26 -0
  124. package/templates/telegram-bot/CLAUDE.deploy.md +356 -0
  125. package/templates/telegram-bot/CLAUDE.dev.md +266 -0
  126. package/templates/telegram-bot/CLAUDE.md +280 -0
  127. package/templates/telegram-bot/Dockerfile +46 -0
  128. package/templates/telegram-bot/README.md +245 -0
  129. package/templates/telegram-bot/apps/.gitkeep +0 -0
  130. package/templates/telegram-bot/bun.lock +208 -0
  131. package/templates/telegram-bot/core/.env.example +71 -0
  132. package/templates/telegram-bot/core/README.md +1067 -0
  133. package/templates/telegram-bot/core/package.json +15 -0
  134. package/templates/telegram-bot/core/src/config/env.ts +131 -0
  135. package/templates/telegram-bot/core/src/config/index.ts +97 -0
  136. package/templates/telegram-bot/core/src/config/logging.ts +110 -0
  137. package/templates/telegram-bot/core/src/handlers/control.ts +85 -0
  138. package/templates/telegram-bot/core/src/handlers/health.ts +83 -0
  139. package/templates/telegram-bot/core/src/handlers/logs.ts +126 -0
  140. package/templates/telegram-bot/core/src/index.ts +161 -0
  141. package/templates/telegram-bot/core/src/middleware/auth.ts +41 -0
  142. package/templates/telegram-bot/core/src/middleware/error-handler.ts +41 -0
  143. package/templates/telegram-bot/core/src/middleware/logging.ts +1 -0
  144. package/templates/telegram-bot/core/src/middleware/topics.ts +55 -0
  145. package/templates/telegram-bot/core/src/types/bot.ts +92 -0
  146. package/templates/telegram-bot/core/src/types/constants.ts +50 -0
  147. package/templates/telegram-bot/core/src/types/result.ts +1 -0
  148. package/templates/telegram-bot/core/src/utils/bot-manager.test.ts +111 -0
  149. package/templates/telegram-bot/core/src/utils/bot-manager.ts +201 -0
  150. package/templates/telegram-bot/core/src/utils/commands.ts +63 -0
  151. package/templates/telegram-bot/core/src/utils/formatters.ts +82 -0
  152. package/templates/telegram-bot/core/src/utils/instance-manager.ts +189 -0
  153. package/templates/telegram-bot/core/src/utils/memory.ts +33 -0
  154. package/templates/telegram-bot/core/src/utils/result.ts +26 -0
  155. package/templates/telegram-bot/core/src/utils/telegram.ts +31 -0
  156. package/templates/telegram-bot/core/src/utils/type-guards.ts +71 -0
  157. package/templates/telegram-bot/core/tsconfig.json +9 -0
  158. package/templates/telegram-bot/docker-compose.yml +37 -0
  159. package/templates/telegram-bot/docs/cli-commands.md +377 -0
  160. package/templates/telegram-bot/docs/development.md +363 -0
  161. package/templates/telegram-bot/docs/environment.md +460 -0
  162. package/templates/telegram-bot/docs/examples/middleware-auth.md +335 -0
  163. package/templates/telegram-bot/docs/examples/simple-command.md +207 -0
  164. package/templates/telegram-bot/docs/examples/webhook-setup.md +362 -0
  165. package/templates/telegram-bot/docs/getting-started.md +223 -0
  166. package/templates/telegram-bot/docs/troubleshooting.md +489 -0
  167. package/templates/telegram-bot/package.json +49 -0
  168. package/templates/telegram-bot/packages/utils/package.json +12 -0
  169. package/templates/telegram-bot/packages/utils/src/index.ts +2 -0
  170. package/templates/telegram-bot/packages/utils/src/logger.ts +72 -0
  171. package/templates/telegram-bot/packages/utils/src/result.ts +80 -0
  172. package/templates/telegram-bot/tools/README.md +47 -0
  173. package/templates/telegram-bot/tools/commands/doctor.ts +460 -0
  174. package/templates/telegram-bot/tools/commands/index.ts +35 -0
  175. package/templates/telegram-bot/tools/commands/ngrok.ts +207 -0
  176. package/templates/telegram-bot/tools/commands/setup.ts +368 -0
  177. package/templates/telegram-bot/tools/commands/status.ts +140 -0
  178. package/templates/telegram-bot/tools/index.ts +16 -0
  179. package/templates/telegram-bot/tools/package.json +12 -0
  180. package/templates/telegram-bot/tools/utils/index.ts +13 -0
  181. package/templates/telegram-bot/tsconfig.json +22 -0
  182. package/templates/telegram-bot/vitest.config.ts +29 -0
@@ -0,0 +1,335 @@
1
+ # Example: Auth Middleware
2
+
3
+ Ejemplo de cómo crear middleware de autenticación para comandos restringidos.
4
+
5
+ ## Middleware: Solo Usuarios Autorizados
6
+
7
+ ### Paso 1: Crear Middleware
8
+
9
+ **Archivo**: `core/src/middleware/auth-only.ts`
10
+
11
+ ```typescript
12
+ import type { Context, Middleware } from 'telegraf'
13
+ import { botLogger, badge } from '@mks2508/telegram-bot-utils'
14
+
15
+ interface AuthOnlyOptions {
16
+ authorizedIds: Set<string>
17
+ allowGroups?: boolean
18
+ }
19
+
20
+ export function authOnly(options: AuthOnlyOptions): Middleware<Context> {
21
+ const { authorizedIds, allowGroups = false } = options
22
+
23
+ return async (ctx, next) => {
24
+ const userId = ctx.from?.id.toString()
25
+
26
+ // Verificar usuario
27
+ if (!userId) {
28
+ botLogger.warn(`${badge('AUTH')} No user ID in context`)
29
+ await ctx.reply('⛔ Could not identify user')
30
+ return
31
+ }
32
+
33
+ // Verificar autorización
34
+ if (!authorizedIds.has(userId)) {
35
+ botLogger.warn(`${badge('AUTH')} Unauthorized access attempt`, {
36
+ user: userId,
37
+ command: ctx.message?.text,
38
+ })
39
+ await ctx.reply('⛔ You are not authorized to use this command')
40
+ return
41
+ }
42
+
43
+ // Usuario autorizado, continuar
44
+ botLogger.info(`${badge('AUTH')} User authorized`, { user: userId })
45
+ return next()
46
+ }
47
+ }
48
+ ```
49
+
50
+ ### Paso 2: Crear Configuración de Usuarios
51
+
52
+ **Archivo**: `core/src/config/auth.ts`
53
+
54
+ ```typescript
55
+ import { getConfig } from './index.js'
56
+
57
+ export function getAuthorizedUsers(): Set<string> {
58
+ const config = getConfig()
59
+ const authorizedIds = config.authorizedUserIds
60
+
61
+ if (!authorizedIds) {
62
+ return new Set()
63
+ }
64
+
65
+ return new Set(authorizedIds.split(',').map((id) => id.trim()))
66
+ }
67
+
68
+ // IDs para desarrollo
69
+ export const DEV_USER_IDS = new Set([
70
+ '123456789', // Reemplaza con tu ID
71
+ ])
72
+
73
+ // IDs para producción (desde env)
74
+ export function getProdUserIds(): Set<string> {
75
+ return getAuthorizedUsers()
76
+ }
77
+ ```
78
+
79
+ ### Paso 3: Usar en Comandos
80
+
81
+ **Archivo**: `core/src/handlers/admin.ts`
82
+
83
+ ```typescript
84
+ import type { Context } from 'telegraf'
85
+ import { authOnly, getProdUserIds } from '../middleware/auth-only.js'
86
+ import { botLogger } from '@mks2508/telegram-bot-utils'
87
+
88
+ export async function handleAdmin(ctx: Context): Promise<void> {
89
+ // Este comando solo funciona si el middleware auth pasa
90
+ await ctx.reply('🔐 Admin panel')
91
+ await ctx.reply('Available commands: /users, /stats, /broadcast')
92
+ }
93
+
94
+ // Registrar con middleware
95
+ export function registerAdminCommands(bot: any) {
96
+ const prodUserIds = getProdUserIds()
97
+
98
+ bot.command('admin', authOnly({ authorizedIds: prodUserIds }), handleAdmin)
99
+ }
100
+ ```
101
+
102
+ **En `core/src/index.ts`**:
103
+ ```typescript
104
+ import { registerAdminCommands } from './handlers/admin.js'
105
+
106
+ // ... después de otros comandos
107
+ registerAdminCommands(bot)
108
+ ```
109
+
110
+ ## Middleware: Chat Type
111
+
112
+ Solo permitir comandos en privados (no grupos):
113
+
114
+ ```typescript
115
+ import type { Context, Middleware } from 'telegraf'
116
+
117
+ export function privateOnly(): Middleware<Context> {
118
+ return async (ctx, next) => {
119
+ const chatType = ctx.chat?.type
120
+
121
+ if (chatType !== 'private') {
122
+ await ctx.reply('⚠️ This command only works in private chat')
123
+ return
124
+ }
125
+
126
+ return next()
127
+ }
128
+ }
129
+ ```
130
+
131
+ Usar:
132
+ ```typescript
133
+ bot.command('secret', privateOnly(), handleSecret)
134
+ ```
135
+
136
+ ## Middleware: Group Only
137
+
138
+ Solo permitir comandos en grupos:
139
+
140
+ ```typescript
141
+ import type { Context, Middleware } from 'telegraf'
142
+
143
+ export function groupOnly(): Middleware<Context> {
144
+ return async (ctx, next) => {
145
+ const chatType = ctx.chat?.type
146
+
147
+ if (chatType !== 'group' && chatType !== 'supergroup') {
148
+ await ctx.reply('⚠️ This command only works in groups')
149
+ return
150
+ }
151
+
152
+ return next()
153
+ }
154
+ }
155
+ ```
156
+
157
+ ## Middleware: Admin del Chat
158
+
159
+ Solo permitir admins del chat:
160
+
161
+ ```typescript
162
+ import type { Context, Middleware } from 'telegraf'
163
+
164
+ export function chatAdminOnly(): Middleware<Context> {
165
+ return async (ctx, next) => {
166
+ const chatId = ctx.chat?.id
167
+ const userId = ctx.from?.id
168
+
169
+ if (!chatId || !userId) {
170
+ await ctx.reply('⚠️ Could not identify chat or user')
171
+ return
172
+ }
173
+
174
+ try {
175
+ // Verificar si el usuario es admin del chat
176
+ const member = await ctx.getChatMember(userId)
177
+
178
+ if (
179
+ member.status !== 'creator' &&
180
+ member.status !== 'administrator'
181
+ ) {
182
+ await ctx.reply('⛔ Only chat admins can use this command')
183
+ return
184
+ }
185
+
186
+ return next()
187
+ } catch (error) {
188
+ botLogger.error('Failed to check chat admin status', error)
189
+ await ctx.reply('⚠️ Could not verify admin status')
190
+ return
191
+ }
192
+ }
193
+ }
194
+ ```
195
+
196
+ ## Middleware: Rate Limiting
197
+
198
+ Limitar frecuencia de comandos por usuario:
199
+
200
+ ```typescript
201
+ import type { Context, Middleware } from 'telegraf'
202
+
203
+ interface RateLimitEntry {
204
+ count: number
205
+ resetTime: number
206
+ }
207
+
208
+ const rateLimits = new Map<string, RateLimitEntry>()
209
+
210
+ interface RateLimitOptions {
211
+ maxRequests: number
212
+ windowMs: number
213
+ }
214
+
215
+ export function rateLimit(options: RateLimitOptions): Middleware<Context> {
216
+ const { maxRequests, windowMs } = options
217
+
218
+ return async (ctx, next) => {
219
+ const userId = ctx.from?.id.toString()
220
+
221
+ if (!userId) {
222
+ return next()
223
+ }
224
+
225
+ const now = Date.now()
226
+ const entry = rateLimits.get(userId)
227
+
228
+ if (!entry || now > entry.resetTime) {
229
+ // Nueva ventana
230
+ rateLimits.set(userId, {
231
+ count: 1,
232
+ resetTime: now + windowMs,
233
+ })
234
+ return next()
235
+ }
236
+
237
+ if (entry.count >= maxRequests) {
238
+ const waitTime = Math.ceil((entry.resetTime - now) / 1000)
239
+ await ctx.reply(
240
+ `⚠️ Rate limit exceeded. Wait ${waitTime}s before trying again.`
241
+ )
242
+ return
243
+ }
244
+
245
+ entry.count++
246
+ return next()
247
+ }
248
+ }
249
+ ```
250
+
251
+ Usar:
252
+ ```typescript
253
+ // Máximo 5 comandos por minuto
254
+ bot.command('search', rateLimit({ maxRequests: 5, windowMs: 60000 }), handleSearch)
255
+ ```
256
+
257
+ ## Middleware Combinado
258
+
259
+ Combinar múltiples middleware:
260
+
261
+ ```typescript
262
+ bot.command(
263
+ 'admin',
264
+ authOnly({ authorizedIds: getProdUserIds() }),
265
+ chatAdminOnly(),
266
+ rateLimit({ maxRequests: 10, windowMs: 60000 }),
267
+ handleAdmin
268
+ )
269
+ ```
270
+
271
+ ## Obtener User IDs
272
+
273
+ ### Método 1: Usar el Comando /whoami
274
+
275
+ **Archivo**: `core/src/handlers/debug.ts`
276
+
277
+ ```typescript
278
+ export async function handleWhoami(ctx: Context): Promise<void> {
279
+ const user = ctx.from
280
+ const chat = ctx.chat
281
+
282
+ const info = [
283
+ `👤 User Info:`,
284
+ `ID: ${user?.id}`,
285
+ `Username: @${user?.username ?? 'none'}`,
286
+ `First Name: ${user?.first_name ?? 'none'}`,
287
+ `Last Name: ${user?.last_name ?? 'none'}`,
288
+ ```,
289
+ `💬 Chat Info:`,
290
+ `ID: ${chat?.id}`,
291
+ `Type: ${chat?.type}`,
292
+ `Title: ${chat?.title ?? 'none'}`,
293
+ ].join('\n')
294
+
295
+ await ctx.reply(info)
296
+ }
297
+ ```
298
+
299
+ ### Método 2: Usar @GetTelegraphBot
300
+
301
+ 1. Enviar un mensaje al bot
302
+ 2. Forward el mensaje a @GetTelegraphBot
303
+ 3. El bot responde con tu ID
304
+
305
+ ### Método 3: Desde Logs
306
+
307
+ ```bash
308
+ bun run dev
309
+ # Enviar cualquier comando al bot
310
+ # Ver el log:
311
+ [Cmd] ℹ /start from user 123456789
312
+ ```
313
+
314
+ ## Configurar IDs Autorizados
315
+
316
+ En `core/.env.local`:
317
+
318
+ ```bash
319
+ # IDs separados por coma
320
+ TG_AUTHORIZED_USER_IDS=123456789,987654321
321
+ ```
322
+
323
+ ## Resumen
324
+
325
+ 1. **Crear middleware** en `core/src/middleware/`
326
+ 2. **Definir opciones** (authorized IDs, rate limits, etc.)
327
+ 3. **Aplicar a comandos** en `core/src/index.ts`
328
+ 4. **Obtener user IDs** con /whoami o @GetTelegraphBot
329
+ 5. **Configurar IDs** en `.env.local`
330
+
331
+ ## Próximos Pasos
332
+
333
+ - [Simple Command Example](./simple-command.md) - Crear comandos
334
+ - [Webhook Setup Example](./webhook-setup.md) - Configurar webhook
335
+ - [Development Guide](../development.md) - Más middleware patterns
@@ -0,0 +1,207 @@
1
+ # Example: Simple Command
2
+
3
+ Ejemplo completo de cómo agregar un comando simple al bot.
4
+
5
+ ## Comando: `/echo`
6
+
7
+ Repite el mensaje que el usuario envía.
8
+
9
+ ## Paso 1: Crear Handler
10
+
11
+ **Archivo**: `core/src/handlers/echo.ts`
12
+
13
+ ```typescript
14
+ import type { Context } from 'telegraf'
15
+ import { botLogger, badge, kv } from '@mks2508/telegram-bot-utils'
16
+
17
+ export async function handleEcho(ctx: Context): Promise<void> {
18
+ const message = ctx.message
19
+ const text = message?.text ?? ''
20
+
21
+ // Extraer argumentos (todo después de /echo)
22
+ const args = text.split(' ').slice(1).join(' ')
23
+
24
+ if (!args) {
25
+ await ctx.reply('Usage: /echo <message>')
26
+ return
27
+ }
28
+
29
+ // Log el comando
30
+ botLogger.info(`${badge('CMD')} /echo`, kv({
31
+ user: ctx.from?.id,
32
+ message: args,
33
+ }))
34
+
35
+ // Responder
36
+ await ctx.reply(args)
37
+ }
38
+ ```
39
+
40
+ ## Paso 2: Registrar en Bot
41
+
42
+ **Archivo**: `core/src/index.ts`
43
+
44
+ ```typescript
45
+ import { handleEcho } from './handlers/echo.js'
46
+
47
+ // ... después de bot.command('health', handleHealth)
48
+
49
+ bot.command('echo', handleEcho)
50
+ ```
51
+
52
+ ## Paso 3: Probar
53
+
54
+ ```bash
55
+ bun run dev
56
+ ```
57
+
58
+ En Telegram:
59
+ ```
60
+ Usuario: /echo hola mundo
61
+ Bot: hola mundo
62
+ ```
63
+
64
+ ## Variación: Echo con Mayúsculas
65
+
66
+ ```typescript
67
+ export async function handleEchoShout(ctx: Context): Promise<void> {
68
+ const message = ctx.message
69
+ const text = message?.text ?? ''
70
+ const args = text.split(' ').slice(1).join(' ')
71
+
72
+ if (!args) {
73
+ await ctx.reply('Usage: /echoshout <message>')
74
+ return
75
+ }
76
+
77
+ botLogger.info(`${badge('CMD')} /echoshout`, kv({
78
+ user: ctx.from?.id,
79
+ message: args,
80
+ }))
81
+
82
+ // Convertir a mayúsculas y agregar emojis
83
+ const shouted = `📢 ${args.toUpperCase()} 🔊`
84
+
85
+ await ctx.reply(shouted)
86
+ }
87
+ ```
88
+
89
+ Registrar:
90
+ ```typescript
91
+ bot.command('echoshout', handleEchoShout)
92
+ ```
93
+
94
+ ## Variación: Echo con Repetición
95
+
96
+ ```typescript
97
+ interface EchoOptions {
98
+ times?: number
99
+ delay?: number
100
+ }
101
+
102
+ export async function handleEchoRepeat(ctx: Context): Promise<void> {
103
+ const message = ctx.message
104
+ const text = message?.text ?? ''
105
+ const args = text.split(' ').slice(1)
106
+
107
+ // Parsear opciones
108
+ const options: EchoOptions = {}
109
+ let messageText = ''
110
+
111
+ for (let i = 0; i < args.length; i++) {
112
+ const arg = args[i]
113
+ if (arg === '--times' && args[i + 1]) {
114
+ options.times = Number.parseInt(args[i + 1], 10)
115
+ i++
116
+ } else if (arg === '--delay' && args[i + 1]) {
117
+ options.delay = Number.parseInt(args[i + 1], 10)
118
+ i++
119
+ } else {
120
+ messageText = args.slice(i).join(' ')
121
+ break
122
+ }
123
+ }
124
+
125
+ if (!messageText) {
126
+ await ctx.reply('Usage: /echorepeat [--times N] [--delay MS] <message>')
127
+ return
128
+ }
129
+
130
+ const times = options.times ?? 1
131
+ const delay = options.delay ?? 500
132
+
133
+ if (times < 1 || times > 10) {
134
+ await ctx.reply('Times must be between 1 and 10')
135
+ return
136
+ }
137
+
138
+ botLogger.info(`${badge('CMD')} /echorepeat`, kv({
139
+ user: ctx.from?.id,
140
+ message: messageText,
141
+ times,
142
+ delay,
143
+ }))
144
+
145
+ // Enviar mensajes con delay
146
+ for (let i = 0; i < times; i++) {
147
+ await ctx.reply(`${i + 1}. ${messageText}`)
148
+ if (i < times - 1) {
149
+ await new Promise(resolve => setTimeout(resolve, delay))
150
+ }
151
+ }
152
+ }
153
+ ```
154
+
155
+ Uso:
156
+ ```
157
+ /echorepeat hola → "1. hola"
158
+ /echorepeat --times 3 hola → "1. hola", "2. hola", "3. hola"
159
+ /echorepeat --delay 1000 hola → "1. hola" (1s delay) "2. hola"
160
+ ```
161
+
162
+ ## Manejo de Errors
163
+
164
+ ```typescript
165
+ import { botError, err, type Result } from '@mks2508/telegram-bot-utils'
166
+
167
+ function validateEchoMessage(message: string): Result<string> {
168
+ if (!message || message.trim().length === 0) {
169
+ return err(botError('INVALID_ARGS', 'Message cannot be empty'))
170
+ }
171
+
172
+ if (message.length > 1000) {
173
+ return err(botError('INVALID_ARGS', 'Message too long (max 1000 chars)'))
174
+ }
175
+
176
+ return { ok: true, value: message }
177
+ }
178
+
179
+ export async function handleEchoSafe(ctx: Context): Promise<void> {
180
+ const message = ctx.message
181
+ const text = message?.text ?? ''
182
+ const args = text.split(' ').slice(1).join(' ')
183
+
184
+ const result = validateEchoMessage(args)
185
+
186
+ if (!result.ok) {
187
+ botLogger.error('Echo validation failed', result.error)
188
+ await ctx.reply(`Error: ${result.error.message}`)
189
+ return
190
+ }
191
+
192
+ await ctx.reply(result.value)
193
+ }
194
+ ```
195
+
196
+ ## Resumen
197
+
198
+ 1. **Crear handler** en `core/src/handlers/`
199
+ 2. **Importar y registrar** en `core/src/index.ts`
200
+ 3. **Probar** con `bun run dev`
201
+ 4. **Commitear** después de verificar typecheck y lint
202
+
203
+ ## Próximos Pasos
204
+
205
+ - [Middleware Auth Example](./middleware-auth.md) - Agregar autenticación
206
+ - [Webhook Setup Example](./webhook-setup.md) - Configurar webhook
207
+ - [Development Guide](../development.md) - Más patrones