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>
This commit is contained in:
2026-05-11 23:49:43 +03:00
commit ecb5e7e49f
52 changed files with 11718 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
/**
* Search script template for creating custom site search scripts
*
* Copy this file and modify the search() function to work with your target site.
*
* Available tools:
* - axios: For making HTTP requests
* - cheerio: For parsing HTML (jQuery-like syntax)
* - proxyConfig: Proxy settings if useProxy is true
*
* @param {string} query - Search query entered by user
* @param {string} siteUrl - Base URL of the website (e.g., "https://example.com")
* @param {boolean} useProxy - Whether to use proxy for this request
* @param {object} axios - Axios HTTP client
* @param {object} cheerio - Cheerio HTML parser
* @param {object} proxyConfig - Proxy configuration {host: string, port: number}
* @returns {Promise<Array>} Array of results in format: [{name: string, url: string, image?: string, year?: string, description?: string, rating?: string}]
*/
async function search(query, siteUrl, useProxy, axios, cheerio, proxyConfig) {
try {
// 1. Build the search URL
const searchUrl = `${siteUrl}/search?q=${encodeURIComponent(query)}`;
// 2. Configure the request
const config = {
timeout: 15000, // 15 seconds timeout
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
};
// 3. Add proxy if needed
if (useProxy && proxyConfig) {
config.proxy = {
host: proxyConfig.host,
port: proxyConfig.port
};
}
// 4. Make the HTTP request
const response = await axios.get(searchUrl, config);
// 5a. If the response is JSON:
// const data = response.data;
// const results = data.items.map(item => ({
// name: item.title,
// url: item.link,
// image: item.thumbnail,
// year: item.year,
// description: item.synopsis
// }));
// 5b. If the response is HTML:
const html = response.data;
const $ = cheerio.load(html);
const results = [];
// Parse HTML and extract movie data
$('.movie-card').each((index, element) => {
const $item = $(element);
const name = $item.find('.movie-title').text().trim();
const url = $item.find('a').attr('href');
const image = $item.find('img').attr('src');
const year = $item.find('.year').text().trim();
const description = $item.find('.description').text().trim();
// Only add if name and url exist
if (name && url) {
results.push({
name,
url: url.startsWith('http') ? url : siteUrl + url,
image: image ? (image.startsWith('http') ? image : siteUrl + image) : undefined,
year: year || undefined,
description: description || undefined
});
}
});
// 6. Return the results
return results;
} catch (error) {
console.error('Search error:', error.message);
return []; // Return empty array on error
}
}
// Important notes:
// 1. The function MUST be named 'search'
// 2. It MUST return a Promise that resolves to an array
// 3. Each result MUST have 'name' and 'url' fields
// 4. Other fields (image, year, description, rating) are optional
// 5. Handle errors gracefully and return [] on failure
// 6. Test with different queries to ensure reliability