fixed telegram bug on not displaying things
This commit is contained in:
parent
f608aed3c2
commit
28d280d37a
|
|
@ -78,6 +78,105 @@ class TelegramChannel extends NotificationChannel {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape special characters for Telegram Markdown
|
||||
* @param {string} text - Text to escape
|
||||
* @returns {string} - Escaped text
|
||||
*/
|
||||
_escapeMarkdown(text) {
|
||||
if (!text) return '';
|
||||
// Minimal escaping to avoid message rejection
|
||||
// Over-escaping causes Telegram to reject the message
|
||||
return text
|
||||
.replace(/\*/g, '\\*') // Escape asterisks
|
||||
.replace(/_/g, '\\_') // Escape underscores
|
||||
.replace(/\[/g, '\\[') // Escape square brackets
|
||||
.replace(/\]/g, '\\]') // Escape square brackets
|
||||
.replace(/`/g, '\\`'); // Escape backticks
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a safe plain text version without markdown formatting
|
||||
* @param {string} text - Text to make safe
|
||||
* @returns {string} - Safe text
|
||||
*/
|
||||
_createSafeText(text) {
|
||||
if (!text) return '';
|
||||
// Remove problematic characters entirely to ensure message sends
|
||||
return text
|
||||
.replace(/[_*\[\]()~`>#+=|{}.!\\-]/g, '') // Remove special chars
|
||||
.replace(/\s+/g, ' ') // Collapse multiple spaces
|
||||
.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate message length including formatting
|
||||
* @param {string} message - Message to calculate
|
||||
* @returns {number} - Message length
|
||||
*/
|
||||
_calculateMessageLength(message) {
|
||||
return message.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split long text into chunks that fit Telegram limits
|
||||
* @param {string} text - Text to split
|
||||
* @param {number} maxLength - Maximum length per chunk
|
||||
* @returns {string[]} - Array of text chunks
|
||||
*/
|
||||
_splitTextIntoChunks(text, maxLength = 3000) {
|
||||
if (text.length <= maxLength) {
|
||||
return [text];
|
||||
}
|
||||
|
||||
const chunks = [];
|
||||
let currentChunk = '';
|
||||
const lines = text.split('\n');
|
||||
|
||||
for (const line of lines) {
|
||||
// If adding this line would exceed the limit
|
||||
if (currentChunk.length + line.length + 1 > maxLength) {
|
||||
if (currentChunk) {
|
||||
chunks.push(currentChunk.trim());
|
||||
currentChunk = '';
|
||||
}
|
||||
|
||||
// If single line is too long, split it by words
|
||||
if (line.length > maxLength) {
|
||||
const words = line.split(' ');
|
||||
let wordChunk = '';
|
||||
|
||||
for (const word of words) {
|
||||
if (wordChunk.length + word.length + 1 > maxLength) {
|
||||
if (wordChunk) {
|
||||
chunks.push(wordChunk.trim());
|
||||
wordChunk = word;
|
||||
} else {
|
||||
// Single word is too long, truncate it
|
||||
chunks.push(word.substring(0, maxLength - 3) + '...');
|
||||
}
|
||||
} else {
|
||||
wordChunk += (wordChunk ? ' ' : '') + word;
|
||||
}
|
||||
}
|
||||
if (wordChunk) {
|
||||
currentChunk = wordChunk;
|
||||
}
|
||||
} else {
|
||||
currentChunk = line;
|
||||
}
|
||||
} else {
|
||||
currentChunk += (currentChunk ? '\n' : '') + line;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentChunk) {
|
||||
chunks.push(currentChunk.trim());
|
||||
}
|
||||
|
||||
return chunks;
|
||||
}
|
||||
|
||||
async _getBotUsername() {
|
||||
if (this.botUsername) {
|
||||
return this.botUsername;
|
||||
|
|
@ -156,16 +255,100 @@ class TelegramChannel extends NotificationChannel {
|
|||
};
|
||||
|
||||
try {
|
||||
// Log the message details for debugging
|
||||
console.log(`[DEBUG] =====================================================`);
|
||||
console.log(`[DEBUG] Sending Telegram message, length: ${messageText.length}`);
|
||||
console.log(`[DEBUG] Chat ID: ${chatId}`);
|
||||
console.log(`[DEBUG] Session ID: ${sessionId}`);
|
||||
console.log(`[DEBUG] Message preview:`, messageText.substring(0, 200) + '...');
|
||||
console.log(`[DEBUG] =====================================================`);
|
||||
|
||||
const response = await axios.post(
|
||||
`${this.apiBaseUrl}/bot${this.config.botToken}/sendMessage`,
|
||||
requestData,
|
||||
this._getNetworkOptions()
|
||||
{
|
||||
...this._getNetworkOptions(),
|
||||
timeout: 15000 // 15 second timeout
|
||||
}
|
||||
);
|
||||
|
||||
console.log(`[DEBUG] ✅ Telegram message sent successfully!`);
|
||||
this.logger.info(`Telegram message sent successfully, Session: ${sessionId}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
this.logger.error('Failed to send Telegram message:', error.response?.data || error.message);
|
||||
// Enhanced error logging
|
||||
const errorData = error.response?.data;
|
||||
const errorMessage = errorData?.description || error.message;
|
||||
const errorCode = errorData?.error_code;
|
||||
|
||||
console.log(`[DEBUG] ❌ Telegram send error occurred:`);
|
||||
console.log(`[DEBUG] Error Code: ${errorCode}`);
|
||||
console.log(`[DEBUG] Error Message: ${errorMessage}`);
|
||||
console.log(`[DEBUG] Full error response:`, JSON.stringify(errorData, null, 2));
|
||||
console.log(`[DEBUG] Original message length: ${messageText.length}`);
|
||||
|
||||
this.logger.error(`Failed to send Telegram message (${errorCode}): ${errorMessage}`);
|
||||
|
||||
// Try multiple fallback strategies
|
||||
console.log(`[DEBUG] Attempting fallback strategies...`);
|
||||
|
||||
// Strategy 1: Try without parse_mode (plain text)
|
||||
try {
|
||||
console.log(`[DEBUG] Trying Strategy 1: Plain text without markdown`);
|
||||
const plainTextMessage = this._generateMinimalMessage(notification, token,
|
||||
notification.type === 'completed' ? '✅' : '⏳',
|
||||
notification.type === 'completed' ? 'Completed' : 'Waiting');
|
||||
|
||||
await axios.post(
|
||||
`${this.apiBaseUrl}/bot${this.config.botToken}/sendMessage`,
|
||||
{
|
||||
chat_id: chatId,
|
||||
text: plainTextMessage,
|
||||
reply_markup: {
|
||||
inline_keyboard: buttons
|
||||
}
|
||||
},
|
||||
{
|
||||
...this._getNetworkOptions(),
|
||||
timeout: 15000
|
||||
}
|
||||
);
|
||||
|
||||
console.log(`[DEBUG] ✅ Strategy 1 succeeded: Plain text message sent`);
|
||||
this.logger.info(`Telegram plain text fallback message sent successfully, Session: ${sessionId}`);
|
||||
return true;
|
||||
|
||||
} catch (fallbackError1) {
|
||||
console.log(`[DEBUG] ❌ Strategy 1 failed:`, fallbackError1.response?.data?.description || fallbackError1.message);
|
||||
|
||||
// Strategy 2: Try absolute minimal message without buttons
|
||||
try {
|
||||
console.log(`[DEBUG] Trying Strategy 2: Minimal message without buttons`);
|
||||
const minimalMessage = `Claude Task Ready\\nToken: ${token}`;
|
||||
|
||||
await axios.post(
|
||||
`${this.apiBaseUrl}/bot${this.config.botToken}/sendMessage`,
|
||||
{
|
||||
chat_id: chatId,
|
||||
text: minimalMessage
|
||||
},
|
||||
{
|
||||
...this._getNetworkOptions(),
|
||||
timeout: 15000
|
||||
}
|
||||
);
|
||||
|
||||
console.log(`[DEBUG] ✅ Strategy 2 succeeded: Minimal message sent`);
|
||||
this.logger.info(`Telegram minimal fallback message sent successfully, Session: ${sessionId}`);
|
||||
return true;
|
||||
|
||||
} catch (fallbackError2) {
|
||||
console.log(`[DEBUG] ❌ Strategy 2 failed:`, fallbackError2.response?.data?.description || fallbackError2.message);
|
||||
console.log(`[DEBUG] ❌ All fallback strategies failed`);
|
||||
this.logger.error('All Telegram fallback strategies failed');
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up failed session
|
||||
await this._removeSession(sessionId);
|
||||
return false;
|
||||
|
|
@ -177,35 +360,92 @@ class TelegramChannel extends NotificationChannel {
|
|||
const emoji = type === 'completed' ? '✅' : '⏳';
|
||||
const status = type === 'completed' ? 'Completed' : 'Waiting for Input';
|
||||
|
||||
let messageText = `${emoji} *Claude Task ${status}*\n`;
|
||||
messageText += `*Project:* ${notification.project}\n`;
|
||||
messageText += `*Session Token:* \`${token}\`\n\n`;
|
||||
|
||||
if (notification.metadata) {
|
||||
if (notification.metadata.userQuestion) {
|
||||
messageText += `📝 *Your Question:*\n${notification.metadata.userQuestion.substring(0, 200)}`;
|
||||
if (notification.metadata.userQuestion.length > 200) {
|
||||
messageText += '...';
|
||||
}
|
||||
messageText += '\n\n';
|
||||
try {
|
||||
// Method 1: Try with minimal markdown formatting
|
||||
let messageText = this._generateFormattedMessage(notification, token, emoji, status);
|
||||
|
||||
if (messageText.length <= 4000) {
|
||||
console.log(`[DEBUG] Generated formatted message length: ${messageText.length}`);
|
||||
return messageText;
|
||||
}
|
||||
|
||||
if (notification.metadata.claudeResponse) {
|
||||
messageText += `🤖 *Claude Response:*\n${notification.metadata.claudeResponse.substring(0, 300)}`;
|
||||
if (notification.metadata.claudeResponse.length > 300) {
|
||||
messageText += '...';
|
||||
}
|
||||
messageText += '\n\n';
|
||||
// Method 2: If too long, try plain text version
|
||||
console.log(`[DEBUG] Formatted message too long (${messageText.length}), trying plain text`);
|
||||
messageText = this._generatePlainTextMessage(notification, token, emoji, status);
|
||||
|
||||
if (messageText.length <= 4000) {
|
||||
console.log(`[DEBUG] Generated plain text message length: ${messageText.length}`);
|
||||
return messageText;
|
||||
}
|
||||
|
||||
// Method 3: If still too long, use minimal fallback
|
||||
console.log(`[DEBUG] Plain text still too long (${messageText.length}), using minimal fallback`);
|
||||
return this._generateMinimalMessage(notification, token, emoji, status);
|
||||
|
||||
} catch (error) {
|
||||
console.log(`[DEBUG] Error generating message: ${error.message}, using safe fallback`);
|
||||
return this._generateMinimalMessage(notification, token, emoji, status);
|
||||
}
|
||||
}
|
||||
|
||||
_generateFormattedMessage(notification, token, emoji, status) {
|
||||
let messageText = `${emoji} *Claude Task ${status}*\n`;
|
||||
messageText += `*Project:* ${notification.project || 'Unknown'}\n`;
|
||||
messageText += `*Token:* \`${token}\`\n\n`;
|
||||
|
||||
// Add user question if available (limited length)
|
||||
if (notification.metadata?.userQuestion) {
|
||||
const question = notification.metadata.userQuestion.substring(0, 150);
|
||||
messageText += `📝 *Question:* ${this._escapeMarkdown(question)}${question.length < notification.metadata.userQuestion.length ? '...' : ''}\n\n`;
|
||||
}
|
||||
|
||||
messageText += `💬 *To send a new command:*\n`;
|
||||
messageText += `Reply with: \`/cmd ${token} <your command>\`\n`;
|
||||
messageText += `Example: \`/cmd ${token} Please analyze this code\``;
|
||||
|
||||
// Add Claude response if available (limited length)
|
||||
if (notification.metadata?.claudeResponse) {
|
||||
const maxResponseLength = 3000 - messageText.length - 200; // Reserve space for instructions
|
||||
let response = notification.metadata.claudeResponse;
|
||||
|
||||
if (response.length > maxResponseLength) {
|
||||
response = response.substring(0, maxResponseLength - 10) + '...';
|
||||
}
|
||||
|
||||
messageText += `🤖 *Response:*\n${this._escapeMarkdown(response)}\n\n`;
|
||||
}
|
||||
|
||||
messageText += `💬 Use: \`/cmd ${token} <command>\``;
|
||||
return messageText;
|
||||
}
|
||||
|
||||
_generatePlainTextMessage(notification, token, emoji, status) {
|
||||
let messageText = `${emoji} Claude Task ${status}\n`;
|
||||
messageText += `Project: ${notification.project || 'Unknown'}\n`;
|
||||
messageText += `Token: ${token}\n\n`;
|
||||
|
||||
// Add user question (plain text, limited)
|
||||
if (notification.metadata?.userQuestion) {
|
||||
const question = this._createSafeText(notification.metadata.userQuestion.substring(0, 150));
|
||||
messageText += `Question: ${question}${question.length < notification.metadata.userQuestion.length ? '...' : ''}\n\n`;
|
||||
}
|
||||
|
||||
// Add Claude response (plain text, limited)
|
||||
if (notification.metadata?.claudeResponse) {
|
||||
const maxResponseLength = 3000 - messageText.length - 100;
|
||||
let response = this._createSafeText(notification.metadata.claudeResponse);
|
||||
|
||||
if (response.length > maxResponseLength) {
|
||||
response = response.substring(0, maxResponseLength - 10) + '...';
|
||||
}
|
||||
|
||||
messageText += `Response: ${response}\n\n`;
|
||||
}
|
||||
|
||||
messageText += `Use: /cmd ${token} <command>`;
|
||||
return messageText;
|
||||
}
|
||||
|
||||
_generateMinimalMessage(notification, token, emoji, status) {
|
||||
return `${emoji} Claude Task ${status}\nToken: ${token}\nUse: /cmd ${token} <command>`;
|
||||
}
|
||||
|
||||
async _createSession(sessionId, notification, token) {
|
||||
const session = {
|
||||
id: sessionId,
|
||||
|
|
|
|||
|
|
@ -817,5 +817,95 @@
|
|||
"sessionId": "dbd1f477-0550-463b-b147-fcdf78720177",
|
||||
"tmuxSession": "claude-session",
|
||||
"description": "completed - ecllipse"
|
||||
},
|
||||
"IS1F9FN9": {
|
||||
"type": "pty",
|
||||
"createdAt": 1756991169,
|
||||
"expiresAt": 1757077569,
|
||||
"cwd": "/home/lsamc/.local/src/Claude-Code-Remote",
|
||||
"sessionId": "2fa9255d-eb9a-4b37-8852-8204d5730d42",
|
||||
"tmuxSession": "claude-session",
|
||||
"description": "completed - Claude-Code-Remote"
|
||||
},
|
||||
"CJRIHOH9": {
|
||||
"type": "pty",
|
||||
"createdAt": 1756991395,
|
||||
"expiresAt": 1757077795,
|
||||
"cwd": "/home/lsamc/develop/ecllipse",
|
||||
"sessionId": "c5d96613-00de-459c-a8f0-52f020d135fc",
|
||||
"tmuxSession": "claude-session",
|
||||
"description": "completed - ecllipse"
|
||||
},
|
||||
"19318YCF": {
|
||||
"type": "pty",
|
||||
"createdAt": 1756991584,
|
||||
"expiresAt": 1757077984,
|
||||
"cwd": "/home/lsamc/develop/ecllipse",
|
||||
"sessionId": "ffba11b1-0aaf-4639-ba4f-6db27249ae22",
|
||||
"tmuxSession": "claude-session",
|
||||
"description": "completed - ecllipse"
|
||||
},
|
||||
"KTP2NLKA": {
|
||||
"type": "pty",
|
||||
"createdAt": 1756991689,
|
||||
"expiresAt": 1757078089,
|
||||
"cwd": "/home/lsamc/develop/ecllipse",
|
||||
"sessionId": "c4b49e6a-c4ca-446a-b28c-09863478c9fc",
|
||||
"tmuxSession": "claude-session",
|
||||
"description": "completed - ecllipse"
|
||||
},
|
||||
"3HB36PXA": {
|
||||
"type": "pty",
|
||||
"createdAt": 1756991822,
|
||||
"expiresAt": 1757078222,
|
||||
"cwd": "/home/lsamc/develop/ecllipse",
|
||||
"sessionId": "9a14ee0e-cf2d-44f5-bec8-548853fc97e1",
|
||||
"tmuxSession": "claude-session",
|
||||
"description": "completed - ecllipse"
|
||||
},
|
||||
"WLR6CVMN": {
|
||||
"type": "pty",
|
||||
"createdAt": 1756991860,
|
||||
"expiresAt": 1757078260,
|
||||
"cwd": "/home/lsamc/.local/src/Claude-Code-Remote",
|
||||
"sessionId": "22cd07f1-34c2-4f58-b470-d7e7d235a92b",
|
||||
"tmuxSession": "claude-session",
|
||||
"description": "completed - Claude-Code-Remote"
|
||||
},
|
||||
"634ZIJ55": {
|
||||
"type": "pty",
|
||||
"createdAt": 1756991894,
|
||||
"expiresAt": 1757078294,
|
||||
"cwd": "/home/lsamc/develop/ecllipse",
|
||||
"sessionId": "7016be36-709a-48c5-8f64-2589aae4e5e9",
|
||||
"tmuxSession": "claude-session",
|
||||
"description": "completed - ecllipse"
|
||||
},
|
||||
"HG4Z82VG": {
|
||||
"type": "pty",
|
||||
"createdAt": 1756991984,
|
||||
"expiresAt": 1757078384,
|
||||
"cwd": "/home/lsamc/develop/ecllipse",
|
||||
"sessionId": "c42a911c-2b47-4b41-8280-c62889ab2384",
|
||||
"tmuxSession": "claude-session",
|
||||
"description": "completed - ecllipse"
|
||||
},
|
||||
"OIO9DPTN": {
|
||||
"type": "pty",
|
||||
"createdAt": 1756992035,
|
||||
"expiresAt": 1757078435,
|
||||
"cwd": "/home/lsamc/develop/ecllipse",
|
||||
"sessionId": "e29d64f2-19f5-4e5b-92c8-6bd1b766bc0d",
|
||||
"tmuxSession": "claude-session",
|
||||
"description": "completed - ecllipse"
|
||||
},
|
||||
"PWB2DEYR": {
|
||||
"type": "pty",
|
||||
"createdAt": 1756992167,
|
||||
"expiresAt": 1757078567,
|
||||
"cwd": "/home/lsamc/develop/ecllipse",
|
||||
"sessionId": "197cd53a-4a64-42a9-8262-8e3b429f08b8",
|
||||
"tmuxSession": "claude-session",
|
||||
"description": "completed - ecllipse"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Test script for extractConversation function fix
|
||||
* Tests the improved response detection logic
|
||||
*/
|
||||
|
||||
const TmuxMonitor = require('./src/utils/tmux-monitor');
|
||||
|
||||
// Create test tmux buffer content that mimics actual Claude Code output
|
||||
const testBuffer1 = `
|
||||
Welcome to Claude Code
|
||||
? for shortcuts
|
||||
───────────────────────────
|
||||
|
||||
> what does this project do?
|
||||
|
||||
I'll help you understand what this project does. Let me analyze the codebase structure first.
|
||||
|
||||
<function_calls>
|
||||
<invoke name="Read">
|
||||
<parameter name="file_path">/path/to/file.js
|
||||
Loading…
Reference in New Issue