您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Ищет фильм в Google и автоматически переходит на Flicksbar без использования API Кинопоиска
// ==UserScript== // @name Кнопка перехода на Flicksbar из Kinorium (без использования API Кинопоиска) // @namespace http://tampermonkey.net/ // @version 1.0.5.5.0 // @description Ищет фильм в Google и автоматически переходит на Flicksbar без использования API Кинопоиска // @author CgPT & Vladimir_0202 // @icon https://ru.kinorium.com/favicon.ico // @match *://*.kinorium.com/* // @match *://flcksbr.top/* // @match *://www.google.com/search* // @match *://duckduckgo.com/* // @include /^https:\/\/.*flicksbar\..*$/ // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_registerMenuCommand // @license MIT // ==/UserScript== (function () { 'use strict'; //Добавляем кнопки в меню TamperMonkey let menuCommands = {}; // Описываем функции в массиве const features = [ { key: 'function1Enabled', name: 'Очистка Хранилища', description: 'Удаляет сохранённые временные данные (например, постер и описание)' }, { key: 'function2Enabled', name: 'Запрос при переходе на Flicksbar', description: 'Показывает подтверждение перед редиректом на Flicksbar' }, { key: 'function3Enabled', name: 'Редирект через Google или DuckDuckGo ', description: 'Переключение редиректа с Google на DuckDuckGo'} ]; // Регистрируем все пункты меню function registerAllMenus() { // Удаляем старые команды меню for (let id in menuCommands) { GM_unregisterMenuCommand(menuCommands[id]); } menuCommands = {}; // Регистрируем новые команды for (let feature of features) { let enabled = GM_getValue(feature.key, true); let title = (enabled ? "✅ Вкл: " : "❌ Выкл: ") + feature.name; menuCommands[feature.key] = GM_registerMenuCommand(title, () => toggleFeature(feature)); } } // Функция переключения состояния function toggleFeature(feature) { let currentState = GM_getValue(feature.key, true); let newState = !currentState; GM_setValue(feature.key, newState); alert(`${feature.name} ${newState ? '✅ Включен (а)' : '❌ Выключен (а)'}\n\nОписание: ${feature.description}`); registerAllMenus(); // Перерегистрировать меню после переключения } // При старте скрипта registerAllMenus(); const url = window.location.href; // === 1. KINORIUM: Добавляем кнопку на страницу фильма === if (/kinorium\.com\/\d+\/?$/.test(url)) { // Сохраняем постер и описание в хранилище Tampermonkey const posterEl = document.querySelector('.jsCarouselImageContainer img') || document.querySelector('.carousel_image-handler img'); const descEl = document.querySelector('.film-page__text'); const titleEl = document.querySelector('.film-page__title-text.film-page__itemprop'); const originalTitleEl = document.querySelector('.film-page__orig_with_comment') || document.querySelector('.film-page__subtitle'); const yearEl = document.querySelector('.film-page__date a[href*="years_min="]'); const raitingEl = document.querySelector('.film-page__title-rating') || Array.from(document.querySelectorAll('.ratingsBlock li')) .find(li => li.textContent.includes('Кинориум')) ?.querySelector('.value'); const poster = posterEl?.src; const description = descEl?.innerText; const titleTMP = titleEl?.innerText; const originalTitleTMP = originalTitleEl?.innerText; const yearTMP = yearEl?.innerText || ''; const raitingTMP = raitingEl?.innerText?.trim() || ''; const currentUrlTMP = window.location.href; if (poster && description) { GM_setValue('flicksbar_poster', poster); // Сохраняем в хранилище Tampermonkey GM_setValue('flicksbar_description', description); // Сохраняем в хранилище Tampermonkey GM_setValue('flicksbar_titleTMP', titleTMP); // Сохраняем в хранилище Tampermonkey GM_setValue('flicksbar_originalTitleTMP', originalTitleTMP); // Сохраняем в хранилище Tampermonkey GM_setValue('flicksbar_yearTMP', yearTMP); // Сохраняем в хранилище Tampermonkey GM_setValue('flicksbar_raitingTMP', raitingTMP); // Сохраняем в хранилище Tampermonkey GM_setValue('flicksbar_currentUrlTMP', currentUrlTMP); console.log('✅ Постер и описание сохранены в Tampermonkey storage'); } else { console.warn('⚠️ Не удалось найти постер или описание'); } function getFilmDetails() { const titleElement = document.querySelector('.film-page__title-text.film-page__itemprop'); const originalTitleElement = document.querySelector('.film-page__orig_with_comment'); const typeLink = document.querySelector('.b-post__info a[href*="/series/"]'); const yearElement = document.querySelector('.film-page__date a[href*="years_min="]'); const title = titleElement ? titleElement.textContent.trim() : ''; const originalTitle = originalTitleElement ? originalTitleElement.textContent.trim() : ''; const year = yearElement ? yearElement.textContent.trim() : ''; const isSeries = typeLink !== null; return { title, originalTitle, year, isSeries }; } function createButton() { const button = document.createElement('button'); button.innerHTML = '<span style="display:inline-flex; align-items:center; justify-content:center; width:20px; height:22px; margin-right:8px; border:2px solid white; border-radius:50%; font-size:12px; padding-left:2px;">▶</span>Смотреть на Flicksbar'; button.style.cssText = ` padding: 9px; margin-top: -5px; margin-bottom: 2px; background-color: #007bff; color: white; border: none; border-radius: 3px; width: 100%; cursor: pointer; transition: background-color 0.3s ease; `; button.addEventListener('mouseenter', () => button.style.backgroundColor = '#0056b3'); button.addEventListener('mouseleave', () => button.style.backgroundColor = '#007bff'); const { title, originalTitle, year } = getFilmDetails(); button.title = `Смотреть "${title} ${originalTitle} ${year}" бесплатно онлайн на Flicksbar`; button.onclick = () => { const { title, originalTitle, year, isSeries } = getFilmDetails(); if (!title) return alert('Не удалось извлечь информацию о фильме.'); const searchQuery = encodeURIComponent(`${title} ${originalTitle} ${year} кинопоиск`); const flicksbarType = isSeries ? 'series' : 'film'; const googleUrl = GM_getValue('function3Enabled', true) ? `https://www.google.com/search?q=${searchQuery}&btnK&flcks_type=${flicksbarType}` : `https://duckduckgo.com/?q=${searchQuery}&btnK&flcks_type=${flicksbarType}`; window.open(googleUrl, '_blank'); }; const sideCover = document.querySelector('.collectionWidget.collectionWidgetData.withFavourites'); if (sideCover) sideCover.appendChild(button); else console.warn('Элемент для вставки кнопки не найден.'); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', createButton); } else { createButton(); } } // === 2. GOOGLE: Автопереход на Flicksbar по найденному ID Кинопоиска === if (/google\.com\/search/.test(url) || /duckduckgo\.com\//.test(url)) { function showConfirmWithTimeout(flicksbarUrl, timeout = 5000) { return new Promise((resolve) => { const modal = document.createElement('div'); Object.assign(modal.style, { position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', padding: '20px', backgroundColor: '#EEE8AA', border: '1px solid #ccc', zIndex: '9999', boxShadow: '0 4px 8px rgba(0, 0, 0, 0.2)', borderRadius: '8px', }); const message = document.createElement('p'); message.style.color = 'black'; message.innerHTML = `<b>Переход на Flicksbar</b> <br><br>Перейти по ссылке: <b>${flicksbarUrl}</b> ?`; modal.appendChild(message); const okButton = document.createElement('button'); okButton.textContent = 'Да'; Object.assign(okButton.style, { marginRight: '10px', padding: '5px 10px', backgroundColor: '#28a745', color: 'white', border: 'none', cursor: 'pointer', borderRadius: '5px', }); okButton.onclick = () => { resolve(true); modal.remove(); }; modal.appendChild(okButton); const cancelButton = document.createElement('button'); cancelButton.textContent = 'Нет'; Object.assign(cancelButton.style, { padding: '5px 10px', backgroundColor: '#dc3545', color: 'white', border: 'none', cursor: 'pointer', borderRadius: '5px', }); cancelButton.onclick = () => { resolve(false); modal.remove(); }; modal.appendChild(cancelButton); document.body.appendChild(modal); setTimeout(() => { resolve(false); //resolve(true); - если надо чтобы после таймера нажималась кнопка ОK modal.remove(); }, timeout); }); } function observeResults() { const observer = new MutationObserver(() => { const kpLink = document.querySelector('a[href*="kinopoisk.ru/film/"]'); if (kpLink) { observer.disconnect(); // Остановить наблюдение tryRedirect(kpLink); } }); observer.observe(document.body, { childList: true, subtree: true }); } async function tryRedirect(kpLink) { const urlParams = new URLSearchParams(window.location.search); const type = urlParams.get('flcks_type'); // фильм / сериал (для Flicksbar) const preferGoogle = GM_getValue('function3Enabled', true); // ✅ Разрешаем редирект, если: // - включён Google и есть параметр flcks_type // - включён DuckDuckGo и есть параметр flcks_type const allowRedirect = (preferGoogle && type) || (!preferGoogle && type); console.log ('urlParams: ', urlParams) console.log ('type: ', type) console.log ('preferGoogle: ', preferGoogle) if (!allowRedirect) { console.log('Редирект не выполняется: источник не соответствует настройке function3Enabled'); return; } const match = kpLink.href.match(/kinopoisk\.ru\/film\/(\d+)/); if (!match) return; const kpId = match[1]; //const urlParams = new URLSearchParams(window.location.search); //const type = urlParams.get('flcks_type') || 'film'; const flicksbarUrl = `https://flcksbr.top/${type}/${kpId}/`; if (GM_getValue('function2Enabled', true)) { const answer = await showConfirmWithTimeout(flicksbarUrl, 5000); if (answer) window.location.href = flicksbarUrl; else console.log('Переход отменен пользователем или истек таймаут.'); } else { window.location.href = flicksbarUrl; } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', tryRedirect); } else { observeResults(); } } // === 3. Flicksbar: изменение плеера и добавление постера и описания === if (/https?:\/\/(flicksbar\.mom|flcksbr\.top)\/(film|series)\/\d+\/?$/.test(location.href)) { // Функция для отображения постера и описания в блоке справа function displayMovieInfo(poster, description, titleTMP, originalTitleTMP, yearTMP, raitingTMP) { const infoBox = document.getElementById("kinorium-info"); if (infoBox && poster && description && titleTMP && originalTitleTMP && yearTMP && raitingTMP) { infoBox.innerHTML = ` <p style="font-size:25px;">${titleTMP} ${originalTitleTMP} ${yearTMP} ${raitingTMP}</p><br><img src="${poster}" alt="Постер" style="width:100%;border-radius:10px;margin-bottom:10px;display:flex;justify-content:center;align-items:center; "> <p style="color:white;font-size:16px;line-height:1.4;">${description}</p> `; } } function clearFlicksbarInfo() { console.log('✅ Очистка данных...'); GM_deleteValue('flicksbar_poster'); GM_deleteValue('flicksbar_description'); GM_deleteValue('flicksbar_titleTMP'); GM_deleteValue('flicksbar_originalTitleTMP'); GM_deleteValue('flicksbar_yearTMP'); GM_deleteValue('flicksbar_raitingTMP'); GM_deleteValue('flicksbar_currentUrlTMP'); } // Убираем рекламу function removeAds() { const selectors = [ "#tgWrapper", "#TopAdMb", ".brand", ".topAdPad", ".adDown", "body > span", "body > script:first-child" ]; selectors.forEach(sel => { const el = document.querySelector(sel); if (el) el.remove(); }); } // Структурируем страницу function restructurePage() { const main = document.querySelector(".mainContainer"); const player = document.querySelector(".kinobox"); if (!main || !player) return; document.documentElement.style.overflowY = "auto"; // Включаем скроллинг на уровне всей страницы document.body.style.overflowY = "auto"; // И на body тоже на всякий document.body.style.background = "#1c1c1c"; player.style.minHeight = "0"; player.style.height = "100%"; player.style.width = "100%"; player.style.borderRadius = "8px"; const layout = document.createElement("div"); layout.style.display = "flex"; layout.style.flexWrap = "nowrap"; // не переносить элементы layout.style.background = "#1c1c1c"; layout.style.gap = "10px"; layout.style.marginTop = "10px"; layout.style.alignItems = "stretch"; layout.style.width = "100%"; layout.style.boxSizing = "border-box"; layout.classList.add("responsive-layout"); const left = document.createElement("div"); left.style.flex = "7 1 0"; // flex-grow, flex-shrink, flex-basis left.style.height = "100%"; left.style.minHeight = "500px"; left.style.marginLeft = "5px"; left.style.display = "flex"; left.style.flexDirection = "column"; left.style.minWidth = "0"; // чтобы flex мог ужимать left.classList.add("responsive-left"); left.appendChild(player); const right = document.createElement("div"); right.style.flex = "3 1 0"; right.style.fontFamily = "sans-serif"; right.style.color = "#eee"; right.style.borderRadius = "8px"; right.style.marginRight = "5px"; right.style.padding = "15px"; right.style.background = "#222"; right.style.overflow = "auto"; right.style.minWidth = "0"; right.classList.add("responsive-right"); const infoWrapper = document.createElement("div"); infoWrapper.id = "kinorium-info"; infoWrapper.style.flex = "flex"; infoWrapper.style.flexDirection = "column"; infoWrapper.style.gap = "20px"; infoWrapper.style.width = "100%"; right.appendChild(infoWrapper); layout.appendChild(left); layout.appendChild(right); main.innerHTML = ""; main.style.display = "inline-block"; main.style.background = "#1c1c1c"; main.style.boxSizing = "border-box"; // на всякий main.style.width = "100%"; main.appendChild(layout); const style = document.createElement("style"); style.textContent = ` @media (max-width: 768px) and (orientation: portrait) { .responsive-layout { flex-direction: column !important; margin-top: 2px !important; } .responsive-left { width: auto !important; height: auto !important; margin: 2px !important; min-height: auto !important; } .responsive-right { flex: none !important; } } `; document.head.appendChild(style); } // Добавялем инфу про фильм function loadAndDisplayInfo() { const poster = GM_getValue('flicksbar_poster', null); const description = GM_getValue('flicksbar_description', null); const titleTMP = GM_getValue('flicksbar_titleTMP', null); const originalTitleTMP = GM_getValue('flicksbar_originalTitleTMP', null); const yearTMP = GM_getValue('flicksbar_yearTMP', null); const raitingTMP = GM_getValue('flicksbar_raitingTMP', null); const currentUrlTMP = GM_getValue('flicksbar_currentUrlTMP', null); const infoContainer = document.querySelector("#kinorium-info"); if (!infoContainer) { console.log('#kinorium-info element not found on the page.'); return; } infoContainer.innerHTML = ""; const dynamicStyle = document.createElement('style'); dynamicStyle.textContent = ` @keyframes fadeInScale { 0% { opacity: 0; transform: scale(0.95); } 100% { opacity: 1; transform: scale(1); } } .fade-in-scale { animation: fadeInScale 0.8s ease-out; } `; const invisibleScrollbarStyle = document.createElement('style'); invisibleScrollbarStyle.textContent = ` /* Скроллбар невидим в обычном состоянии */ ::-webkit-scrollbar { width: 8px; height: 8px; background: transparent; } /* Трек (фон полосы) тоже прозрачный */ ::-webkit-scrollbar-track { background: transparent; } /* Ползунок скрыт, но появляется при наведении */ ::-webkit-scrollbar-thumb { background: transparent; border-radius: 10px; transition: background 0.3s ease; } /* При наведении — появляется аккуратный ползунок */ :hover::-webkit-scrollbar-thumb { background: rgba(150, 150, 150, 0.7); } /* Для Firefox */ * { scrollbar-width: thin; scrollbar-color: transparent transparent; } *:hover { scrollbar-color: rgba(150,150,150,0.7) transparent; } `; document.head.appendChild(invisibleScrollbarStyle); document.head.appendChild(dynamicStyle); // Заголовок if (titleTMP || originalTitleTMP || yearTMP) { const titleElement = document.createElement("div"); titleElement.innerHTML = ` <div style="text-align: center; margin-bottom: 5px;"> <div style="font-size: 22px; font-weight: bold;">${titleTMP || ""}</div> ${(originalTitleTMP || yearTMP) ? ` <div style="font-size: 18px; margin-top: 2px;"> <span style="color: #aaa;">${originalTitleTMP || ""}</span> ${yearTMP ? `<span style="color: #fff;"> (${yearTMP})</span>` : ""} </div> ` : ""} </div> `; infoContainer.appendChild(titleElement); } // Рейтинг if (raitingTMP) { let ratingColor = "#aaa"; const ratingNum = parseFloat(raitingTMP); if (ratingNum < 5) ratingColor = "red"; else if (ratingNum < 7) ratingColor = "orange"; else ratingColor = "lightgreen"; const ratingElement = document.createElement("p"); ratingElement.textContent = `Рейтинг: ${raitingTMP}`; ratingElement.style.cssText = ` font-size: 18px; color: ${ratingColor}; text-align: center; margin: 0 0 5px; `; infoContainer.appendChild(ratingElement); } // Постер if (poster) { const posterElement = document.createElement("img"); posterElement.src = poster; posterElement.alt = "Постер фильма"; posterElement.style.maxWidth = "100%"; posterElement.style.borderRadius = "12px"; posterElement.style.display = "block"; posterElement.style.margin = "0 auto 10px"; posterElement.className = "fade-in-scale"; // применяем нашу анимацию через класс infoContainer.appendChild(posterElement); posterElement.addEventListener('mouseover', () => { posterElement.style.transform = 'scale(1.005)'; posterElement.style.boxShadow = '0 2px 6px rgba(0, 0, 0, 0.3)'; posterElement.style.boxShadow = 'none'; posterElement.style.cursor = 'pointer'; }); posterElement.addEventListener('mouseout', () => { posterElement.style.transform = 'scale(1)'; posterElement.style.boxShadow = '0 2px 6px rgba(0, 0, 0, 0.3)'; posterElement.style.cursor = 'pointer'; }); posterElement.addEventListener('click', () => { window.open(currentUrlTMP, '_blank'); }); } // Описание if (description) { const descriptionWrapper = document.createElement("div"); descriptionWrapper.style.overflowY = "auto"; descriptionWrapper.style.maxHeight = "300px"; descriptionWrapper.style.paddingRight = "8px"; const descPara = document.createElement("p"); descPara.innerText = description; descPara.style.fontSize = "16px"; descPara.style.lineHeight = "1.5"; descPara.style.textAlign = "justify"; descPara.style.boxShadow = "0 0 15px rgba(0,0,0,0.4)"; descPara.style.borderRadius = "10px"; descPara.style.padding = "5px"; descPara.style.background = "#1c1c1c"; descPara.className = "fade-in-scale"; // применяем нашу анимацию через класс descriptionWrapper.appendChild(descPara); infoContainer.appendChild(descriptionWrapper); // Плавное уменьшение шрифта при переполнении setTimeout(() => { let fontSize = 16; while (descriptionWrapper.scrollHeight > descriptionWrapper.clientHeight && fontSize > 12) { fontSize--; descPara.style.fontSize = fontSize + "px"; } }, 100); } console.log('✅ Информация успешно отображена (гибкий режим)'); } // Вызываем всё нужное if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { removeAds(); restructurePage(); loadAndDisplayInfo(); }); } else { removeAds(); restructurePage(); loadAndDisplayInfo(); } // Очистка данных при закрытии страницы или переходе на другой сайт window.addEventListener("unload", () => { if (GM_getValue('function1Enabled', true)) { console.log("✅ Очистка хранилища..."); clearFlicksbarInfo(); // Очистка данных } else { console.log("✅ Очистка хранилища отключена..."); } }); } })();