Mystique/.forgejo/scripts/cultural-groups.js
2025-02-01 00:19:37 +00:00

188 lines
No EOL
6 KiB
JavaScript

const fs = require('fs');
const path = require('path');
// Define cultural groups by country
const culturalGroups = {
anglosphere: [
'united kingdom', 'uk', 'britain', 'england', 'scotland', 'wales', 'northern ireland',
'united states', 'usa', 'america', 'canada', 'australia', 'new zealand', 'ireland'
],
francophone: [
'france', 'belgium', 'switzerland', 'quebec', 'monaco',
'luxembourg', 'haiti', 'ivory coast', 'senegal', 'cameroon'
],
hispanic: [
'spain', 'mexico', 'argentina', 'chile', 'colombia', 'peru',
'venezuela', 'ecuador', 'guatemala', 'cuba', 'dominican republic',
'honduras', 'el salvador', 'nicaragua', 'costa rica', 'panama'
],
lusophone: [
'portugal', 'brazil', 'angola', 'mozambique',
'cape verde', 'guinea-bissau', 'sao tome and principe'
],
arabic: [
'saudi arabia', 'egypt', 'uae', 'united arab emirates', 'qatar',
'kuwait', 'oman', 'bahrain', 'yemen', 'iraq', 'syria',
'jordan', 'lebanon', 'palestine', 'libya', 'tunisia',
'algeria', 'morocco', 'sudan'
],
germanosphere: [
'germany', 'austria', 'switzerland', 'luxembourg', 'liechtenstein'
],
slavic: [
'russia', 'ukraine', 'belarus', 'poland', 'czech republic',
'slovakia', 'serbia', 'croatia', 'bosnia', 'montenegro',
'slovenia', 'bulgaria', 'north macedonia'
],
sinosphere: [
'china', 'hong kong', 'taiwan', 'singapore', 'macau'
],
indosphere: [
'india', 'pakistan', 'bangladesh', 'nepal', 'sri lanka',
'bhutan', 'maldives'
],
turkic: [
'turkey', 'azerbaijan', 'uzbekistan', 'kazakhstan',
'kyrgyzstan', 'turkmenistan'
],
nordic: [
'sweden', 'norway', 'denmark', 'finland', 'iceland',
'faroe islands', 'greenland'
],
baltic: [
'estonia', 'latvia', 'lithuania'
],
hellenic: [
'greece', 'cyprus'
],
benelux: [
'netherlands', 'belgium', 'luxembourg'
],
persian: [
'iran', 'afghanistan', 'tajikistan'
],
malaysphere: [
'malaysia', 'brunei', 'indonesia'
],
korean: [
'south korea', 'korea', 'north korea'
],
japanese: [
'japan'
],
vietnamese: [
'vietnam'
],
thai: [
'thailand'
]
};
function getCulturalGroup(channelInfo) {
// Look specifically for group-title (country information)
const groupMatch = channelInfo.match(/group-title="([^"]*)"/) || [];
const groupTitle = (groupMatch[1] || '').toLowerCase();
// Check if the country belongs to any cultural group
for (const [group, countries] of Object.entries(culturalGroups)) {
if (countries.some(country => groupTitle.includes(country))) {
return group;
}
}
return null; // Return null instead of 'other' for non-matching channels
}
function splitByCulturalGroup(filePath) {
const content = fs.readFileSync(filePath, 'utf8');
const lines = content.split('\n');
// Create cultural groups directory
const groupsDir = path.join(path.dirname(filePath), 'cultural-groups');
if (!fs.existsSync(groupsDir)) {
fs.mkdirSync(groupsDir);
}
// Get existing cultural group files
const existingFiles = fs.readdirSync(groupsDir)
.filter(file => file.endsWith('.m3u'))
.map(file => file.toLowerCase());
const groups = {};
let currentExtinf = null;
// Verify M3U header
const header = lines[0];
if (!header.startsWith('#EXTM3U')) {
throw new Error('Invalid M3U file: Missing #EXTM3U header');
}
// Process lines
lines.forEach(line => {
line = line.trim();
if (!line) return;
if (line.startsWith('#EXTINF')) {
currentExtinf = line;
const culturalGroup = getCulturalGroup(line);
// Only add to a group if there's a match
if (culturalGroup) {
if (!groups[culturalGroup]) {
groups[culturalGroup] = ['#EXTM3U'];
}
groups[culturalGroup].push(line);
}
} else if (currentExtinf && !line.startsWith('#')) {
const culturalGroup = getCulturalGroup(currentExtinf);
// Only add the URL line if the channel belonged to a group
if (culturalGroup) {
groups[culturalGroup].push(line);
}
currentExtinf = null;
}
});
// Get list of current cultural group files
const currentGroupFiles = Object.keys(groups).map(groupTitle =>
`${groupTitle.toLowerCase()}.m3u`
);
// Remove obsolete files
existingFiles.forEach(existingFile => {
if (!currentGroupFiles.includes(existingFile)) {
const fileToRemove = path.join(groupsDir, existingFile);
fs.unlinkSync(fileToRemove);
console.log(`Removed obsolete cultural group playlist: ${existingFile}`);
}
});
// Write cultural group files
Object.entries(groups).forEach(([groupTitle, groupLines]) => {
const groupFilePath = path.join(groupsDir, `${groupTitle.toLowerCase()}.m3u`);
fs.writeFileSync(groupFilePath, groupLines.join('\n') + '\n');
console.log(`Created/updated cultural group playlist: ${groupFilePath}`);
});
// Generate summary
const summary = Object.entries(groups).map(([group, lines]) => {
const channelCount = (lines.length - 1) / 2; // Subtract header and divide by 2 (EXTINF + URL)
return `${group}: ${channelCount} channels`;
});
console.log('\nCultural group split summary:');
console.log(summary.join('\n'));
}
const filePath = process.argv[2];
if (!filePath) {
console.error('Please provide the path to the M3U file');
process.exit(1);
}
try {
splitByCulturalGroup(filePath);
} catch (error) {
console.error('Error splitting M3U file:', error.message);
process.exit(1);
}