feat: Implement Telegram Bot and AI Settings
This commit is contained in:
117
scripts/bot.js
Normal file
117
scripts/bot.js
Normal file
@@ -0,0 +1,117 @@
|
||||
const TelegramBot = require('node-telegram-bot-api');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// 1. Load Settings
|
||||
const SETTINGS_FILE = path.join(__dirname, '..', 'server-settings.json');
|
||||
|
||||
function getSettings() {
|
||||
if (!fs.existsSync(SETTINGS_FILE)) {
|
||||
console.error("❌ No configuration file found! Go to /settings in the app first.");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(SETTINGS_FILE, 'utf8'));
|
||||
} catch (err) {
|
||||
console.error("❌ Error reading settings:", err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function startBot() {
|
||||
console.log("🚀 Starting Finance Bot...");
|
||||
|
||||
const settings = getSettings();
|
||||
if (!settings || !settings.telegram?.botToken) {
|
||||
console.error("❌ config or Bot Token missing.");
|
||||
return;
|
||||
}
|
||||
|
||||
const { botToken, chatId } = settings.telegram;
|
||||
const bot = new TelegramBot(botToken, { polling: true });
|
||||
|
||||
console.log(`✅ Bot started! Waiting for messages...`);
|
||||
|
||||
bot.on('message', async (msg) => {
|
||||
const incomingChatId = msg.chat.id.toString();
|
||||
const text = msg.text;
|
||||
|
||||
// Security check: only reply to the configured owner/group
|
||||
if (chatId && incomingChatId !== chatId) {
|
||||
console.warn(`⚠️ Ignoring message from unauthorized chat: ${incomingChatId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!text) return;
|
||||
|
||||
console.log(`📩 Received: "${text}" from ${msg.from.first_name}`);
|
||||
|
||||
// Send typing action
|
||||
bot.sendChatAction(incomingChatId, 'typing');
|
||||
|
||||
// Refresh settings to get latest AI config
|
||||
const currentSettings = getSettings();
|
||||
const aiProvider = currentSettings?.aiProviders?.[0];
|
||||
|
||||
if (!aiProvider || !aiProvider.endpoint || !aiProvider.token) {
|
||||
bot.sendMessage(incomingChatId, "⚠️ No AI provider configured. Please set one up in the app.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Prepare AI Request
|
||||
let targetUrl = aiProvider.endpoint;
|
||||
if (!targetUrl.endsWith('/messages') && !targetUrl.endsWith('/chat/completions')) {
|
||||
targetUrl = targetUrl.endsWith('/') ? `${targetUrl}v1/messages` : `${targetUrl}/v1/messages`;
|
||||
}
|
||||
|
||||
const model = aiProvider.model || "gpt-3.5-turbo";
|
||||
console.log(`🤖 Asking ${aiProvider.name} (Model: ${model})...`);
|
||||
|
||||
const response = await fetch(targetUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${aiProvider.token}`,
|
||||
'x-api-key': aiProvider.token,
|
||||
'anthropic-version': '2023-06-01'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: model,
|
||||
messages: [{ role: "user", content: text }],
|
||||
max_tokens: 1000
|
||||
})
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errText = await response.text();
|
||||
throw new Error(`API Error ${response.status}: ${errText}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
// Handle different response formats (Anthropic vs OpenAI-compatible)
|
||||
let reply = "🤖 No response content.";
|
||||
|
||||
if (data.content && Array.isArray(data.content)) {
|
||||
// Anthropic format: { content: [{ type: 'text', text: '...' }] }
|
||||
reply = data.content.find(c => c.type === 'text')?.text || reply;
|
||||
} else if (data.choices && Array.isArray(data.choices)) {
|
||||
// OpenAI format: { choices: [{ message: { content: '...' } }] }
|
||||
reply = data.choices[0]?.message?.content || reply;
|
||||
}
|
||||
|
||||
bot.sendMessage(incomingChatId, reply, { parse_mode: 'Markdown' });
|
||||
|
||||
} catch (error) {
|
||||
console.error("❌ AI Error:", error.message);
|
||||
bot.sendMessage(incomingChatId, `❌ Error calling AI: ${error.message}`);
|
||||
}
|
||||
});
|
||||
|
||||
bot.on('polling_error', (error) => {
|
||||
console.error("⚠️ Polling Error:", error.code); // E.g., EFATAL if token is wrong
|
||||
});
|
||||
}
|
||||
|
||||
startBot();
|
||||
Reference in New Issue
Block a user