// ==UserScript== // @name Kinopoisk - Add to folder // @namespace scriptomatika // @author mouse-karaganda // @description Добавить фильм в папку // @license MIT // @match https://*.kinopoisk.ru/film/* // @match https://*.kinopoisk.ru/series/* // @icon https://www.google.com/s2/favicons?sz=64&domain=kinopoisk.ru // @version 1.4 // @grant none // @downloadURL none // ==/UserScript== (function() { let $ = window.jQuery; console.log('kinoscript :: userscript run at == ', location.href); let poisk = {}; let plugin = { insertStyle: function() { if ($('style[name="kinoscript"]').length > 0) { return; } let styleText = [ '.styles_userFoldersContainer { margin-bottom: 24px; }', '.styles_userFoldersContainer .btn_outer { display: flex; justify-content: center; cursor: pointer; font-weight: bold; color: #3bb33b; }', '.styles_userFoldersContainer .btn_outer:hover { color: #266fff; }', '.styles_userFoldersContainer .btn_outer .button { margin: 0 8px; }', '.styles_userFoldersContainer .btn_outer .arrow_right { transform: rotate(90deg); }', 'div[class*=styles_rootDark] .styles_userFoldersContainer .menu_outer { background-color: #000000; color: white; }', '.styles_userFoldersContainer .menu_outer { position: absolute; left: 0; right: 0; z-index: 10; padding: 12px 0; border: 2px dotted #3bb33b; border-radius: 12px; background-color: #ffffff; }', '.styles_userFoldersContainer .menu_inner { height: 250px; overflow-x: hidden; overflow-y: scroll; scrollbar-width: thin; }', '.styles_userFoldersContainer .menu_outer .item { display: flex; justify-content: space-between; padding: 8px 20px; margin: 4px 0; cursor: pointer; }', '.styles_userFoldersContainer .menu_outer .item:hover { background-color: rgba(0, 0, 0, 0.04) }', '.styles_userFoldersContainer .menu_outer .item:hover .button { color: #266fff; }', '.styles_userFoldersContainer.opened .btn_outer .arrow_right,', '.styles_userFoldersContainer:not(.opened) .btn_outer .arrow_down,', '.styles_userFoldersContainer:not(.opened) .btn_outer .count,', '.styles_userFoldersContainer:not(.opened) .menu_outer,', '.styles_userFoldersContainer .menu_outer .item:not(.select) .mark { display: none; }' ]; $('').appendTo(document.head) .text(styleText.join('\n')); }, createFoldersButton: function() { let foldersMenu = $('div[class*=styles_foldersMenu]').parents('div[class*=styles_userControlsContainer]'); console.log('kinoscript :: foldersMenu = ', foldersMenu); if (foldersMenu.length == 0) { return; } poisk.section = $('
').insertBefore(foldersMenu).addClass('styles_userFoldersContainer styles_section'); poisk.link = $('').addClass('btn_outer').appendTo(poisk.section).on('click', plugin.openFolderList); $('').addClass('arrow_down').text('🔻').appendTo(poisk.link); $('').addClass('arrow_right').text('🔺').appendTo(poisk.link); $('').addClass('button').text('Список папок').appendTo(poisk.link); poisk.count = $('').addClass('count').text('(0)').appendTo(poisk.link); let menuOuter = $('').addClass('menu_outer').appendTo(poisk.section); poisk.menu = $('').addClass('menu_inner').appendTo(menuOuter); }, openFolderList: function(evt) { evt.preventDefault(); evt.stopPropagation(); poisk.menu.empty(); poisk.count.text('(0)'); // Открытое меню нужно закрыть if (poisk.section.hasClass('opened')) { poisk.section.removeClass('opened'); return; } let random = Math.round(Math.random() * 1e8); $.post('/handler_mustsee_ajax.php?mode=multiple&rnd=' + random, { //mode: multiple | single token: plugin.cookie('_csrf_csrf_token'), id_films: plugin.getCurrentFilm() }, function(data) { console.log('kinoscript :: openFolderList POST = ', data); if (data.folders.length == 0) { return; } poisk.section.addClass('opened'); let filmId = plugin.getCurrentFilm(); let selectedCount = 0; data.folders.forEach((folder, index) => { let info = { 'data-id': folder.id, 'data-urladd': `/handler_mykp/folders/${folder.id}/film/${filmId}/` }; let div = $('').addClass('item').attr(info).appendTo(poisk.menu) .on('click', plugin.toggleFilmToFolder); $('').addClass('button').html(folder.name).appendTo(div); $('').addClass('mark').text('✔️').appendTo(div); if (filmId in data.objFolders) { if (folder.id in data.objFolders[filmId]) { div.addClass('select'); selectedCount++; } } }); poisk.count.text(`(${selectedCount})`); }); }, toggleFilmToFolder: function(evt) { console.log('kinoscript :: toggleFilmToFolder = ', evt, this); let urlAdd = $(this).data('urladd'); console.log('kinoscript :: toggleFilmToFolder urlAdd = ', plugin.cookie('_csrf_csrf_token')); $.post(urlAdd, { token: plugin.cookie('_csrf_csrf_token') }, function(data) { console.log('kinoscript :: toggleFilmToFolder post = ', data); }); }, cookie: function(name) { let match = document.cookie.match(new RegExp('\b' + name + '=(.+)(;|$)')); console.log('kinoscript :: cookie = ', match); }, getCurrentFilm: function() { let match = location.href.match(/\/(film|series)\/(\d+)/); if (match) { return match[2]; } return '0'; }, missingElement: function(elemGetter, callback) { // Итерации 10 раз в секунду let missingOne = 100; // Ограничим количество попыток разумными пределами let maxIterCount = 3000; let elemTimer; let iterCount = 0; let missingHandler = () => { let elemList = elemGetter(); // Определим, что вышел элемент let elemStop = (elemList.length > 0); // Определим, что кончилось количество попыток let iterStop = (iterCount >= maxIterCount); if (elemStop || iterStop) { clearInterval(elemTimer); // Если элемент так и не появился if (!elemStop && iterStop) { console.log('kinoscript :: Нет элемента = ', elemGetter.toString()); return; } if (elemList.length == 1) { elemList = elemList.eq(0); } callback.call(window, elemList); } iterCount++; }; elemTimer = setInterval(missingHandler, missingOne); }, checkLocation: function () { let result = /(film|series)\/\d+\/?$/.test(location.pathname); return result; }, checkLibrary: function () { if (window.jQuery) { plugin.afterLoad(); } else { let tagJS = document.createElement('script'); tagJS.src = ('https://yastatic.net/jquery/3.3.1/jquery.min.js'); tagJS.onload = plugin.afterLoad; document.body.append(tagJS); } }, createChangeTimer: function() { $(window).on('kinochange', (evt) => { console.log('kinoscript :: kinochange [%o] = %o, jQuery = %o', location.href, evt, window.jQuery); }); let urlChanger = () => { if (!plugin.location) { plugin.location = location.href; } // Если адрес страницы изменился if (plugin.location != location.href) { $(window).trigger({ type: 'kinochange', oldValue: plugin.location, newValue: location.href }); plugin.location = location.href; } }; setInterval(urlChanger, 200); urlChanger(); }, afterLoad: function () { //window.jQuery.noConflict(); $ = window.jQuery; console.log('kinoscript :: jQuery = ', $); plugin.insertStyle(); plugin.createChangeTimer(); plugin.createFoldersButton(); }, start: function() { console.log('kinoscript :: plugin START [%o] = ', plugin.checkLocation(), location.href); //if (!plugin.checkLocation()) plugin.checkLibrary(); window.addEventListener('popstate', (evt) => { // Эксперимент показал, что popstate на сайте не вызывается, // хотя внешний вид страницы изменяется. Вместо него будет // кастомное событие kinochange console.log('kinoscript :: popstate [%o] = ', location.href, evt); }); } }; plugin.start(); console.log('Kinopoisk - Add to folder 💬 1.4'); })();