Authorization, favorites and players have been moved to the API server

This commit is contained in:
2025-07-07 18:08:42 +03:00
parent df03badb88
commit a251e38302
12 changed files with 1735 additions and 5 deletions

54
src/utils/adblock.js Normal file
View File

@@ -0,0 +1,54 @@
const fs = require('fs');
const path = require('path');
const cheerio = require('cheerio');
// Lazy-loaded in-memory set of ad domains
let adDomains = null;
function loadAdDomains() {
if (adDomains) return adDomains;
adDomains = new Set();
try {
const listPath = path.join(__dirname, '..', '..', 'easylist.txt');
const data = fs.readFileSync(listPath, 'utf8');
const lines = data.split('\n');
const domainRegex = /^\|\|([^\/^]+)\^/; // matches ||domain.com^
for (const line of lines) {
const m = domainRegex.exec(line.trim());
if (m) {
adDomains.add(m[1].replace(/^www\./, ''));
}
}
console.log(`Adblock: loaded ${adDomains.size} domains from easylist.txt`);
} catch (e) {
console.error('Adblock: failed to load easylist.txt', e);
adDomains = new Set();
}
return adDomains;
}
function cleanHtml(html) {
const domains = loadAdDomains();
const $ = cheerio.load(html);
const removed = [];
$('script[src], iframe[src], img[src], link[href]').each((_, el) => {
const attr = $(el).attr('src') || $(el).attr('href');
if (!attr) return;
try {
const host = new URL(attr, 'https://dummy-base/').hostname.replace(/^www\./, '');
if (domains.has(host)) {
removed.push(host);
$(el).remove();
}
} catch (_) {
// ignore invalid URLs
}
});
if (removed.length) {
const unique = [...new Set(removed)];
console.log(`Adblock removed resources from: ${unique.join(', ')}`);
}
return $.html();
}
module.exports = { cleanHtml };

23
src/utils/cleanup.js Normal file
View File

@@ -0,0 +1,23 @@
const { getDb } = require('../db');
// Delete unverified users older than 7 days
async function deleteStaleUsers() {
try {
const db = await getDb();
const weekAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000);
const result = await db.collection('users').deleteMany({ verified: false, createdAt: { $lt: weekAgo } });
if (result.deletedCount) {
console.log(`Cleanup: removed ${result.deletedCount} stale unverified users`);
}
} catch (e) {
console.error('Cleanup error:', e);
}
}
// run once at startup and then every 24h
(async () => {
await deleteStaleUsers();
setInterval(deleteStaleUsers, 24 * 60 * 60 * 1000);
})();
module.exports = { deleteStaleUsers };

45
src/utils/mailer.js Normal file
View File

@@ -0,0 +1,45 @@
const nodemailer = require('nodemailer');
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.GMAIL_USER || process.env.gmail_user,
pass: process.env.GMAIL_APP_PASSWORD || process.env.gmail_app_password
}
});
async function sendVerificationEmail(to, code) {
try {
await transporter.sendMail({
from: process.env.GMAIL_USER || process.env.gmail_user,
to,
subject: 'Подтверждение регистрации Neo Movies',
html: `
<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto;">
<h1 style="color: #2196f3;">Neo Movies</h1>
<p>Здравствуйте!</p>
<p>Для завершения регистрации введите этот код:</p>
<div style="
background: #f5f5f5;
padding: 20px;
border-radius: 8px;
text-align: center;
font-size: 24px;
letter-spacing: 4px;
margin: 20px 0;
">
${code}
</div>
<p>Код действителен в течение 10 минут.</p>
<p>Если вы не регистрировались на нашем сайте, просто проигнорируйте это письмо.</p>
</div>
`
});
return { success: true };
} catch (err) {
console.error('Error sending verification email:', err);
return { error: 'Failed to send email' };
}
}
module.exports = { sendVerificationEmail };