Refactor: Implement DashboardLayout, fix mobile nav, and resolve scroll issues
This commit is contained in:
129
scripts/bot.js
129
scripts/bot.js
@@ -1,21 +1,79 @@
|
||||
const TelegramBot = require('node-telegram-bot-api');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
require('dotenv').config({ path: path.join(__dirname, '..', '.env') });
|
||||
|
||||
// 1. Load Settings
|
||||
const SETTINGS_FILE = path.join(__dirname, '..', 'server-settings.json');
|
||||
const DB_FILE = path.join(__dirname, '..', 'data', 'db.json');
|
||||
|
||||
console.log(`📂 DB Path resolved to: ${DB_FILE}`);
|
||||
|
||||
// --- Database Helpers ---
|
||||
function getDatabase() {
|
||||
if (!fs.existsSync(DB_FILE)) return null;
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(DB_FILE, 'utf8'));
|
||||
} catch (err) {
|
||||
console.error("❌ Error reading DB:", err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function saveDatabase(data) {
|
||||
try {
|
||||
fs.writeFileSync(DB_FILE, JSON.stringify(data, null, 2));
|
||||
console.log("💾 Database updated successfully.");
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error("❌ Error saving DB:", err);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Action Handlers ---
|
||||
function handleAddIncome(amount, description, category = 'other') {
|
||||
const db = getDatabase();
|
||||
if (!db) return "Error: Database not found.";
|
||||
|
||||
// Ensure incomes array exists
|
||||
if (!db.incomes) db.incomes = [];
|
||||
|
||||
const newIncome = {
|
||||
id: Date.now().toString(), // Simple ID
|
||||
amount: parseFloat(amount),
|
||||
description: description,
|
||||
category: category,
|
||||
date: new Date().toISOString()
|
||||
};
|
||||
|
||||
db.incomes.push(newIncome);
|
||||
|
||||
if (saveDatabase(db)) {
|
||||
return `✅ Ingreso agregado: $${newIncome.amount.toLocaleString()} (${newIncome.description})`;
|
||||
} else {
|
||||
return "❌ Error interno guardando el ingreso.";
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
let settings = {};
|
||||
|
||||
// Try to load from file
|
||||
if (fs.existsSync(SETTINGS_FILE)) {
|
||||
try {
|
||||
settings = JSON.parse(fs.readFileSync(SETTINGS_FILE, 'utf8'));
|
||||
} catch (err) {
|
||||
console.error("❌ Error reading settings:", err);
|
||||
}
|
||||
}
|
||||
|
||||
// Override with Env Vars
|
||||
if (!settings.telegram) settings.telegram = {};
|
||||
if (process.env.TELEGRAM_BOT_TOKEN) settings.telegram.botToken = process.env.TELEGRAM_BOT_TOKEN;
|
||||
if (process.env.TELEGRAM_CHAT_ID) settings.telegram.chatId = process.env.TELEGRAM_CHAT_ID;
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
async function startBot() {
|
||||
@@ -68,6 +126,31 @@ async function startBot() {
|
||||
const model = aiProvider.model || "gpt-3.5-turbo";
|
||||
console.log(`🤖 Asking ${aiProvider.name} (Model: ${model})...`);
|
||||
|
||||
const dbData = getDatabase();
|
||||
const dbString = dbData ? JSON.stringify(dbData) : "No data available.";
|
||||
|
||||
const systemPrompt = `You are a helpful financial assistant called "Finanzas Bot".
|
||||
You have access to the user's financial data (JSON).
|
||||
Current Date: ${new Date().toISOString()}
|
||||
|
||||
CAPABILITIES:
|
||||
1. ANSWER questions about the data.
|
||||
2. ADD INCOMES if the user asks.
|
||||
|
||||
*** IMPORTANT: TO ADD AN INCOME ***
|
||||
If the user wants to add an income, DO NOT reply with text. Instead, reply with a JSON OBJECT strictly in this format:
|
||||
{
|
||||
"action": "add_income",
|
||||
"amount": 150000,
|
||||
"description": "Freelance payment",
|
||||
"category": "freelance"
|
||||
}
|
||||
(Categories: salary, freelance, business, gift, other)
|
||||
|
||||
DATA:
|
||||
${dbString}
|
||||
`;
|
||||
|
||||
const response = await fetch(targetUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@@ -78,11 +161,14 @@ async function startBot() {
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: model,
|
||||
messages: [{ role: "user", content: text }],
|
||||
messages: [
|
||||
{ role: "system", content: systemPrompt },
|
||||
{ role: "user", content: text }
|
||||
],
|
||||
max_tokens: 1000
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
if (!response.ok) {
|
||||
const errText = await response.text();
|
||||
throw new Error(`API Error ${response.status}: ${errText}`);
|
||||
@@ -94,16 +180,33 @@ async function startBot() {
|
||||
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;
|
||||
}
|
||||
|
||||
// Check for JSON Action
|
||||
try {
|
||||
// Try to find JSON block if mixed with text
|
||||
const jsonMatch = reply.match(/\{[\s\S]*\}/);
|
||||
const potentialJson = jsonMatch ? jsonMatch[0] : reply;
|
||||
|
||||
const actionData = JSON.parse(potentialJson);
|
||||
|
||||
if (actionData && actionData.action === 'add_income') {
|
||||
console.log("⚡ Executing Action: add_income");
|
||||
const resultMsg = handleAddIncome(actionData.amount, actionData.description, actionData.category);
|
||||
bot.sendMessage(incomingChatId, resultMsg);
|
||||
return; // Stop here, don't send the raw JSON reply
|
||||
}
|
||||
} catch (e) {
|
||||
// Not a JSON action, standard text reply
|
||||
}
|
||||
|
||||
bot.sendMessage(incomingChatId, reply, { parse_mode: 'Markdown' });
|
||||
|
||||
} catch (error) {
|
||||
|
||||
console.error("❌ AI Error:", error.message);
|
||||
bot.sendMessage(incomingChatId, `❌ Error calling AI: ${error.message}`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user