faster smaller

This commit is contained in:
Andrey Kondratev
2025-11-09 18:48:57 +05:00
parent ca27a2b3f0
commit 6db48b16a7
11 changed files with 470 additions and 76 deletions

View File

@@ -40,7 +40,27 @@ export class QuixoticBot {
private db: Database;
constructor(token: string, webAppUrl: string) {
this.bot = new TelegramBot(token, { polling: true });
// Validate token format
if (!token || token.length < 40 || token === 'your_telegram_bot_token_here') {
throw new Error('Invalid or placeholder TELEGRAM_BOT_TOKEN provided');
}
// Use webhook in production, polling in development
const useWebhook = process.env.NODE_ENV === 'production' && process.env.WEBHOOK_URL;
if (useWebhook) {
console.log('🌐 Using webhook mode for production');
this.bot = new TelegramBot(token, {
webHook: {
port: 8443,
host: '0.0.0.0'
}
});
} else {
console.log('🔄 Using polling mode for development');
this.bot = new TelegramBot(token, { polling: true });
}
this.webAppUrl = webAppUrl;
this.db = new Database();
this.init();
@@ -257,6 +277,7 @@ export class QuixoticBot {
private async sendAudioFileInternal(chatId: number, audioUrlOrPath: string, title: string, performer?: string, thumbnail?: string): Promise<void> {
try {
console.log(`📤 Sending: ${title} to chat ${chatId}`);
console.log(`📂 File source: ${audioUrlOrPath}`);
// Check if it's a URL or local file path
const isUrl = audioUrlOrPath.startsWith('http');
@@ -267,68 +288,86 @@ export class QuixoticBot {
const urlParts = audioUrlOrPath.split('/');
const filename = urlParts[urlParts.length - 1];
filePath = require('path').join(process.cwd(), 'downloads', filename);
console.log(`📂 Converted URL to local path: ${filePath}`);
}
// Generate custom filename for display
const safeTitle = (title || '').replace(/[^\w\s-]/g, '').replace(/\s+/g, '_').substring(0, 30);
const safePerformer = (performer || '').replace(/[^\w\s-]/g, '').replace(/\s+/g, '_').substring(0, 20);
const customFilename = safePerformer ? `${safePerformer} - ${safeTitle}` : `${safeTitle}`;
const fs = require('fs');
// Try sending as audio with custom filename
// Check if file exists
if (!fs.existsSync(filePath)) {
console.error(`❌ File not found: ${filePath}`);
throw new Error('File not found: ' + filePath);
}
// Get file stats for debugging
const stats = fs.statSync(filePath);
console.log(`📊 File size: ${(stats.size / 1024 / 1024).toFixed(2)} MB`);
// Generate custom filename for display
const safeTitle = (title || 'audio').replace(/[^\w\s-]/g, '').replace(/\s+/g, '_').substring(0, 30);
const safePerformer = (performer || '').replace(/[^\w\s-]/g, '').replace(/\s+/g, '_').substring(0, 20);
const customFilename = safePerformer ? `${safePerformer} - ${safeTitle}.mp3` : `${safeTitle}.mp3`;
console.log(`📝 Sending as: ${customFilename}`);
// Send file using stream (better for large files)
const fileStream = fs.createReadStream(filePath);
// Try sending as audio with metadata
try {
const fs = require('fs');
// Check if file exists
if (!fs.existsSync(filePath)) {
throw new Error('File not found: ' + filePath);
}
await this.bot.sendAudio(chatId, filePath, {
await this.bot.sendAudio(chatId, fileStream, {
title: title,
performer: performer,
performer: performer || 'Unknown Artist',
caption: undefined,
thumbnail: thumbnail,
thumbnail: undefined, // Thumbnail requires special handling
parse_mode: undefined
}, {
filename: customFilename,
contentType: 'audio/mpeg'
});
console.log(`✅ Audio sent: ${title}`);
console.log(`✅ Audio sent successfully: ${title}`);
return;
} catch (error: any) {
console.log('Audio send failed, trying as document...', error.message);
console.error('Audio send failed:', error.message);
console.error('Error code:', error.code);
// Fallback: try as document with custom filename
// Fallback: try as document
try {
await this.bot.sendDocument(chatId, filePath, {
caption: undefined,
console.log('🔄 Retrying as document...');
const docStream = fs.createReadStream(filePath);
await this.bot.sendDocument(chatId, docStream, {
caption: `🎵 ${title}\n👤 ${performer || 'Unknown Artist'}`,
parse_mode: undefined
}, {
filename: customFilename,
contentType: 'audio/mpeg'
});
console.log(`✅ Document sent: ${title}`);
console.log(`✅ Document sent successfully: ${title}`);
return;
} catch (documentError: any) {
console.error('❌ Document send also failed:', documentError.message);
throw documentError;
}
}
} catch (error: any) {
console.error('❌ Send failed:', error.message);
console.error('❌ Send failed completely:', error.message);
console.error('Full error:', error);
// Send fallback with link if it was a URL
// Send error message to user
try {
const message = audioUrlOrPath.startsWith('http')
? `Не удалось отправить файл.\n🎵 ${title}\n🔗 ${audioUrlOrPath}`
: `Не удалось отправить файл: ${title}`;
await this.bot.sendMessage(chatId, message);
await this.bot.sendMessage(chatId,
`Не удалось отправить файл.\n🎵 ${title}\n\опробуйте другой трек.`
);
} catch {
// Silent fail
console.error('❌ Could not even send error message');
}
// Re-throw to trigger unhandled rejection handler
throw error;
}
}