faster smaller
This commit is contained in:
99
src/bot.ts
99
src/bot.ts
@@ -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\nПопробуйте другой трек.`
|
||||
);
|
||||
} catch {
|
||||
// Silent fail
|
||||
console.error('❌ Could not even send error message');
|
||||
}
|
||||
|
||||
// Re-throw to trigger unhandled rejection handler
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user