const axios = require('axios'); const fs = require('fs'); const path = require('path'); const { db } = require('../database/db'); const logger = require('./logger'); const parseM3U = async (source, playlistId, isFile = false) => { try { let content; if (isFile) { content = fs.readFileSync(source, 'utf8'); } else { const response = await axios.get(source, { timeout: 30000 }); content = response.data; } const lines = content.split('\n').map(line => line.trim()); const channels = []; for (let i = 0; i < lines.length; i++) { if (lines[i].startsWith('#EXTINF:')) { const info = lines[i]; const url = lines[i + 1]; if (!url || url.startsWith('#')) continue; const nameMatch = info.match(/,(.+)$/); const name = nameMatch ? nameMatch[1].trim() : 'Unknown'; const tvgIdMatch = info.match(/tvg-id="([^"]*)"/); const tvgNameMatch = info.match(/tvg-name="([^"]*)"/); const tvgLogoMatch = info.match(/tvg-logo="([^"]*)"/); const groupTitleMatch = info.match(/group-title="([^"]*)"/); const languageMatch = info.match(/tvg-language="([^"]*)"/); const countryMatch = info.match(/tvg-country="([^"]*)"/); const isRadio = info.toLowerCase().includes('radio') || groupTitleMatch?.[1]?.toLowerCase().includes('radio') || url.toLowerCase().includes('radio'); channels.push({ playlistId, name, url, logo: tvgLogoMatch ? tvgLogoMatch[1] : null, groupName: groupTitleMatch ? groupTitleMatch[1] : 'Uncategorized', tvgId: tvgIdMatch ? tvgIdMatch[1] : null, tvgName: tvgNameMatch ? tvgNameMatch[1] : null, language: languageMatch ? languageMatch[1] : null, country: countryMatch ? countryMatch[1] : null, isRadio: isRadio ? 1 : 0 }); i++; // Skip the URL line } } // Insert channels in batches const batchSize = 100; for (let i = 0; i < channels.length; i += batchSize) { const batch = channels.slice(i, i + batchSize); const stmt = db.prepare(` INSERT INTO channels (playlist_id, name, url, logo, group_name, tvg_id, tvg_name, language, country, is_radio) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `); for (const channel of batch) { stmt.run( channel.playlistId, channel.name, channel.url, channel.logo, channel.groupName, channel.tvgId, channel.tvgName, channel.language, channel.country, channel.isRadio ); } stmt.finalize(); } logger.info(`Parsed ${channels.length} channels for playlist ${playlistId}`); return channels.length; } catch (error) { logger.error('M3U parsing error:', error); throw error; } }; module.exports = { parseM3U };