265 lines
9.8 KiB
JavaScript
265 lines
9.8 KiB
JavaScript
const targetUrl = 'https://coldfilm.ink';
|
||
|
||
let currentFilmName = '';
|
||
let availableTorrents = [];
|
||
|
||
// Публичные CORS-прокси
|
||
const PROXIES = [
|
||
'https://corsproxy.io/?',
|
||
'https://api.allorigins.win/raw?url=',
|
||
'https://proxy.cors.sh/',
|
||
'https://corsproxy.org/?',
|
||
'https://allorigins.win/raw?url=',
|
||
'https://api.codetabs.com/v1/proxy?quest=',
|
||
'https://thingproxy.freeboard.io/fetch/',
|
||
'https://cors-anywhere.herokuapp.com/',
|
||
'https://corsproxy.ca/',
|
||
'https://proxy.t vot.pw/',
|
||
];
|
||
|
||
// Кеш страниц фильмов и постеров
|
||
const filmData = new Map();
|
||
|
||
async function fetchWithProxy(url) {
|
||
for (const proxy of PROXIES) {
|
||
try {
|
||
const response = await fetch(proxy + encodeURIComponent(url), { timeout: 15000 });
|
||
if (response.ok) return await response.text();
|
||
} catch (e) {}
|
||
}
|
||
throw new Error('Все прокси недоступны');
|
||
}
|
||
|
||
function parseColdfilm(html) {
|
||
const films = [];
|
||
|
||
// Сначала соберём все ссылки на фильмы с названиями
|
||
// Сразу исключаем Telegram
|
||
const linksMap = new Map();
|
||
let match;
|
||
const linkRegex = new RegExp('href="(/news/[^"#]+)"[^>]*class="kino-h"[^>]*title="([^"]+)\\[Смотреть Онлайн\\]"', 'gi');
|
||
while ((match = linkRegex.exec(html)) !== null) {
|
||
const title = match[2].trim();
|
||
if (title.toLowerCase().includes('telegram')) continue;
|
||
linksMap.set(match[1], title);
|
||
}
|
||
|
||
console.log('linksMap:', linksMap.size);
|
||
|
||
// Пробуем разные паттерны для поиска постеров
|
||
const patterns = [
|
||
'<a[^>]+href="(/news/[^"#]+)"[^>]*>\\s*<img[^>]+src="([^"]+)"',
|
||
'<img[^>]+src="([^"]+)"[^>]*>\\s*<a[^>]+href="(/news/[^"#]+)"',
|
||
'class="kino-h"[^>]*title="[^"]*"[^>]*>[\\s\\S]*?<img[^>]+src="([^"]+)"'
|
||
];
|
||
|
||
for (const pat of patterns) {
|
||
const regex = new RegExp(pat, 'gi');
|
||
let count = 0;
|
||
while ((match = regex.exec(html)) !== null) {
|
||
count++;
|
||
}
|
||
console.log('Pattern:', pat.substring(0, 50), 'matches:', count);
|
||
}
|
||
|
||
// Ищем постеры по alt/title - там есть название фильма
|
||
const posterMap = new Map();
|
||
const posterRegex = new RegExp('<img[^>]+src="([^"]+)"[^>]+alt="([^"]*\\[Смотреть Онлайн\\])"[^>]*>', 'gi');
|
||
while ((match = posterRegex.exec(html)) !== null) {
|
||
const poster = match[1];
|
||
const alt = match[2].replace('[Смотреть Онлайн]', '').trim();
|
||
|
||
let fullPoster = poster;
|
||
if (!fullPoster.startsWith('http')) {
|
||
fullPoster = targetUrl + poster;
|
||
}
|
||
posterMap.set(alt, fullPoster);
|
||
}
|
||
|
||
// Альтернативно - title вместо alt
|
||
const posterRegex2 = new RegExp('<img[^>]+src="([^"]+)"[^>]+title="([^"]*\\[Смотреть Онлайн\\])"[^>]*>', 'gi');
|
||
while ((match = posterRegex2.exec(html)) !== null) {
|
||
const poster = match[1];
|
||
const title = match[2].replace('[Смотреть Онлайн]', '').trim();
|
||
|
||
if (!posterMap.has(title)) {
|
||
let fullPoster = poster;
|
||
if (!fullPoster.startsWith('http')) {
|
||
fullPoster = targetUrl + poster;
|
||
}
|
||
posterMap.set(title, fullPoster);
|
||
}
|
||
}
|
||
|
||
console.log('Найдено постеров:', posterMap.size);
|
||
|
||
// Собираем фильмы и ищем постер по названию
|
||
const urls = Array.from(linksMap.keys());
|
||
const titles = Array.from(linksMap.values());
|
||
|
||
console.log('URLs:', urls.length, 'Posters:', posterMap.size);
|
||
|
||
for (let i = 0; i < titles.length; i++) {
|
||
const url = urls[i];
|
||
const title = titles[i];
|
||
const poster = posterMap.get(title) || '';
|
||
|
||
films.push({ title, url, poster });
|
||
filmData.set(title, { url, poster });
|
||
}
|
||
|
||
console.log('Фильмов с постерами:', films.length);
|
||
return films.slice(0, 30);
|
||
}
|
||
|
||
async function loadFilms() {
|
||
const status = document.getElementById('status');
|
||
const list = document.getElementById('films');
|
||
|
||
try {
|
||
status.textContent = '🌐 Загружаем...';
|
||
const html = await fetchWithProxy(targetUrl);
|
||
status.textContent = '🔍 Парсим...';
|
||
|
||
const films = parseColdfilm(html);
|
||
|
||
if (films.length > 0) {
|
||
status.className = 'status success';
|
||
status.textContent = `✅ Найдено ${films.length} релизов!`;
|
||
|
||
list.innerHTML = '';
|
||
films.forEach((film, i) => {
|
||
const li = document.createElement('li');
|
||
li.className = 'film-item';
|
||
|
||
// Постер
|
||
const img = document.createElement('img');
|
||
img.className = 'film-poster';
|
||
img.src = film.poster;
|
||
img.alt = film.title;
|
||
img.onerror = () => { img.style.display = 'none'; };
|
||
|
||
// Инфо
|
||
const info = document.createElement('div');
|
||
info.className = 'film-info';
|
||
|
||
const span = document.createElement('span');
|
||
span.className = 'film-title';
|
||
span.textContent = `${i + 1}. ${film.title}`;
|
||
|
||
const btn = document.createElement('button');
|
||
btn.className = 'btn';
|
||
btn.textContent = '📥 Скачать';
|
||
btn.onclick = () => showQualityModal(film.title);
|
||
|
||
info.appendChild(span);
|
||
info.appendChild(btn);
|
||
|
||
li.appendChild(img);
|
||
li.appendChild(info);
|
||
|
||
list.appendChild(li);
|
||
});
|
||
} else {
|
||
status.textContent = '❌ Фильмы не найдены';
|
||
status.className = 'status error';
|
||
}
|
||
|
||
} catch (e) {
|
||
status.textContent = `❌ Ошибка: ${e.message}`;
|
||
status.className = 'status error';
|
||
}
|
||
}
|
||
|
||
async function showQualityModal(filmName) {
|
||
const status = document.getElementById('status');
|
||
const modal = document.getElementById('qualityModal');
|
||
const options = document.getElementById('qualityOptions');
|
||
|
||
currentFilmName = filmName;
|
||
availableTorrents = [];
|
||
options.innerHTML = '';
|
||
|
||
try {
|
||
status.className = 'status downloading';
|
||
status.textContent = `🔍 Ищем торренты для ${filmName}...`;
|
||
|
||
const filmInfo = filmData.get(filmName);
|
||
if (!filmInfo) throw new Error('Ссылка не найдена');
|
||
const filmUrl = filmInfo.url;
|
||
|
||
const filmPageHtml = await fetchWithProxy(targetUrl + filmUrl);
|
||
|
||
// Ищем все торренты на странице
|
||
let match;
|
||
const torrentRegex = /href="(\/t\d+\/[^"]+\.torrent)"/gi;
|
||
while ((match = torrentRegex.exec(filmPageHtml)) !== null) {
|
||
let url = match[1];
|
||
if (!url.startsWith('http')) {
|
||
url = targetUrl + url;
|
||
}
|
||
|
||
// Определяем качество из названия файла
|
||
const filename = url.toLowerCase();
|
||
let quality = 'Стандарт';
|
||
if (filename.includes('720p') || filename.includes('hd720')) quality = '720p';
|
||
else if (filename.includes('1080p') || filename.includes('hd1080')) quality = '1080p';
|
||
else if (filename.includes('4k') || filename.includes('2160p')) quality = '4K';
|
||
|
||
// Проверяем, не добавляли ли уже
|
||
if (!availableTorrents.find(t => t.url === url)) {
|
||
availableTorrents.push({ url, quality });
|
||
}
|
||
}
|
||
|
||
// Ищем magnet
|
||
const magnetRegex = /href="(magnet:[^"]+)"/gi;
|
||
while ((match = magnetRegex.exec(filmPageHtml)) !== null) {
|
||
if (!availableTorrents.find(t => t.url === match[1])) {
|
||
availableTorrents.push({ url: match[1], quality: 'Magnet' });
|
||
}
|
||
}
|
||
|
||
if (availableTorrents.length === 0) {
|
||
throw new Error('Торренты не найдены');
|
||
}
|
||
|
||
// Сортируем: 4K, 1080p, 720p, STD, Magnet
|
||
const sortOrder = { '4K': 1, '1080p': 2, '720p': 3, 'Стандарт': 4, 'Magnet': 5 };
|
||
availableTorrents.sort((a, b) => (sortOrder[a.quality] || 99) - (sortOrder[b.quality] || 99));
|
||
|
||
// Создаём кнопки
|
||
availableTorrents.forEach(t => {
|
||
const btn = document.createElement('button');
|
||
btn.className = 'quality-btn';
|
||
btn.textContent = `📥 ${t.quality}`;
|
||
btn.onclick = () => downloadTorrent(t.url);
|
||
options.appendChild(btn);
|
||
});
|
||
|
||
modal.classList.add('active');
|
||
status.textContent = `✅ Найдено ${availableTorrents.length} торрентов`;
|
||
|
||
} catch (e) {
|
||
status.className = 'status error';
|
||
status.textContent = `❌ Ошибка: ${e.message}`;
|
||
}
|
||
}
|
||
|
||
function closeModal() {
|
||
document.getElementById('qualityModal').classList.remove('active');
|
||
}
|
||
|
||
function downloadTorrent(url) {
|
||
const status = document.getElementById('status');
|
||
status.textContent = '⬇️ Открываем торрент...';
|
||
window.open(url, '_blank');
|
||
status.className = 'status success';
|
||
status.textContent = `✅ Торрент открыт!`;
|
||
closeModal();
|
||
}
|
||
|
||
// Запуск при загрузке
|
||
loadFilms();
|
||
setInterval(loadFilms, 15 * 60 * 1000);
|