/*********************************************************************************************
Abrir la web de Playdede y pulsa f12 y "consola" pegáis todo este código y le dais a enter
Aparecerá un nuevo menú a la derecha de tu usuario llamado "Descargar CSV" pulsa en él para ver el menú de descargas
Hasta que no termine un comando no ejecutar el siguiente, cada uno genera un csv diferente.
***********************************************************************************************/
var delimiter_csv = '\t'; // delimitador para el csv: '\t' => tabulacion, ',' => comilla, ';' => punto y coma.
var series = [], pelis = [], capitulos = [], temporadas = [], listas_creadas = [], listas_siguiendo = [];
function getCapitulos() {
return console.log("Capitulos, Nada que exportar: Pendiente de realizar la programación para exportar capitulos.\n");
var r = confirm("Exportar el CSV de Capítulos.\nLa página se quedará congelada mientras se procesa.\nPulsa aceptar para proceder");
if (r == true) {
let capitulos_series_favorites;
let capitulos_series_following;
let capitulos_series_pending;
let capitulos_series_seen;
console.log("Capítulos");
capitulos_series_favorites = parser.parseFromString(getContenido(url_series_favorites), "text/html").querySelectorAll('.media-container');
createData(capitulos_series_favorites, "favorita", "capitulos");
capitulos_series_following = parser.parseFromString(getContenido(url_series_following), "text/html").querySelectorAll('.media-container');
createData(capitulos_series_following, "siguiendo", "capitulos");
capitulos_series_pending = parser.parseFromString(getContenido(url_series_pending), "text/html").querySelectorAll('.media-container');
createData(capitulos_series_pending, "pendiente", "capitulos");
capitulos_series_seen = parser.parseFromString(getContenido(url_series_seen), "text/html").querySelectorAll('.media-container');
createData(capitulos_series_seen, "vista", "capitulos");
createCsvCapitulos(capitulos, name = 'capitulos');
}
}
/// GET PELICULAS
async function getPelis() {
console.log("Películas\n");
showLoading("Exportando películas...");
try {
// Usar Promise.allSettled para que todas se ejecuten aunque alguna falle
const results = await Promise.allSettled([
fetchUserData('movie', 'fav'),
fetchUserData('movie', 'pend'),
fetchUserData('movie', 'vis')
]);
const allPelis = [];
const types = ['favorita', 'pendiente', 'vista'];
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
const pelis = result.value.map(item => ({
name: item.name,
id_thetvbb: item.id_thetvbb,
type: types[index],
}));
allPelis.push(...pelis);
console.log(`${types[index]} procesadas:`, pelis);
} else {
console.error(`Error en ${types[index]}:`, result.reason);
}
});
createCsv(allPelis, 'pelis');
// Ocultar loading cuando todo termine
hideLoading();
// Opcional: Mostrar mensaje de éxito
//alert("CSV de películas exportado correctamente!");
} catch (error) {
console.error('Error general:', error);
}
}
async function getSeries() {
console.log("Series\n");
showLoading("Exportando Series...");
try {
// Usar Promise.allSettled para que todas se ejecuten aunque alguna falle
const results = await Promise.allSettled([
fetchUserData('serie', 'fav'),
fetchUserData('serie', 'sig'),
fetchUserData('serie', 'pend'),
fetchUserData('serie', 'vis')
]);
const allSeries = [];
const types = ['favorita', 'siguiendo', 'pendiente', 'vista'];
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
const series = result.value.map(item => ({
name: item.name,
id_thetvbb: item.id_thetvbb,
type: types[index],
}));
allSeries.push(...series);
console.log(`${types[index]} procesadas:`, series);
} else {
console.error(`Error en ${types[index]}:`, result.reason);
}
});
createCsv(allSeries, 'series');
// Ocultar loading cuando todo termine
hideLoading();
// Opcional: Mostrar mensaje de éxito
//alert("CSV de series exportado correctamente!");
} catch (error) {
console.error('Error general:', error);
}
}
async function getAnimes() {
console.log("Animes\n");
showLoading("Exportando animes...");
try {
// Usar Promise.allSettled para que todas se ejecuten aunque alguna falle
const results = await Promise.allSettled([
fetchUserData('anime', 'fav'),
fetchUserData('anime', 'sig'),
fetchUserData('anime', 'pend'),
fetchUserData('anime', 'vis')
]);
const allAnimes = [];
const types = ['favorita', 'siguiendo', 'pendiente', 'vista'];
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
const animes = result.value.map(item => ({
name: item.name,
id_thetvbb: item.id_thetvbb,
type: types[index],
}));
allAnimes.push(...animes);
console.log(`${types[index]} procesadas:`, animes);
} else {
console.error(`Error en ${types[index]}:`, result.reason);
}
});
createCsv(allAnimes, 'animes');
// Ocultar loading cuando todo termine
hideLoading();
// Opcional: Mostrar mensaje de éxito
//alert("CSV de animes exportado correctamente!");
} catch (error) {
console.error('Error general:', error);
}
}
//// GET LISTAS
async function getListas() {
console.log("Listas\n");
return console.log("Listas, Nada que exportar: Pendiente de realizar la programación para exportar listas.\n");
try {
// Usar Promise.allSettled para que todas se ejecuten aunque alguna falle
const results = await Promise.allSettled([
fetchUserData('listas', 'publ'),
fetchUserData('listas', 'priv'),
fetchUserData('listas', 'fav')
]);
const allPelis = [];
const types = ['publica', 'privada', 'favorita'];
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
const pelis = result.value.map(item => ({
name: item.name,
id_thetvbb: item.id_thetvbb,
type: types[index],
}));
allPelis.push(...pelis);
console.log(`${types[index]} procesadas:`, pelis);
} else {
console.error(`Error en ${types[index]}:`, result.reason);
}
});
createCsv(allPelis, 'pelis');
} catch (error) {
console.error('Error general:', error);
}
}
function parseDataFromHTML(htmlString) {
const parser = new DOMParser();
const doc = parser.parseFromString(htmlString, 'text/html');
const articles = doc.querySelectorAll('article.item');
const movies = [];
articles.forEach(article => {
// Extraer el nombre (dentro de h3 en la clase data)
const nameElement = article.querySelector('.data h3');
const name = nameElement ? nameElement.textContent.trim() : '';
// Extraer el id_thetvbb del href - buscando después del último '_'
const linkElement = article.querySelector('a[href]');
let id_thetvbb = '';
if (linkElement) {
const href = linkElement.getAttribute('href');
// Buscar lo que está después del último '_'
const lastUnderscoreIndex = href.lastIndexOf('_');
if (lastUnderscoreIndex !== -1) {
id_thetvbb = href.substring(lastUnderscoreIndex + 1);
// Si hay una barra después, la removemos
if (id_thetvbb.includes('/')) {
id_thetvbb = id_thetvbb.split('/')[0];
}
}
}
// Extraer otros datos útiles que podrías necesitar
const posterElement = article.querySelector('.poster img');
const posterUrl = posterElement ? posterElement.getAttribute('src') : '';
const dateElement = article.querySelector('.data p');
const date = dateElement ? dateElement.textContent.trim() : '';
const genresElement = article.querySelector('.data span');
const genres = genresElement ? genresElement.textContent.trim() : '';
const ratingElement = article.querySelector('.nota span');
let rating = '';
if (ratingElement) {
const ratingText = ratingElement.textContent.trim();
const ratingMatch = ratingText.match(/(\d+\.?\d*)/);
rating = ratingMatch ? ratingMatch[1] : '';
}
// Solo agregar si tenemos al menos el nombre
if (name) {
movies.push({
name: name,
id_thetvbb: id_thetvbb,
poster_url: posterUrl,
release_date: date,
genres: genres,
rating: rating
});
}
});
return movies;
}
function extractUsername() {
// Buscar directamente en el DOM global
let username = '';
const linkElement = document.querySelector('.uPerfil a[href]');
if (linkElement) {
const href = linkElement.getAttribute('href');
const match = href.match(/\/user\/([^\/]+)/);
if (match && match[1]) {
username = match[1];
}
}
return username;
}
async function fetchUserData(tipo, subtipo) {
const formData = new FormData();
const usuario = extractUsername();
const data = {
'_method': 'items',
'page': '1',
'type': tipo,
'username': usuario,
'subtype': subtipo,
'async': 'true',
'ajaxName': 'profile',
'slug': 'user',
'identifier': ''
};
// Agregar datos al FormData
Object.entries(data).forEach(([key, value]) => {
formData.append(key, value);
});
const headers = {
"accept": "*/*",
"accept-language": "es-ES,es;q=0.9",
"cache-control": "no-cache",
"pragma": "no-cache",
"priority": "u=1, i",
"sec-ch-ua": "\"Google Chrome\";v=\"141\", \"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"141\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\"",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"sec-gpc": "1"
};
try {
const response = await fetch("https://playdede.club/ajax.php", {
method: "POST",
mode: "cors",
credentials: "include",
headers: headers,
body: formData
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
// Parsear el HTML de la respuesta
const resultparse = parseDataFromHTML(result.render);
return resultparse;
} catch (error) {
console.error('Error fetching data:', error);
throw error;
}
}
function createCsv(data, fileName) {
let csvHeader = ["Title", "IdThetvbb", "Type"];
let csv2 = [];
data.forEach(element => {
let csv_temp =
{
"name": element.name,
"id_thetvbb": element.id_thetvbb,
"type": element.type,
}
csv2.push(csv_temp);
});
console.log("CSV Series " + fileName + "\n");
export_csv(csvHeader, csv2, delimiter_csv, fileName)
}
function createCsvCapitulos(data, fileName) {
let csvHeader = ["Title", "Episode", "Name", "IdImdb", "IdThetvbb"];
let csv2 = [];
data.forEach(element => {
let csv_temp =
{
"name": element.name,
"episode": element.episode,
"episode_name": element.episode_name,
"id_imdb": element.id_imdb,
"id_thetvbb": element.id_thetvbb,
}
csv2.push(csv_temp);
});
console.log("CSV Capitulos TERMINADO\n");
export_csv(csvHeader, csv2, delimiter_csv, fileName)
}
function createCsvListas(data, fileName) {
let csvHeader = ["Id", "ListTitle", "Username", "Title", "Type", "IdImdb", "IdThetvbb"];
let csv2 = [];
data.forEach(element => {
let csv_temp =
{
"id": element.id,
"listname": element.listname,
"username": element.username,
"name": element.name,
"type2": element.type2,
"id_imdb": element.id_imdb,
"id_thetvbb": element.id_thetvbb,
}
csv2.push(csv_temp);
});
export_csv(csvHeader, csv2, delimiter_csv, fileName);
}
function export_csv(arrayHeader, arrayData, delimiter, fileName) {
let header = arrayHeader.join(delimiter) + '\n';
let csv = header;
arrayData.forEach(obj => {
let row = [];
for (key in obj) {
if (obj.hasOwnProperty(key)) {
row.push(obj[key]);
}
}
csv += row.join(delimiter) + "\n";
});
let csvData = new Blob([csv], { type2: 'text/csv' });
let csvUrl = URL.createObjectURL(csvData);
let hiddenElement = document.createElement('a');
hiddenElement.href = csvUrl;
hiddenElement.target = '_blank';
hiddenElement.download = fileName + '.csv';
hiddenElement.click();
}
function showLoadingWithProgress(message = "Cargando datos...") {
const loadingDiv = document.createElement('div');
loadingDiv.id = 'loadingOverlay';
loadingDiv.innerHTML = `
${message}
Procesando...
Por favor, espera
`;
document.body.appendChild(loadingDiv);
}
function updateLoadingProgress(message) {
const progressElement = document.getElementById('loadingProgress');
if (progressElement) {
progressElement.textContent = message;
}
}
function showLoading(message = "Cargando datos...") {
const loadingDiv = document.createElement('div');
loadingDiv.id = 'loadingOverlay';
loadingDiv.innerHTML = `
${message}
No cierres esta página
`;
document.body.appendChild(loadingDiv);
}
function hideLoading() {
const loadingDiv = document.getElementById('loadingOverlay');
if (loadingDiv) {
loadingDiv.remove();
}
}
var descarga_li = document.createElement("div");
descarga_li.classList.add("uPerfil");
descarga_li.innerHTML =
'';
// Añadir el CSS necesario
const style = document.createElement('style');
style.textContent = `
.hidden { display: none !important; }
.visible { display: block !important; }
.dropdown-menu {
position: absolute;
background: white;
border: 1px solid #ccc;
z-index: 1000;
list-style: none;
padding: 0;
margin: 0;
}
.dropdown-menu li a {
display: block;
padding: 8px 12px;
text-decoration: none;
color: #333;
cursor: pointer;
}
.dropdown-menu li a:hover {
background: #f5f5f5;
color: #000000ff !important;
}
`;
document.head.appendChild(style);
// Eventos para mostrar/ocultar
const dropdownBtn = descarga_li.querySelector('#dropdownBtn');
const dropdownMenu = descarga_li.querySelector('.dropdown-menu');
dropdownBtn.addEventListener('click', function (e) {
e.stopPropagation();
dropdownMenu.classList.toggle('hidden');
dropdownMenu.classList.toggle('visible');
});
// Cerrar al hacer clic fuera
document.addEventListener('click', function () {
dropdownMenu.classList.add('hidden');
dropdownMenu.classList.remove('visible');
});
// Evitar cerrar al hacer clic dentro del menú
dropdownMenu.addEventListener('click', function (e) {
e.stopPropagation();
});
document.getElementsByClassName('main-header')[0].appendChild(descarga_li);