Files
ESH-Media/SEARCH_SCRIPTS.md
eshmeshek ecb5e7e49f init: media-center v2
Rewrite of ESH-Media v1 with separated main/renderer/shared architecture
(vite-plugin-electron, React 18, react-router-dom). Includes NeDB storage,
electron-store config, proxy manager with FoxyProxy/uBlock extensions,
custom server-checked updater, NSIS installer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 23:49:43 +03:00

8.5 KiB
Raw Blame History

Система Поисковых Скриптов

Обзор

Media Center использует систему кастомных JavaScript скриптов для поиска контента на различных сайтах. Каждый сайт имеет свой собственный скрипт, который знает, как выполнять поиск на этом конкретном сайте.

Преимущества подхода

  1. Гибкость: Каждый сайт может иметь уникальную логику поиска
  2. Расширяемость: Легко добавлять новые сайты без изменения основного кода
  3. Обновляемость: Скрипты можно обновлять с сервера
  4. Нет зависимости от Node.js: Скрипты выполняются в контексте Electron

Структура скрипта

Каждый скрипт - это JavaScript файл, который экспортирует функцию search:

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 клиент для выполнения запросов:

// 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:

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)

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)

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. Встроенные скрипты: <app>/search-scripts/

    • Поставляются с приложением
    • Только для чтения
    • Используются по умолчанию
  2. Пользовательские скрипты: <userData>/search-scripts/

    • Загружаются с сервера
    • Можно обновлять
    • Имеют приоритет над встроенными

Конфигурация сайта

В config/sites.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

Возвращает конфигурацию со списком сайтов и ссылками на скрипты:

{
  "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