(function () { //BDVBuriлk.github.io //2025 ("use strict"); let year; let namemovie; let savedHTML = null; function getSettings() { let host = (Lampa.Storage.get('rezka_comment_host', 'https://rezka.ag') || 'https://rezka.ag').trim().replace(/\/+$/, ''); let cookie = (Lampa.Storage.get('rezka_comment_cookie', '') || '').trim(); let proxy = (Lampa.Storage.get('rezka_comment_proxy', 'https://worker-patient-dream-26d8.bdvburik.workers.dev:8443/') || 'https://worker-patient-dream-26d8.bdvburik.workers.dev:8443/').trim(); if (proxy && !proxy.endsWith('/')) { proxy += '/'; } return { host, cookie, proxy }; } // Функция для поиска на сайте hdrezka async function searchRezka(name, ye) { try { let { host, cookie, proxy } = getSettings(); let path = host + "/search/?do=search&subaction=search&q=" + encodeURIComponent(name) + (ye ? "+" + ye : ""); let searchUrl = proxy; if (cookie) { searchUrl += "param/Cookie=" + encodeURIComponent(cookie) + "/"; } searchUrl += path; console.log('[RezkaComment] searching hdrezka with url:', searchUrl); let fc = await fetch(searchUrl, { method: "GET", headers: { "Content-Type": "text/html" } }).then((response) => { if (!response.ok) { throw new Error('HTTP status ' + response.status); } return response.text(); }); let dom = new DOMParser().parseFromString(fc, "text/html"); const item = dom.querySelector(".b-content__inline_item"); if (!item) { console.warn('[RezkaComment] show not found on Rezka:', name, ye); if (fc.indexOf("Проверяем, что вы не бот") !== -1 || fc.indexOf("Anubis") !== -1) { Lampa.Noty.show('Защита от ботов на Rezka. Настройте Cookie в настройках плагина.'); } else { Lampa.Noty.show('Фильм/сериал не найден на Rezka'); } Lampa.Loading.stop(); return; } namemovie = item.querySelector(".b-content__inline_item-link")?.innerText || ""; let itemUrl = item.querySelector(".b-content__inline_item-link")?.getAttribute("href") || ""; await comment_rezka(item.dataset.id, itemUrl); } catch (e) { console.error('[RezkaComment] searchRezka error:', e); Lampa.Noty.show('Ошибка поиска на Rezka: ' + e.message); Lampa.Loading.stop(); } } // Функция для получения английского названия фильма или сериала async function getEnTitle(id, type) { try { var tmdbType = type === 'movie' ? 'movie' : 'tv'; var tmdbCacheKey = tmdbType + '_' + id; // Спочатку перевіряємо спільний кеш (заповнює title.js) window.__tmdbTranslationsCache = window.__tmdbTranslationsCache || {}; var cachedTr = window.__tmdbTranslationsCache[tmdbCacheKey]; var tr; if (cachedTr) { console.log('[RezkaComment] using shared translations cache for', tmdbCacheKey); tr = cachedTr; } else { const data = await new Promise((res, rej) => Lampa.Api.sources.tmdb.get( `${tmdbType}/${id}?append_to_response=translations`, {}, res, rej, ), ); tr = data.translations?.translations || []; window.__tmdbTranslationsCache[tmdbCacheKey] = tr; } const enTranslation = tr.find((t) => t.iso_3166_1 === 'US' || t.iso_639_1 === 'en'); const enTitle = enTranslation?.data?.title || enTranslation?.data?.name; if (enTitle) { await searchRezka(normalizeTitle(enTitle), year); } else { console.warn('[RezkaComment] English title not found for', tmdbCacheKey, tr); Lampa.Noty.show('Английское название не найдено'); Lampa.Loading.stop(); } } catch (e) { console.error('[RezkaComment] TMDB error', e); Lampa.Noty.show('Ошибка получения данных TMDB'); Lampa.Loading.stop(); } } // Функция для очистки заголовка от лишних символов function cleanTitle(str) { return str.replace(/[\s.,:;’'`!?]+/g, " ").trim(); } // Функция для нормализации заголовка function normalizeTitle(str) { return cleanTitle( str .toLowerCase() .replace(/[\-\u2010-\u2015\u2E3A\u2E3B\uFE58\uFE63\uFF0D]+/g, "-") .replace(/ё/g, "е"), ); } // Создаёт один комментарий function buildCommentNode(item) { const q = (s) => item.querySelector(s); const avatar = q(".ava img")?.dataset.src || q(".ava img")?.src || ""; const user = q(".name, .b-comment__user")?.innerText || "Без имени"; const date = q(".date, .b-comment__time")?.innerText || ""; const text = q(".message .text, .text")?.innerHTML || ""; const wrapper = document.createElement("div"); wrapper.className = "message"; wrapper.innerHTML = `
${user}
${user} ${date}
${text}
`; return wrapper; } // Рекурсивно строит дерево function buildTree(root) { const fragment = document.createDocumentFragment(); for (let li of root.children) { const indent = parseInt(li.dataset.indent || 0, 10); const wrapper = document.createElement("li"); wrapper.className = "comments-tree-item"; wrapper.style.marginLeft = indent > 0 ? "20px" : "0"; wrapper.appendChild(buildCommentNode(li)); const childrenList = li.querySelector("ol.comments-tree-list"); if (childrenList) wrapper.appendChild(buildTree(childrenList)); fragment.appendChild(wrapper); } return fragment; } // === Основная обработка комментариев Rezka с storage на сутки === async function comment_rezka(id, pageUrl) { try { let { host, cookie, proxy } = getSettings(); let t = Date.now(); let path = host + "/ajax/get_comments/?t=" + t + "&news_id=" + (id ? id : "1") + "&cstart=1&type=0&comment_id=0&skin=hdrezka"; let commentsUrl = proxy; if (cookie) { commentsUrl += "param/Cookie=" + encodeURIComponent(cookie) + "/"; } if (pageUrl) { commentsUrl += "param/Referer=" + encodeURIComponent(pageUrl) + "/"; } commentsUrl += path; console.log('[RezkaComment] fetching comments from:', commentsUrl); let fc = await fetch(commentsUrl, { method: "GET", headers: { "Content-Type": "text/plain" }, }).then((r) => { if (!r.ok) { throw new Error('HTTP status ' + r.status); } return r.text(); }); // Check if the response is actually HTML challenge instead of JSON if (fc.indexOf("Проверяем, что вы не бот") !== -1 || fc.indexOf("Anubis") !== -1) { Lampa.Noty.show('Защита от ботов на Rezka. Настройте Cookie в настройках плагина.'); Lampa.Loading.stop(); return; } let json = JSON.parse(fc); if (!json || !json.comments) { throw new Error('Пустой ответ от сервера комментариев'); } let dom = new DOMParser().parseFromString(json.comments, "text/html"); dom .querySelectorAll(".actions, i, .share-link") .forEach((elem) => elem.remove()); let rootList = dom.querySelector(".comments-tree-list"); if (!rootList) { console.warn('[RezkaComment] comments-tree-list not found in parsed HTML for', id); Lampa.Noty.show('Комментарии к фильму/сериалу отсутствуют'); Lampa.Loading.stop(); return; } let newTree = buildTree(rootList); openModal(newTree); } catch (e) { console.error('[RezkaComment] comment_rezka error:', e); Lampa.Noty.show('Ошибка получения комментариев: ' + e.message); Lampa.Loading.stop(); } function openModal(treeContent) { Lampa.Loading.stop(); let modal = $( `
`, ); modal.find(".comment").append(treeContent); // Стили модалки (если ещё не добавлены) if (!document.getElementById("rezka-comment-style")) { const styleEl = document.createElement("style"); styleEl.id = "rezka-comment-style"; styleEl.textContent = ` .comments-tree-list{list-style:none;margin:0;padding:0;} .comments-tree-item{list-style:none;margin:0;padding:0;} .comment-wrap{display:flex;margin-bottom:5px;} .avatar-column{margin-right:10px;} .avatar-img{width:48px;height:48px;border-radius:4px;} .comment-card{background:#1b1b1b;padding:5px 12px;border-radius:6px;border:1px solid #2a2a2a;width:100%;} .comment-header{display:flex;justify-content:space-between;margin-bottom:6px;} .comment-header .name{font-weight:600;color:#fff;} .comment-header .date{opacity:.7;font-size:11px;} .comment-text .text{color:#ddd;line-height:1.45;} .rc-children{margin-left:30px;border-left:1px solid #333;padding-left:14px;} .title_spoiler{display:inline-flex;align-items:center;background:#2a2a2a;border-radius:6px;padding:1px 4px;margin:0 2px;font-size:13px;color:#e0e0e0;cursor:pointer;box-shadow:0 0 2px rgba(0,0,0,.4);} .title_spoiler a{color:#e0e0e0!important;text-decoration:none!important;} .title_spoiler img{height:14px;width:auto;vertical-align:middle;margin:0 2px;} .title_spoiler .attention{height:14px;width:14px;margin-left:4px;vertical-align:middle;} .modal-close-btn{background:#2a2a2a;border:1px solid #444;color:#ddd;border-radius:6px;font-size:18px;line-height:18px;cursor:pointer;transition:.15s;} .modal-close-btn:hover{background:#3a3a3a;color:#fff;} `; document.head.appendChild(styleEl); } if (!window.rezkaSpoilerInit) { window.rezkaSpoilerInit = true; const Script = document.createElement("script"); Script.textContent = "function ShowOrHide(id){var t=$('#'+id);t.prev('.title_spoiler').remove();t.css('display','inline');}"; document.head.appendChild(Script); } Lampa.Modal.open({ title: ``, html: modal, size: "large", style: "margin-top:10px;", mask: true, onBack: function () { Lampa.Modal.close(); $(".modal--large").remove(); Lampa.Controller.toggle("content"); }, }); document .querySelector(".modal__head") ?.insertAdjacentHTML( "afterend", ` ${namemovie}`, ); } } // Функция для начала работы плагина function startPlugin() { window.comment_plugin = true; try { // Регистрация настроек Lampa.SettingsApi.addComponent({ component: 'rezka_comment', name: 'Rezka Comments', icon: '' }); Lampa.SettingsApi.addParam({ component: 'rezka_comment', param: { name: 'rezka_comment_host', type: 'input', placeholder: 'https://rezka.ag', values: Lampa.Storage.get('rezka_comment_host', 'https://rezka.ag'), default: 'https://rezka.ag' }, field: { name: 'Зеркало hdrezka', description: 'Адрес зеркала hdrezka (например, https://hdrezka.me)' }, onChange: function(value) { Lampa.Storage.set('rezka_comment_host', value); } }); Lampa.SettingsApi.addParam({ component: 'rezka_comment', param: { name: 'rezka_comment_cookie', type: 'input', placeholder: 'вставьте cookie', values: Lampa.Storage.get('rezka_comment_cookie', ''), default: '' }, field: { name: 'Cookie авторизации', description: 'Cookie из вашего браузера для обхода защиты (Anubis / PHPSESSID)' }, onChange: function(value) { Lampa.Storage.set('rezka_comment_cookie', value); } }); Lampa.SettingsApi.addParam({ component: 'rezka_comment', param: { name: 'rezka_comment_proxy', type: 'input', placeholder: 'https://worker-patient-dream-26d8.bdvburik.workers.dev:8443/', values: Lampa.Storage.get('rezka_comment_proxy', 'https://worker-patient-dream-26d8.bdvburik.workers.dev:8443/'), default: 'https://worker-patient-dream-26d8.bdvburik.workers.dev:8443/' }, field: { name: 'CORS Прокси', description: 'Ваш Cloudflare Worker прокси (обязательно с / на конце)' }, onChange: function(value) { Lampa.Storage.set('rezka_comment_proxy', value); } }); } catch (e) { console.error('[RezkaComment] Settings init error:', e); } Lampa.Listener.follow("full", function (e) { if (e.type == "complite") { $(".button--comment").remove(); $(".full-start-new__buttons").append( `
${Lampa.Lang.translate( "title_comments", )}
`, ); $(".button--comment").on("hover:enter", function (card) { year = 0; if (e.data.movie.release_date) { year = e.data.movie.release_date.slice(0, 4); } else if (e.data.movie.first_air_date) { year = e.data.movie.first_air_date.slice(0, 4); } Lampa.Loading.start(); getEnTitle(e.data.movie.id, e.object.method); }); } }); } if (!window.comment_plugin) startPlugin(); })();