286 lines
10 KiB
JavaScript
286 lines
10 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/',
|
|
];
|
|
|
|
// Кеш страниц фильмов и постеров
|
|
const filmData = new Map();
|
|
|
|
function buildProxyUrl(proxy, url) {
|
|
return proxy + encodeURIComponent(url);
|
|
}
|
|
|
|
async function fetchWithProxy(url, timeout = 15000) {
|
|
const controller = new AbortController();
|
|
const timer = setTimeout(() => controller.abort(), timeout);
|
|
|
|
try {
|
|
for (const proxy of PROXIES) {
|
|
try {
|
|
const response = await fetch(buildProxyUrl(proxy, url), {
|
|
signal: controller.signal,
|
|
headers: {
|
|
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
|
|
}
|
|
});
|
|
|
|
if (response.ok) {
|
|
const text = await response.text();
|
|
if (text && text.trim().length > 0) {
|
|
return text;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
// Прокси не сработал — пробуем следующий
|
|
}
|
|
}
|
|
|
|
throw new Error('Все прокси недоступны');
|
|
} finally {
|
|
clearTimeout(timer);
|
|
}
|
|
}
|
|
|
|
function normalizePosterUrl(poster) {
|
|
if (!poster) return '';
|
|
if (poster.startsWith('http')) return poster;
|
|
return targetUrl + poster;
|
|
}
|
|
|
|
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();
|
|
posterMap.set(alt, normalizePosterUrl(poster));
|
|
}
|
|
|
|
// Альтернативно - 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)) {
|
|
posterMap.set(title, normalizePosterUrl(poster));
|
|
}
|
|
}
|
|
|
|
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);
|