94 lines
2.9 KiB
JavaScript
94 lines
2.9 KiB
JavaScript
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 };
|