// src/index.ts export default { async fetch(request, env) { const url = new URL(request.url); // Handle webhook setup if (url.pathname === '/setWebhook') { return await setWebhook(env); } // Handle Telegram webhook if (request.method === 'POST') { try { const update = await request.json(); await handleTelegramUpdate(update, env); return new Response('OK'); } catch (error) { console.error('Error handling update:', error); return new Response('Error', { status: 500 }); } } return new Response('Telegram AI Bot is running!'); } }; async function setWebhook(env) { const webhookUrl = `https://${env.WORKER_DOMAIN}`; const telegramUrl = `https://api.telegram.org/bot${env.TELEGRAM_BOT_TOKEN}/setWebhook`; try { const response = await fetch(telegramUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ url: webhookUrl }) }); const result = await response.json(); return new Response(JSON.stringify(result), { headers: { 'Content-Type': 'application/json' } }); } catch (error) { return new Response(JSON.stringify({ error: error.message }), { status: 500, headers: { 'Content-Type': 'application/json' } }); } } async function handleTelegramUpdate(update, env) { if (update.message && update.message.text) { const chatId = update.message.chat.id; const userMessage = update.message.text; const userName = update.message.from.first_name || 'User'; if (userMessage === '/start') { await sendTelegramMessage( chatId, `Hello ${userName}! 👋\n\nI'm an AI assistant powered by Cloudflare AI. Send me any message and I'll respond using AI!\n\nJust type your question or message.`, env ); return; } if (userMessage === '/help') { await sendTelegramMessage( chatId, `🤖 *AI Bot Help*\n\n` + `• Send me any text message and I'll respond with AI\n` + `• Ask me questions, request explanations, or just chat\n` + `• Use /start to see welcome message\n` + `• Use /help to see this help\n\n` + `Powered by Cloudflare AI`, env, 'Markdown' ); return; } await sendTypingAction(chatId, env); try { const aiResponse = await env.AI.run('@cf/zai-org/glm-5.2', { messages: [ { role: 'system', content: `You are a helpful AI assistant in a Telegram chat. You must give short, simple, and direct answers. The user's name is ${userName}.` }, { role: 'user', content: userMessage } ] }); console.log('AI Raw Response:', JSON.stringify(aiResponse)); let responseText = extractTextFromAIResponse(aiResponse); // If we still can't parse it, send the raw JSON for debugging if (!responseText) { const rawJson = JSON.stringify(aiResponse, null, 2); responseText = `⚠️ Could not parse AI response. Raw format:\n\`\`\`\n${rawJson.slice(0, 3500)}\n\`\`\``; } await sendTelegramMessage(chatId, responseText, env); } catch (error) { console.error('AI Error:', error); await sendTelegramMessage( chatId, '🚫 Error calling AI. Please try again later.\n' + error.message, env ); } } } function extractTextFromAIResponse(aiResponse) { if (!aiResponse) return null; // If it's already a string if (typeof aiResponse === 'string') { return aiResponse; } // Format 1: Standard Workers AI { response: "..." } if (aiResponse.response) { return aiResponse.response; } // Format 2: OpenAI-style chat completions { choices: [{ message: { content: "..." } }] } if (aiResponse.choices && Array.isArray(aiResponse.choices) && aiResponse.choices.length > 0) { const choice = aiResponse.choices[0]; if (choice.message) { if (choice.message.content) return choice.message.content; if (choice.message.text) return choice.message.text; } if (choice.text) return choice.text; } // Format 3: Responses API format { output: [{ role: "assistant", content: [...] }] } if (aiResponse.output && Array.isArray(aiResponse.output)) { const assistantMsg = aiResponse.output.find(item => item.role === 'assistant'); if (assistantMsg) { if (Array.isArray(assistantMsg.content)) { // Try output_text type const textItem = assistantMsg.content.find(c => c.type === 'output_text' && c.text); if (textItem) return textItem.text; // Try text type const textItem2 = assistantMsg.content.find(c => c.type === 'text' && c.text); if (textItem2) return textItem2.text; // Try any item with text const anyText = assistantMsg.content.find(c => c.text); if (anyText) return anyText.text; } else if (typeof assistantMsg.content === 'string') { return assistantMsg.content; } } } // Format 4: Direct array of messages (some models return this) if (Array.isArray(aiResponse)) { const assistantMsg = aiResponse.find(item => item.role === 'assistant'); if (assistantMsg) { if (Array.isArray(assistantMsg.content)) { const textItem = assistantMsg.content.find(c => c.type === 'output_text' && c.text); if (textItem) return textItem.text; const textItem2 = assistantMsg.content.find(c => c.text); if (textItem2) return textItem2.text; } else if (typeof assistantMsg.content === 'string') { return assistantMsg.content; } else if (assistantMsg.text) { return assistantMsg.text; } } } // Format 5: Nested result { result: { response: "..." } } or { result: "..." } if (aiResponse.result) { if (aiResponse.result.response) return aiResponse.result.response; if (typeof aiResponse.result === 'string') return aiResponse.result; // Recursively try to parse nested result const nested = extractTextFromAIResponse(aiResponse.result); if (nested) return nested; } // Format 6: Direct text/content fields if (aiResponse.text) return aiResponse.text; if (aiResponse.content && typeof aiResponse.content === 'string') return aiResponse.content; // Format 7: If it has a single key that might be the response const keys = Object.keys(aiResponse); if (keys.length === 1 && typeof aiResponse[keys[0]] === 'string') { return aiResponse[keys[0]]; } return null; } async function sendTelegramMessage(chatId, text, env, parseMode = null) { const telegramUrl = `https://api.telegram.org/bot${env.TELEGRAM_BOT_TOKEN}/sendMessage`; const payload = { chat_id: chatId, text: text.slice(0, 4096), // Telegram message limit }; if (parseMode) { payload.parse_mode = parseMode; } try { const response = await fetch(telegramUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) { console.error('Telegram API error:', await response.text()); } } catch (error) { console.error('Error sending message:', error); } } async function sendTypingAction(chatId, env) { const telegramUrl = `https://api.telegram.org/bot${env.TELEGRAM_BOT_TOKEN}/sendChatAction`; try { await fetch(telegramUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chat_id: chatId, action: 'typing' }) }); } catch (error) { console.error('Error sending typing action:', error); } }