Initial commit

This commit is contained in:
2026-03-23 20:59:26 +01:00
commit 16c95f747b
56 changed files with 21177 additions and 0 deletions

View File

@@ -0,0 +1,227 @@
/**
* Lycostorrent - Admin Parsing Tags
* Gestion des tags de coupure pour le parsing des titres
*/
let currentTags = [];
// Présets de tags
const PRESETS = {
langues: ['MULTi', 'MULTI', 'VOSTFR', 'VOST', 'VFF', 'VFQ', 'VFI', 'FRENCH', 'TRUEFRENCH', 'SUBFRENCH'],
resolutions: ['1080p', '720p', '480p', '2160p', '4K', 'UHD'],
sources: ['WEB', 'WEBRIP', 'WEBDL', 'WEB-DL', 'HDTV', 'BLURAY', 'BDRIP', 'BRRIP', 'DVDRIP', 'HDRip', 'REMUX'],
codecs: ['x264', 'x265', 'HEVC', 'H264', 'H265', 'AV1'],
audio: ['HDR', 'HDR10', 'DV', 'DOLBY', 'ATMOS', 'DTS', 'AC3', 'AAC', 'FLAC', 'TrueHD']
};
// Tags par défaut (copie de tmdb_api.py)
const DEFAULT_TAGS = [
"MULTi", "MULTI", "VOSTFR", "VOST", "VFF", "VFQ", "VFI",
"FRENCH", "TRUEFRENCH", "SUBFRENCH",
"1080p", "720p", "480p", "2160p", "4K", "UHD",
"WEB", "WEBRIP", "WEBDL", "WEB-DL", "HDTV", "BLURAY", "BDRIP", "BRRIP", "DVDRIP", "HDRip", "REMUX",
"x264", "x265", "HEVC", "H264", "H265", "AV1",
"HDR", "HDR10", "DV", "DOLBY", "ATMOS", "DTS", "AC3", "AAC", "FLAC", "TrueHD",
"PROPER", "REPACK"
];
// Initialisation
document.addEventListener('DOMContentLoaded', function() {
loadTags();
setupEventListeners();
});
function setupEventListeners() {
document.getElementById('addTagBtn').addEventListener('click', addNewTag);
document.getElementById('newTagInput').addEventListener('keypress', (e) => {
if (e.key === 'Enter') addNewTag();
});
document.getElementById('saveTagsBtn').addEventListener('click', saveTags);
document.getElementById('resetTagsBtn').addEventListener('click', resetToDefault);
document.getElementById('testParsingBtn').addEventListener('click', testParsing);
document.getElementById('testTitleInput').addEventListener('keypress', (e) => {
if (e.key === 'Enter') testParsing();
});
// Présets
document.querySelectorAll('.preset-btn').forEach(btn => {
btn.addEventListener('click', function() {
addPreset(this.dataset.preset);
});
});
}
// ============================================================
// CHARGEMENT / SAUVEGARDE
// ============================================================
async function loadTags() {
try {
const response = await fetch('/api/admin/parsing-tags');
const data = await response.json();
if (data.success) {
currentTags = data.tags || [];
renderTags();
} else {
showMessage('Erreur lors du chargement des tags', 'error');
}
} catch (error) {
console.error('Erreur:', error);
showMessage('Impossible de charger les tags', 'error');
}
}
async function saveTags() {
try {
const response = await fetch('/api/admin/parsing-tags', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ tags: currentTags })
});
const data = await response.json();
if (data.success) {
showMessage(`${currentTags.length} tags sauvegardés !`, 'success');
} else {
showMessage(data.error || 'Erreur lors de la sauvegarde', 'error');
}
} catch (error) {
console.error('Erreur:', error);
showMessage('Erreur de connexion', 'error');
}
}
function resetToDefault() {
if (confirm('Réinitialiser tous les tags aux valeurs par défaut ?')) {
currentTags = [...DEFAULT_TAGS];
renderTags();
showMessage('Tags réinitialisés (pensez à sauvegarder)', 'info');
}
}
// ============================================================
// GESTION DES TAGS
// ============================================================
function renderTags() {
const container = document.getElementById('tagsList');
if (currentTags.length === 0) {
container.innerHTML = '<p class="no-data">Aucun tag configuré</p>';
return;
}
// Trier alphabétiquement
const sortedTags = [...currentTags].sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
container.innerHTML = sortedTags.map(tag => `
<span class="tag-item-editor">
${escapeHtml(tag)}
<button class="tag-remove" data-tag="${escapeHtml(tag)}" title="Supprimer">×</button>
</span>
`).join('');
// Event listeners pour supprimer
container.querySelectorAll('.tag-remove').forEach(btn => {
btn.addEventListener('click', function() {
removeTag(this.dataset.tag);
});
});
}
function addNewTag() {
const input = document.getElementById('newTagInput');
const tag = input.value.trim();
if (!tag) {
showMessage('Veuillez entrer un tag', 'error');
return;
}
if (currentTags.some(t => t.toLowerCase() === tag.toLowerCase())) {
showMessage('Ce tag existe déjà', 'error');
return;
}
currentTags.push(tag);
renderTags();
input.value = '';
showMessage(`Tag "${tag}" ajouté`, 'success');
}
function removeTag(tag) {
currentTags = currentTags.filter(t => t !== tag);
renderTags();
}
function addPreset(presetName) {
const presetTags = PRESETS[presetName];
if (!presetTags) return;
let added = 0;
presetTags.forEach(tag => {
if (!currentTags.some(t => t.toLowerCase() === tag.toLowerCase())) {
currentTags.push(tag);
added++;
}
});
renderTags();
showMessage(`${added} tags ajoutés depuis le préset "${presetName}"`, 'success');
}
// ============================================================
// TEST DE PARSING
// ============================================================
async function testParsing() {
const input = document.getElementById('testTitleInput');
const title = input.value.trim();
if (!title) {
showMessage('Veuillez entrer un titre à tester', 'error');
return;
}
try {
const response = await fetch('/api/admin/test-parsing', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title })
});
const data = await response.json();
if (data.success) {
document.getElementById('testOriginal').textContent = data.original;
document.getElementById('testCleaned').textContent = data.cleaned;
document.getElementById('testResult').classList.remove('hidden');
} else {
showMessage(data.error || 'Erreur de test', 'error');
}
} catch (error) {
console.error('Erreur:', error);
showMessage('Erreur de connexion', 'error');
}
}
// ============================================================
// UTILITAIRES
// ============================================================
function showMessage(message, type = 'info') {
const messageBox = document.getElementById('messageBox');
messageBox.textContent = message;
messageBox.className = `message-box ${type}`;
messageBox.classList.remove('hidden');
setTimeout(() => messageBox.classList.add('hidden'), 4000);
}
function escapeHtml(text) {
if (!text) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}