# Система Поисковых Скриптов ## Обзор Media Center использует систему кастомных JavaScript скриптов для поиска контента на различных сайтах. Каждый сайт имеет свой собственный скрипт, который знает, как выполнять поиск на этом конкретном сайте. ## Преимущества подхода 1. **Гибкость**: Каждый сайт может иметь уникальную логику поиска 2. **Расширяемость**: Легко добавлять новые сайты без изменения основного кода 3. **Обновляемость**: Скрипты можно обновлять с сервера 4. **Нет зависимости от Node.js**: Скрипты выполняются в контексте Electron ## Структура скрипта Каждый скрипт - это JavaScript файл, который экспортирует функцию `search`: ```javascript async function search(query, siteUrl, useProxy, axios, cheerio, proxyConfig) { // Ваша логика поиска return [ { name: "Название фильма", url: "https://site.com/movie/123", image: "https://site.com/poster.jpg", // опционально year: "2023", // опционально description: "Описание фильма", // опционально rating: "8.5" // опционально } ]; } ``` ### Параметры функции - `query` (string) - поисковый запрос пользователя - `siteUrl` (string) - базовый URL сайта - `useProxy` (boolean) - флаг использования прокси - `axios` - HTTP клиент для запросов - `cheerio` - библиотека для парсинга HTML - `proxyConfig` - объект с настройками прокси `{host, port}` ### Возвращаемое значение Массив объектов с результатами. Обязательные поля: - `name` - название фильма/сериала - `url` - ссылка на страницу Опциональные поля: - `image` - URL постера - `year` - год выпуска - `description` - краткое описание - `rating` - рейтинг ## Доступные инструменты ### axios HTTP клиент для выполнения запросов: ```javascript // GET запрос const response = await axios.get('https://site.com/search', { params: { q: query }, timeout: 15000, headers: { 'User-Agent': 'Mozilla/5.0...' } }); // POST запрос const response = await axios.post('https://site.com/search', { query: query }, { timeout: 15000 }); // С прокси if (useProxy && proxyConfig) { const response = await axios.get(url, { proxy: { host: proxyConfig.host, port: proxyConfig.port } }); } ``` ### cheerio jQuery-подобная библиотека для парсинга HTML: ```javascript const $ = cheerio.load(html); // Поиск элементов const title = $('.movie-title').text(); const link = $('a.movie-link').attr('href'); // Итерация по элементам $('.movie-card').each((index, element) => { const $el = $(element); const name = $el.find('.title').text().trim(); const url = $el.find('a').attr('href'); }); ``` ## Примеры реализаций ### Пример 1: HTML парсинг (Kinogo) ```javascript async function search(query, siteUrl, useProxy, axios, cheerio, proxyConfig) { const config = { params: { do: 'search', subaction: 'search', story: query }, timeout: 15000, headers: { 'User-Agent': 'Mozilla/5.0...' } }; if (useProxy && proxyConfig) { config.proxy = { host: proxyConfig.host, port: proxyConfig.port }; } const response = await axios.get(`${siteUrl}/index.php`, config); const $ = cheerio.load(response.data); const results = []; $('.shortstory').each((i, el) => { const $item = $(el); const name = $item.find('.title a').text().trim(); const url = $item.find('.title a').attr('href'); const image = $item.find('img').attr('src'); if (name && url) { results.push({ name, url: siteUrl + url, image }); } }); return results; } ``` ### Пример 2: JSON API (Rutube) ```javascript async function search(query, siteUrl, useProxy, axios, cheerio, proxyConfig) { const config = { params: { query, limit: 20 }, timeout: 15000 }; const response = await axios.get(`${siteUrl}/api/search/video/`, config); const data = response.data; if (!data.results) return []; return data.results.map(item => ({ name: item.title, url: item.video_url || `${siteUrl}/video/${item.id}`, image: item.thumbnail_url, description: item.description })); } ``` ## Хранение скриптов Скрипты хранятся в двух местах: 1. **Встроенные скрипты**: `/search-scripts/` - Поставляются с приложением - Только для чтения - Используются по умолчанию 2. **Пользовательские скрипты**: `/search-scripts/` - Загружаются с сервера - Можно обновлять - Имеют приоритет над встроенными ## Конфигурация сайта В `config/sites.json`: ```json { "id": "kinogo", "name": "Kinogo", "url": "https://kinogo.biz", "logo": "https://kinogo.biz/favicon.ico", "enabled": true, "useProxy": true, "searchScript": "kinogo.js" } ``` ## Создание нового скрипта 1. Скопируйте `SCRIPT_TEMPLATE.js` 2. Назовите файл по имени сайта (например, `mysite.js`) 3. Реализуйте функцию `search()` 4. Протестируйте с разными запросами 5. Добавьте сайт в конфигурацию ## Обновление скриптов с сервера Пользователи могут обновлять скрипты через настройки приложения: 1. Настройки → Конфигурация 2. Кнопка "Обновить конфигурацию" 3. Скачиваются новые скрипты и конфигурация 4. Применяются автоматически ## Безопасность - Скрипты выполняются в изолированном контексте - Таймаут выполнения: 30 секунд - Нет доступа к файловой системе - Нет доступа к другим модулям Node.js - Только axios и cheerio ## Отладка Для отладки скриптов: 1. Откройте DevTools (F12 в приложении) 2. Выполните поиск 3. Проверьте консоль на наличие ошибок 4. Логи включают: - Найденное количество результатов - Ошибки выполнения - Невалидные результаты ## Требования к серверу Сервер должен предоставлять: ### GET /api/config/sites Возвращает конфигурацию со списком сайтов и ссылками на скрипты: ```json { "version": "1.0.0", "lastUpdated": "2025-10-14T12:00:00Z", "sites": [ { "id": "kinogo", "name": "Kinogo", "url": "https://kinogo.biz", "logo": "https://kinogo.biz/favicon.ico", "enabled": true, "useProxy": true, "searchScript": "kinogo.js", "scriptUrl": "https://server.com/scripts/kinogo.js" } ] } ``` ### GET /scripts/{scriptName} Возвращает содержимое скрипта (JavaScript файл). ## Best Practices 1. **Обработка ошибок**: Всегда оборачивайте код в try-catch 2. **Таймауты**: Устанавливайте разумные таймауты для запросов 3. **Валидация**: Проверяйте наличие обязательных полей 4. **User-Agent**: Используйте реалистичный User-Agent 5. **Относительные URL**: Преобразуйте в абсолютные 6. **Пустые результаты**: Возвращайте `[]` при ошибке, а не `null`