crewly 1.4.2 → 1.4.4

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 (83) hide show
  1. package/config/skills/orchestrator/reply-gchat/execute.sh +4 -4
  2. package/config/templates/dev-fullstack/norms/docker-deploy-cleanup.md +28 -0
  3. package/dist/backend/backend/src/constants.d.ts +45 -14
  4. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  5. package/dist/backend/backend/src/constants.js +45 -14
  6. package/dist/backend/backend/src/constants.js.map +1 -1
  7. package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts.map +1 -1
  8. package/dist/backend/backend/src/controllers/cloud/cloud.controller.js +14 -3
  9. package/dist/backend/backend/src/controllers/cloud/cloud.controller.js.map +1 -1
  10. package/dist/backend/backend/src/controllers/cloud/relay.controller.d.ts +15 -3
  11. package/dist/backend/backend/src/controllers/cloud/relay.controller.d.ts.map +1 -1
  12. package/dist/backend/backend/src/controllers/cloud/relay.controller.js +46 -8
  13. package/dist/backend/backend/src/controllers/cloud/relay.controller.js.map +1 -1
  14. package/dist/backend/backend/src/controllers/cloud/relay.routes.d.ts.map +1 -1
  15. package/dist/backend/backend/src/controllers/cloud/relay.routes.js +2 -1
  16. package/dist/backend/backend/src/controllers/cloud/relay.routes.js.map +1 -1
  17. package/dist/backend/backend/src/controllers/messaging/messenger.routes.d.ts.map +1 -1
  18. package/dist/backend/backend/src/controllers/messaging/messenger.routes.js +86 -3
  19. package/dist/backend/backend/src/controllers/messaging/messenger.routes.js.map +1 -1
  20. package/dist/backend/backend/src/index.d.ts +5 -0
  21. package/dist/backend/backend/src/index.d.ts.map +1 -1
  22. package/dist/backend/backend/src/index.js +33 -0
  23. package/dist/backend/backend/src/index.js.map +1 -1
  24. package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts +27 -0
  25. package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts.map +1 -1
  26. package/dist/backend/backend/src/services/cloud/cloud-client.service.js +28 -0
  27. package/dist/backend/backend/src/services/cloud/cloud-client.service.js.map +1 -1
  28. package/dist/backend/backend/src/services/cloud/relay-client.service.d.ts +47 -44
  29. package/dist/backend/backend/src/services/cloud/relay-client.service.d.ts.map +1 -1
  30. package/dist/backend/backend/src/services/cloud/relay-client.service.js +185 -152
  31. package/dist/backend/backend/src/services/cloud/relay-client.service.js.map +1 -1
  32. package/dist/backend/backend/src/services/cloud/relay-server.service.d.ts.map +1 -1
  33. package/dist/backend/backend/src/services/cloud/relay-server.service.js +3 -12
  34. package/dist/backend/backend/src/services/cloud/relay-server.service.js.map +1 -1
  35. package/dist/backend/backend/src/services/cloud/relay.types.d.ts +27 -4
  36. package/dist/backend/backend/src/services/cloud/relay.types.d.ts.map +1 -1
  37. package/dist/backend/backend/src/services/cloud/relay.types.js.map +1 -1
  38. package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.d.ts +16 -8
  39. package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.d.ts.map +1 -1
  40. package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.js +30 -35
  41. package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.js.map +1 -1
  42. package/dist/backend/backend/src/services/messaging/response-router.service.d.ts +8 -0
  43. package/dist/backend/backend/src/services/messaging/response-router.service.d.ts.map +1 -1
  44. package/dist/backend/backend/src/services/messaging/response-router.service.js +16 -0
  45. package/dist/backend/backend/src/services/messaging/response-router.service.js.map +1 -1
  46. package/dist/backend/backend/src/services/telegram/index.d.ts +14 -0
  47. package/dist/backend/backend/src/services/telegram/index.d.ts.map +1 -0
  48. package/dist/backend/backend/src/services/telegram/index.js +11 -0
  49. package/dist/backend/backend/src/services/telegram/index.js.map +1 -0
  50. package/dist/backend/backend/src/services/telegram/telegram-credentials.service.d.ts +54 -0
  51. package/dist/backend/backend/src/services/telegram/telegram-credentials.service.d.ts.map +1 -0
  52. package/dist/backend/backend/src/services/telegram/telegram-credentials.service.js +98 -0
  53. package/dist/backend/backend/src/services/telegram/telegram-credentials.service.js.map +1 -0
  54. package/dist/backend/backend/src/services/telegram/telegram-initializer.d.ts +76 -0
  55. package/dist/backend/backend/src/services/telegram/telegram-initializer.d.ts.map +1 -0
  56. package/dist/backend/backend/src/services/telegram/telegram-initializer.js +131 -0
  57. package/dist/backend/backend/src/services/telegram/telegram-initializer.js.map +1 -0
  58. package/dist/backend/backend/src/services/telegram/telegram-orchestrator-bridge.d.ts +73 -0
  59. package/dist/backend/backend/src/services/telegram/telegram-orchestrator-bridge.d.ts.map +1 -0
  60. package/dist/backend/backend/src/services/telegram/telegram-orchestrator-bridge.js +172 -0
  61. package/dist/backend/backend/src/services/telegram/telegram-orchestrator-bridge.js.map +1 -0
  62. package/dist/backend/backend/src/services/telegram/telegram-thread-store.service.d.ts +86 -0
  63. package/dist/backend/backend/src/services/telegram/telegram-thread-store.service.d.ts.map +1 -0
  64. package/dist/backend/backend/src/services/telegram/telegram-thread-store.service.js +157 -0
  65. package/dist/backend/backend/src/services/telegram/telegram-thread-store.service.js.map +1 -0
  66. package/dist/backend/backend/src/services/telegram/telegram.service.d.ts +173 -0
  67. package/dist/backend/backend/src/services/telegram/telegram.service.d.ts.map +1 -0
  68. package/dist/backend/backend/src/services/telegram/telegram.service.js +304 -0
  69. package/dist/backend/backend/src/services/telegram/telegram.service.js.map +1 -0
  70. package/dist/cli/backend/src/constants.d.ts +45 -14
  71. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  72. package/dist/cli/backend/src/constants.js +45 -14
  73. package/dist/cli/backend/src/constants.js.map +1 -1
  74. package/dist/cli/cli/src/commands/migrate.d.ts +101 -0
  75. package/dist/cli/cli/src/commands/migrate.d.ts.map +1 -0
  76. package/dist/cli/cli/src/commands/migrate.js +335 -0
  77. package/dist/cli/cli/src/commands/migrate.js.map +1 -0
  78. package/dist/cli/cli/src/index.js +8 -0
  79. package/dist/cli/cli/src/index.js.map +1 -1
  80. package/frontend/dist/assets/{index-f1dc9f80.css → index-2b76b01d.css} +1 -1
  81. package/frontend/dist/assets/{index-c35cdbc5.js → index-83869ca7.js} +321 -321
  82. package/frontend/dist/index.html +2 -2
  83. package/package.json +1 -1
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Telegram Thread Store Service
3
+ *
4
+ * Persists Telegram chat conversations as markdown files so the
5
+ * orchestrator can read conversation history after restart.
6
+ *
7
+ * Storage layout:
8
+ * ~/.crewly/telegram-threads/
9
+ * {chatId}.md — Chat conversation file
10
+ *
11
+ * @module services/telegram/telegram-thread-store
12
+ */
13
+ import { promises as fs } from 'fs';
14
+ import path from 'path';
15
+ import os from 'os';
16
+ import { formatMessageTimestamp } from '../../utils/format-date.js';
17
+ /** Storage directory name for Telegram threads */
18
+ const STORAGE_DIR = 'telegram-threads';
19
+ /** File extension for thread files */
20
+ const FILE_EXTENSION = '.md';
21
+ /**
22
+ * TelegramThreadStoreService manages persistent storage of Telegram
23
+ * chat conversations as markdown files.
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * const store = new TelegramThreadStoreService();
28
+ * await store.appendUserMessage('12345', 'Alice', 'Hello bot!');
29
+ * await store.appendBotReply('12345', 'Hello Alice!');
30
+ * ```
31
+ */
32
+ export class TelegramThreadStoreService {
33
+ baseDir;
34
+ /**
35
+ * Create a new TelegramThreadStoreService.
36
+ *
37
+ * @param crewlyHome - Base crewly home directory (defaults to ~/.crewly)
38
+ */
39
+ constructor(crewlyHome) {
40
+ const home = crewlyHome || path.join(os.homedir(), '.crewly');
41
+ this.baseDir = path.join(home, STORAGE_DIR);
42
+ }
43
+ /**
44
+ * Compute the file path for a chat conversation file.
45
+ *
46
+ * @param chatId - Telegram chat ID
47
+ * @returns Absolute path to the chat markdown file
48
+ */
49
+ getChatFilePath(chatId) {
50
+ // Sanitize chatId (remove any non-alphanumeric/dash/underscore characters)
51
+ const safeChatId = chatId.replace(/[^a-zA-Z0-9_-]/g, '_');
52
+ return path.join(this.baseDir, `${safeChatId}${FILE_EXTENSION}`);
53
+ }
54
+ /**
55
+ * Ensure the chat file exists, creating it with frontmatter if needed.
56
+ *
57
+ * @param chatId - Telegram chat ID
58
+ * @param userName - Name of the user who started the conversation
59
+ * @returns Absolute path to the chat file
60
+ */
61
+ async ensureChatFile(chatId, userName) {
62
+ const filePath = this.getChatFilePath(chatId);
63
+ const dir = path.dirname(filePath);
64
+ await fs.mkdir(dir, { recursive: true });
65
+ try {
66
+ await fs.access(filePath);
67
+ }
68
+ catch {
69
+ // File doesn't exist — create with frontmatter
70
+ const frontmatter = [
71
+ '---',
72
+ `chatId: ${chatId}`,
73
+ `user: ${userName}`,
74
+ `started: ${new Date().toISOString()}`,
75
+ '---',
76
+ '',
77
+ '## Messages',
78
+ '',
79
+ ].join('\n');
80
+ await fs.writeFile(filePath, frontmatter, 'utf-8');
81
+ }
82
+ return filePath;
83
+ }
84
+ /**
85
+ * Append a user message to the chat conversation file.
86
+ *
87
+ * @param chatId - Telegram chat ID
88
+ * @param userName - Display name of the sender
89
+ * @param message - Message content
90
+ */
91
+ async appendUserMessage(chatId, userName, message) {
92
+ const filePath = await this.ensureChatFile(chatId, userName);
93
+ const timestamp = formatMessageTimestamp();
94
+ const entry = `\n**${userName}** (${timestamp}):\n${message}\n`;
95
+ await fs.appendFile(filePath, entry, 'utf-8');
96
+ }
97
+ /**
98
+ * Append a bot reply to the chat conversation file.
99
+ *
100
+ * @param chatId - Telegram chat ID
101
+ * @param message - Bot response content
102
+ */
103
+ async appendBotReply(chatId, message) {
104
+ const filePath = this.getChatFilePath(chatId);
105
+ try {
106
+ await fs.access(filePath);
107
+ }
108
+ catch {
109
+ // Chat file doesn't exist — skip silently
110
+ return;
111
+ }
112
+ const timestamp = formatMessageTimestamp();
113
+ const entry = `\n**Crewly** (${timestamp}):\n${message}\n`;
114
+ await fs.appendFile(filePath, entry, 'utf-8');
115
+ }
116
+ /**
117
+ * Read the latest conversation thread file path for a given chat.
118
+ *
119
+ * @param chatId - Telegram chat ID
120
+ * @returns Path to the thread file, or null if not found
121
+ */
122
+ async getLatestThreadPath(chatId) {
123
+ const filePath = this.getChatFilePath(chatId);
124
+ try {
125
+ await fs.access(filePath);
126
+ return filePath;
127
+ }
128
+ catch {
129
+ return null;
130
+ }
131
+ }
132
+ }
133
+ /** Singleton instance */
134
+ let instance = null;
135
+ /**
136
+ * Get the TelegramThreadStoreService singleton.
137
+ *
138
+ * @returns The service instance or null if not initialized
139
+ */
140
+ export function getTelegramThreadStore() {
141
+ return instance;
142
+ }
143
+ /**
144
+ * Set the TelegramThreadStoreService singleton.
145
+ *
146
+ * @param store - The service instance to set
147
+ */
148
+ export function setTelegramThreadStore(store) {
149
+ instance = store;
150
+ }
151
+ /**
152
+ * Reset the TelegramThreadStoreService singleton (for testing).
153
+ */
154
+ export function resetTelegramThreadStore() {
155
+ instance = null;
156
+ }
157
+ //# sourceMappingURL=telegram-thread-store.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram-thread-store.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/telegram/telegram-thread-store.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Telegram Service
3
+ *
4
+ * Core service for Telegram Bot API integration with long-polling
5
+ * for incoming messages. Manages bot lifecycle, incoming message
6
+ * polling, and outgoing message delivery.
7
+ *
8
+ * @module services/telegram/telegram
9
+ */
10
+ import { EventEmitter } from 'events';
11
+ import type { TelegramConfig } from './telegram-credentials.service.js';
12
+ /**
13
+ * Telegram Bot API Update object (simplified).
14
+ */
15
+ export interface TelegramUpdate {
16
+ /** Unique update identifier */
17
+ update_id: number;
18
+ /** Incoming message (present when a text message is received) */
19
+ message?: TelegramMessage;
20
+ }
21
+ /**
22
+ * Telegram Bot API Message object (simplified).
23
+ */
24
+ export interface TelegramMessage {
25
+ /** Unique message identifier */
26
+ message_id: number;
27
+ /** Sender information */
28
+ from?: {
29
+ id: number;
30
+ is_bot: boolean;
31
+ first_name: string;
32
+ last_name?: string;
33
+ username?: string;
34
+ };
35
+ /** Chat information */
36
+ chat: {
37
+ id: number;
38
+ type: 'private' | 'group' | 'supergroup' | 'channel';
39
+ title?: string;
40
+ first_name?: string;
41
+ last_name?: string;
42
+ username?: string;
43
+ };
44
+ /** Date the message was sent (Unix timestamp) */
45
+ date: number;
46
+ /** Message text */
47
+ text?: string;
48
+ /** If the message is a reply, the original message */
49
+ reply_to_message?: TelegramMessage;
50
+ }
51
+ /**
52
+ * Incoming message event payload emitted by TelegramService.
53
+ */
54
+ export interface TelegramIncomingMessage {
55
+ /** Telegram chat ID */
56
+ chatId: string;
57
+ /** Telegram message ID */
58
+ messageId: number;
59
+ /** Sender user ID */
60
+ userId: string;
61
+ /** Sender display name */
62
+ userName: string;
63
+ /** Message text content */
64
+ text: string;
65
+ /** Unix timestamp */
66
+ timestamp: number;
67
+ /** Reply-to message ID (if replying) */
68
+ replyToMessageId?: number;
69
+ }
70
+ /**
71
+ * TelegramService manages the Telegram Bot API connection, incoming
72
+ * message polling via getUpdates, and outgoing message delivery.
73
+ *
74
+ * Events:
75
+ * - 'message' — Emitted when a text message is received
76
+ * - 'error' — Emitted on polling errors
77
+ * - 'connected' — Emitted when polling starts
78
+ * - 'disconnected' — Emitted when polling stops
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * const service = getTelegramService();
83
+ * await service.initialize({ botToken: 'BOT_TOKEN' });
84
+ * service.on('message', (msg) => console.log(msg.text));
85
+ * service.startPolling();
86
+ * ```
87
+ */
88
+ export declare class TelegramService extends EventEmitter {
89
+ private logger;
90
+ private config;
91
+ private botInfo;
92
+ private polling;
93
+ private pollTimer;
94
+ private lastUpdateOffset;
95
+ private consecutiveFailures;
96
+ private connected;
97
+ constructor();
98
+ /**
99
+ * Initialize the Telegram service by validating the bot token.
100
+ *
101
+ * @param config - Telegram configuration with bot token
102
+ * @throws Error if token is invalid or validation fails
103
+ */
104
+ initialize(config: TelegramConfig): Promise<void>;
105
+ /**
106
+ * Start long-polling for incoming messages.
107
+ * Emits 'message' events for each incoming text message.
108
+ */
109
+ startPolling(): void;
110
+ /**
111
+ * Stop polling for incoming messages.
112
+ */
113
+ stopPolling(): void;
114
+ /**
115
+ * Send a text message to a Telegram chat.
116
+ *
117
+ * @param chatId - Telegram chat ID
118
+ * @param text - Message content
119
+ * @param replyToMessageId - Optional message ID to reply to
120
+ * @returns The sent message ID
121
+ * @throws Error if service is not initialized or send fails
122
+ */
123
+ sendMessage(chatId: string, text: string, replyToMessageId?: number): Promise<number>;
124
+ /**
125
+ * Check if the service is currently connected and polling.
126
+ *
127
+ * @returns True if polling is active
128
+ */
129
+ isConnected(): boolean;
130
+ /**
131
+ * Get the current service status.
132
+ *
133
+ * @returns Status object with connection state and bot info
134
+ */
135
+ getStatus(): Record<string, unknown>;
136
+ /**
137
+ * Disconnect the service and stop polling.
138
+ */
139
+ disconnect(): Promise<void>;
140
+ /**
141
+ * Get the bot's username.
142
+ *
143
+ * @returns Bot username or null if not initialized
144
+ */
145
+ getBotUsername(): string | null;
146
+ /**
147
+ * Internal polling loop. Calls getUpdates and schedules next poll.
148
+ */
149
+ private poll;
150
+ /**
151
+ * Call the Telegram getUpdates API with long polling.
152
+ *
153
+ * @returns Array of updates
154
+ */
155
+ private getUpdates;
156
+ /**
157
+ * Process a single Telegram update and emit events.
158
+ *
159
+ * @param update - The update to process
160
+ */
161
+ private processUpdate;
162
+ }
163
+ /**
164
+ * Get the TelegramService singleton.
165
+ *
166
+ * @returns The service instance
167
+ */
168
+ export declare function getTelegramService(): TelegramService;
169
+ /**
170
+ * Reset the TelegramService singleton (for testing).
171
+ */
172
+ export declare function resetTelegramService(): void;
173
+ //# sourceMappingURL=telegram.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/telegram/telegram.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,304 @@
1
+ /**
2
+ * Telegram Service
3
+ *
4
+ * Core service for Telegram Bot API integration with long-polling
5
+ * for incoming messages. Manages bot lifecycle, incoming message
6
+ * polling, and outgoing message delivery.
7
+ *
8
+ * @module services/telegram/telegram
9
+ */
10
+ import { EventEmitter } from 'events';
11
+ import { TELEGRAM_CONSTANTS } from '../../constants.js';
12
+ import { LoggerService } from '../core/logger.service.js';
13
+ import { formatError } from '../../utils/format-error.js';
14
+ /**
15
+ * TelegramService manages the Telegram Bot API connection, incoming
16
+ * message polling via getUpdates, and outgoing message delivery.
17
+ *
18
+ * Events:
19
+ * - 'message' — Emitted when a text message is received
20
+ * - 'error' — Emitted on polling errors
21
+ * - 'connected' — Emitted when polling starts
22
+ * - 'disconnected' — Emitted when polling stops
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const service = getTelegramService();
27
+ * await service.initialize({ botToken: 'BOT_TOKEN' });
28
+ * service.on('message', (msg) => console.log(msg.text));
29
+ * service.startPolling();
30
+ * ```
31
+ */
32
+ export class TelegramService extends EventEmitter {
33
+ logger;
34
+ config = null;
35
+ botInfo = null;
36
+ polling = false;
37
+ pollTimer = null;
38
+ lastUpdateOffset = 0;
39
+ consecutiveFailures = 0;
40
+ connected = false;
41
+ constructor() {
42
+ super();
43
+ this.logger = LoggerService.getInstance().createComponentLogger('TelegramService');
44
+ }
45
+ /**
46
+ * Initialize the Telegram service by validating the bot token.
47
+ *
48
+ * @param config - Telegram configuration with bot token
49
+ * @throws Error if token is invalid or validation fails
50
+ */
51
+ async initialize(config) {
52
+ if (!config.botToken) {
53
+ throw new Error('Telegram bot token is required');
54
+ }
55
+ // Validate token via getMe
56
+ const resp = await fetch(`${TELEGRAM_CONSTANTS.API_BASE}${config.botToken}/getMe`, {
57
+ signal: AbortSignal.timeout(TELEGRAM_CONSTANTS.FETCH_TIMEOUT_MS),
58
+ });
59
+ if (!resp.ok) {
60
+ throw new Error(`Telegram token validation failed (HTTP ${resp.status})`);
61
+ }
62
+ const data = (await resp.json());
63
+ if (!data.ok || !data.result) {
64
+ throw new Error(data.description || 'Telegram token validation failed');
65
+ }
66
+ this.config = config;
67
+ this.botInfo = { id: data.result.id, username: data.result.username };
68
+ this.logger.info('Telegram bot validated', { username: data.result.username });
69
+ }
70
+ /**
71
+ * Start long-polling for incoming messages.
72
+ * Emits 'message' events for each incoming text message.
73
+ */
74
+ startPolling() {
75
+ if (this.polling) {
76
+ this.logger.warn('Polling already active');
77
+ return;
78
+ }
79
+ if (!this.config) {
80
+ throw new Error('TelegramService not initialized — call initialize() first');
81
+ }
82
+ this.polling = true;
83
+ this.connected = true;
84
+ this.consecutiveFailures = 0;
85
+ this.emit('connected');
86
+ this.logger.info('Polling started');
87
+ this.poll();
88
+ }
89
+ /**
90
+ * Stop polling for incoming messages.
91
+ */
92
+ stopPolling() {
93
+ this.polling = false;
94
+ this.connected = false;
95
+ if (this.pollTimer) {
96
+ clearTimeout(this.pollTimer);
97
+ this.pollTimer = null;
98
+ }
99
+ this.emit('disconnected');
100
+ this.logger.info('Polling stopped');
101
+ }
102
+ /**
103
+ * Send a text message to a Telegram chat.
104
+ *
105
+ * @param chatId - Telegram chat ID
106
+ * @param text - Message content
107
+ * @param replyToMessageId - Optional message ID to reply to
108
+ * @returns The sent message ID
109
+ * @throws Error if service is not initialized or send fails
110
+ */
111
+ async sendMessage(chatId, text, replyToMessageId) {
112
+ if (!this.config) {
113
+ throw new Error('TelegramService not initialized');
114
+ }
115
+ // Truncate message if too long
116
+ const truncatedText = text.length > TELEGRAM_CONSTANTS.MAX_MESSAGE_LENGTH
117
+ ? text.slice(0, TELEGRAM_CONSTANTS.MAX_MESSAGE_LENGTH - 20) + '\n\n...(truncated)'
118
+ : text;
119
+ const body = {
120
+ chat_id: chatId,
121
+ text: truncatedText,
122
+ parse_mode: 'Markdown',
123
+ };
124
+ if (replyToMessageId) {
125
+ body.reply_to_message_id = replyToMessageId;
126
+ }
127
+ const resp = await fetch(`${TELEGRAM_CONSTANTS.API_BASE}${this.config.botToken}/sendMessage`, {
128
+ method: 'POST',
129
+ headers: { 'Content-Type': 'application/json' },
130
+ body: JSON.stringify(body),
131
+ signal: AbortSignal.timeout(TELEGRAM_CONSTANTS.FETCH_TIMEOUT_MS),
132
+ });
133
+ if (!resp.ok) {
134
+ const details = await resp.text();
135
+ throw new Error(`Telegram send failed (${resp.status}): ${details}`);
136
+ }
137
+ const data = (await resp.json());
138
+ return data.result?.message_id ?? 0;
139
+ }
140
+ /**
141
+ * Check if the service is currently connected and polling.
142
+ *
143
+ * @returns True if polling is active
144
+ */
145
+ isConnected() {
146
+ return this.connected && this.polling;
147
+ }
148
+ /**
149
+ * Get the current service status.
150
+ *
151
+ * @returns Status object with connection state and bot info
152
+ */
153
+ getStatus() {
154
+ return {
155
+ connected: this.isConnected(),
156
+ polling: this.polling,
157
+ botUsername: this.botInfo?.username ?? null,
158
+ botId: this.botInfo?.id ?? null,
159
+ consecutiveFailures: this.consecutiveFailures,
160
+ lastUpdateOffset: this.lastUpdateOffset,
161
+ };
162
+ }
163
+ /**
164
+ * Disconnect the service and stop polling.
165
+ */
166
+ async disconnect() {
167
+ this.stopPolling();
168
+ this.config = null;
169
+ this.botInfo = null;
170
+ this.lastUpdateOffset = 0;
171
+ this.consecutiveFailures = 0;
172
+ }
173
+ /**
174
+ * Get the bot's username.
175
+ *
176
+ * @returns Bot username or null if not initialized
177
+ */
178
+ getBotUsername() {
179
+ return this.botInfo?.username ?? null;
180
+ }
181
+ /**
182
+ * Internal polling loop. Calls getUpdates and schedules next poll.
183
+ */
184
+ async poll() {
185
+ if (!this.polling || !this.config)
186
+ return;
187
+ try {
188
+ const updates = await this.getUpdates();
189
+ this.consecutiveFailures = 0;
190
+ for (const update of updates) {
191
+ this.processUpdate(update);
192
+ }
193
+ }
194
+ catch (error) {
195
+ this.consecutiveFailures++;
196
+ this.logger.error('Polling error', {
197
+ error: formatError(error),
198
+ consecutiveFailures: this.consecutiveFailures,
199
+ });
200
+ this.emit('error', error);
201
+ if (this.consecutiveFailures >= TELEGRAM_CONSTANTS.MAX_CONSECUTIVE_FAILURES) {
202
+ this.logger.error('Max consecutive failures reached — pausing polling');
203
+ this.stopPolling();
204
+ return;
205
+ }
206
+ }
207
+ // Schedule next poll
208
+ if (this.polling) {
209
+ this.pollTimer = setTimeout(() => this.poll(), TELEGRAM_CONSTANTS.POLL_INTERVAL_MS);
210
+ }
211
+ }
212
+ /**
213
+ * Call the Telegram getUpdates API with long polling.
214
+ *
215
+ * @returns Array of updates
216
+ */
217
+ async getUpdates() {
218
+ if (!this.config)
219
+ return [];
220
+ const params = new URLSearchParams({
221
+ timeout: String(TELEGRAM_CONSTANTS.LONG_POLL_TIMEOUT_S),
222
+ allowed_updates: JSON.stringify(['message']),
223
+ });
224
+ if (this.lastUpdateOffset > 0) {
225
+ params.set('offset', String(this.lastUpdateOffset));
226
+ }
227
+ const resp = await fetch(`${TELEGRAM_CONSTANTS.API_BASE}${this.config.botToken}/getUpdates?${params}`, {
228
+ signal: AbortSignal.timeout(TELEGRAM_CONSTANTS.FETCH_TIMEOUT_MS),
229
+ });
230
+ if (!resp.ok) {
231
+ throw new Error(`getUpdates failed (HTTP ${resp.status})`);
232
+ }
233
+ const data = (await resp.json());
234
+ const updates = data.result ?? [];
235
+ // Update offset to acknowledge processed updates
236
+ if (updates.length > 0) {
237
+ const maxId = Math.max(...updates.map((u) => u.update_id));
238
+ this.lastUpdateOffset = maxId + 1;
239
+ }
240
+ return updates;
241
+ }
242
+ /**
243
+ * Process a single Telegram update and emit events.
244
+ *
245
+ * @param update - The update to process
246
+ */
247
+ processUpdate(update) {
248
+ if (!update.message?.text)
249
+ return;
250
+ const msg = update.message;
251
+ // Skip messages from bots
252
+ if (msg.from?.is_bot)
253
+ return;
254
+ // Check allowed users filter
255
+ if (this.config?.allowedUserIds &&
256
+ this.config.allowedUserIds.length > 0 &&
257
+ !this.config.allowedUserIds.includes(String(msg.from?.id))) {
258
+ this.logger.debug('Message from non-allowed user ignored', {
259
+ userId: msg.from?.id,
260
+ });
261
+ return;
262
+ }
263
+ const incoming = {
264
+ chatId: String(msg.chat.id),
265
+ messageId: msg.message_id,
266
+ userId: String(msg.from?.id ?? 0),
267
+ userName: msg.from?.first_name +
268
+ (msg.from?.last_name ? ` ${msg.from.last_name}` : ''),
269
+ text: msg.text,
270
+ timestamp: msg.date,
271
+ replyToMessageId: msg.reply_to_message?.message_id,
272
+ };
273
+ this.logger.debug('Incoming message', {
274
+ chatId: incoming.chatId,
275
+ userId: incoming.userId,
276
+ textLength: incoming.text.length,
277
+ });
278
+ this.emit('message', incoming);
279
+ }
280
+ }
281
+ /** Singleton instance */
282
+ let instance = null;
283
+ /**
284
+ * Get the TelegramService singleton.
285
+ *
286
+ * @returns The service instance
287
+ */
288
+ export function getTelegramService() {
289
+ if (!instance) {
290
+ instance = new TelegramService();
291
+ }
292
+ return instance;
293
+ }
294
+ /**
295
+ * Reset the TelegramService singleton (for testing).
296
+ */
297
+ export function resetTelegramService() {
298
+ if (instance) {
299
+ instance.stopPolling();
300
+ instance.removeAllListeners();
301
+ }
302
+ instance = null;
303
+ }
304
+ //# sourceMappingURL=telegram.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/telegram/telegram.service.ts"],"names":[],"mappings":"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"}