您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Show your own ratings on other users ratings list
当前为
// ==UserScript== // @name ČSFD Compare // @version 0.3.4.1 // @namespace csfd.cz // @description Show your own ratings on other users ratings list // @author Jan Verner <[email protected]> // @icon http://img.csfd.cz/assets/b1733/images/apple_touch_icon.png // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js // @include *csfd.cz/* // ==/UserScript== Glob = { popupCounter: 0, popup: function (htmlContent, timeout = 3, width = 150) { var id = Glob.popupCounter++; if (!htmlContent) { return; } var yOffset = 10; $(".header-search").append(` <div class='SNPopup' id='SNPopup${id}' style=' border: 1px solid black; border-radius:4px; display:none; padding:10px; opacity:0.95; background:#820001; color:white; position:absolute; left:45%; width:${width}px; z-index:999; top:${yOffset}px; right:10px' >${htmlContent}</div>`); var $me = $(`#SNPopup${id}`); $me.slideDown(100); (function (id) { setTimeout(function () { $(`#SNPopup${id}`).slideUp(100); }, timeout * 1000); })(id); } }; (async () => { "use strict"; /* globals jQuery, $, waitForKeyElements */ /* jshint -W069 */ // const delay = ms => new Promise(res => setTimeout(res, ms)); const SCRIPTNAME = 'CSFD Compare'; class Csfd { constructor(csfdPage) { this.csfdPage = csfdPage; this.stars = {}; this.storageKey = undefined; this.userUrl = undefined; this.endPageNum = 0; this.userRatingsCount = 0; this.userRatingsUrl = undefined; this.localStorageRatingsCount = 0; // Ignore the ads... Make 'hodnoceni' table wider. $('.column.column-80').attr('class', '.column column-90'); } getEndPageNum(data) { console.log("fn: getEndPageNum()"); let $pagination = $(data).find('.box-content').find('.box-more-bar').find('.pagination')[0]; let lastPageHref = $($pagination).find('a:nth-last-child(2)').attr('href'); let foundMatch = lastPageHref.match(new RegExp("page=(.*)$")); let endPageNum = 0; if (foundMatch.length == 2) { endPageNum = parseInt(foundMatch[1]); } console.log(" return:", endPageNum); return endPageNum; } getCurrentUser() { console.log("fn getCurrentUser()"); let loggedInUser = $('.profile.initialized').attr('href'); if (typeof loggedInUser !== 'undefined') { if (loggedInUser.length == 1) { loggedInUser = loggedInUser[0]; } } console.log("loggedInUser:", loggedInUser); if (typeof loggedInUser === 'undefined') { console.log("Trying again..."); // [OLD Firefox] workaround (the first returns undefined....?) let profile = document.querySelectorAll('.profile'); if (profile.length == 0) { return undefined; } loggedInUser = profile[0].getAttribute('href'); console.log(`loggedInUser: ${loggedInUser}`); if (typeof loggedInUser === 'undefined') { console.error(`${SCRIPTNAME}: Can't find logged in username...`); throw (`${SCRIPTNAME}: exit`); // TODO: Popup informing user } } return loggedInUser; } getStars() { if (localStorage[this.storageKey]) { let stars = JSON.parse(localStorage[this.storageKey]); return stars; } } getCurrentFilmUrl() { console.log("fn: getCurrentFilmUrl()"); // Find "Diskuze" button and from it's a href extract /film/${URL}/diskuze let navItemHref = this.csfdPage.find('.tab-nav-item-9 > a').attr('href'); let foundMatch = navItemHref.match(new RegExp("film/" + "(.*)" + "/diskuze")); if (foundMatch == null) { console.error("TODO: nenaslo to... vyhledat jinym zpusobem!"); throw (`${SCRIPTNAME} Exiting...`); } let filmUrl = `/film/${foundMatch[1]}/`; return filmUrl; } updateInLocalStorage(ratingNum) { console.log("Checking if in LocalStorage..."); // Check if film is in LocalStorage let filmUrl = this.getCurrentFilmUrl(); console.log("filmUrl:", filmUrl); let item = this.stars[filmUrl]; // Item not in LocalStorage, add it then! if (typeof item === 'undefined') { console.log(`Item not in LocalStorage, adding... ${filmUrl}: ${ratingNum}`); this.stars[filmUrl] = ratingNum; localStorage.setItem(this.storageKey, JSON.stringify(this.stars)); return true; } if (item != ratingNum) { console.log(`LocalStorage rating [${item}] != current rating [${ratingNum}], updating...`); this.stars[filmUrl] = ratingNum; localStorage.setItem(this.storageKey, JSON.stringify(this.stars)); return true; } console.log(`Rating same in LocalStorage, everything ok`); return true; } removeFromLocalStorage() { console.log("fn: removeFromLocalStorage()"); console.log(" Deleting item from LocalStorage..."); // Check if film is in LocalStorage let filmUrl = this.getCurrentFilmUrl(); let item = this.stars[filmUrl]; // Item not in LocalStorage, everything is fine if (typeof item === 'undefined') { console.log(" Item not in LocalStorage, nothing happens"); return null; } // Item in LocalStorage, delete it from local dc delete this.stars[filmUrl]; // And resave it to LocalStorage console.log(" Resaving ratings into LocalStore"); localStorage.setItem(this.storageKey, JSON.stringify(this.stars)); return true; } checkLocalStorageRatings() { console.log("fun: checkLocalStorageRatings()"); //TODO: Duplicitni, nejak to sloucit... console.log("LOADING RATINGS..."); this.userUrl = this.getCurrentUser(); console.log("this.userUrl:", this.userUrl); this.storageKey = "CsfdCompare_" + this.userUrl.split("/")[2].split("-")[1]; console.log("this.storageKey", this.storageKey); // Try cache if (localStorage[this.storageKey]) { this.stars = JSON.parse(localStorage[this.storageKey]); } if (this.stars != {}) { return true; } return false; // // Cache does not exists... // if (Object.keys(this.stars).length == 0) { // Glob.popup("Načítam hodnocení..."); // // TODO: Add floating pregress notification {loading... 354/2049} // this.refresh(); // } } getCurrentFilmRating() { let $currentUserRating = this.csfdPage.find('.current-user-rating .stars'); // Exit if no user rating found if ($currentUserRating.length == 0) { return null; } // Ignore 'computed' ratings (exit) if ($currentUserRating.parent().hasClass('computed')) { console.log("Smula, computed...."); return null; } // Find the rating for (let num = 0; num <= 5; num++) { if ($currentUserRating.hasClass(`stars-${num}`)) { return num; } } // If not numeric rating, return 0 (Odpad!) if ($currentUserRating.find('.trash').length > 0) { return 0; } } refresh() { let url = this.userUrl + "hodnoceni/"; console.log(`REFRESHING... ${url}`); this.loadHodnoceniPage(url); } getCurrentUserRatingsCount() { console.log(`fn: getCurrentUserRatingsCount()`); let count = 0; let request = $.ajax({ type: "GET", url: this.userRatingsUrl, async: false }); request.done((data) => { // Get ratings: '(2 403)' let $countSpan = $(data).find('span.count'); console.log(` $countSpan: ${$countSpan}`); if ($countSpan.length == 1) { // Strip it '(2 403)' --> '2403' count = $countSpan[0].innerText.replace('(', '').replace(')', '').replace(/ +/g, '').replace(/\xA0/g, ''); count = parseInt(count); } }); console.log(` Returning count: ${count}`); return count; } getLocalStorageRatingsCount() { console.log(`fn: getLocalStorageRatingsCount()`); // this.storageKey = "CsfdCompare_" + this.userUrl.split("/")[2].split("-")[1]; console.log(" this.storageKey:", this.storageKey); if (localStorage[this.storageKey]) { let stars = JSON.parse(localStorage[this.storageKey]); let count = Object.keys(stars).length; console.log(" return:", count); return count; } return 0; } onOtherUserHodnoceniPage() { if (location.href.includes('/hodnoceni') && location.href.includes('/uzivatel/')) { if (!location.href.includes(this.userUrl)) { return true; } } return false; } exportRatings() { console.log(`fn: exportRatings()`); console.log(" this.storageKey:", this.storageKey); // console.log("JSON.stringify(this.stars):", JSON.stringify(this.stars)); localStorage.setItem(this.storageKey, JSON.stringify(this.stars)); if (this.onOtherUserHodnoceniPage()) { this.addRatingsColumn(); } } importRatings() { console.log(`fn: importRatings()`); if (localStorage[this.storageKey]) { this.stars = JSON.parse(localStorage[this.storageKey]); } } async REFRESH_RATINGS() { // Load user ratings... let $this = this; return new Promise((resolve, reject) => { console.log("fn: REFRESH_RATINGS()"); console.log(` Getting data from: '${$this.userRatingsUrl}'...`); $.ajax({ type: "GET", url: $this.userRatingsUrl, async: true }).done((data) => { // Get how many pages will the script load $this.endPageNum = $this.getEndPageNum(data); console.log(" $this.endPageNum:", $this.endPageNum); this.processRatingsPage(data); resolve(); }); }); } async processRatingsPage(dataHTML) { if (!dataHTML) { return; } var $stars = this.stars; $(dataHTML).find("tbody tr").each(function () { var $row = $(this); var filmURL = $("a.film-title-name", $row).attr("href"); var $rating = $("span .stars", $row); let starsRating = 0; for (let stars = 0; stars <= 5; stars++) { if ($rating.hasClass('stars-' + stars)) { starsRating = stars; } } // Add to dict $stars[filmURL] = starsRating; }); // Check if there is next page let nextPaginationURL = $(dataHTML).find("a.page-next").attr("href"); if (nextPaginationURL) { // Next page exists, fetch it and repeat this function, add new ratings to `this.stars` await this.loadPage(nextPaginationURL); } else { // No next page, finish... this.finishRefresh(); } } async loadPage(url) { console.log(`fn: loadPage(${url})`); return new Promise((resolve, reject) => { let foundMatch = url.match(new RegExp("page=(.*)$")); let currentNum = 1; if (foundMatch.length == 2) { currentNum = foundMatch[1]; } Glob.popup(`${SCRIPTNAME} - Nacitam... ${currentNum}/${this.endPageNum}`); $.ajax({ type: "GET", url: url, async: true }).done((data) => { this.processRatingsPage(data); resolve(); }); }); } finishRefresh() { console.log("fn: finishRefresh()"); this.exportRatings(); console.log(" Hotovo, hodnocení načteno"); Glob.popup(`Vaše hodnocení byla načtena.`); } addRatingsColumn() { console.log("fn: addRatingsColumn()"); let $page = this.csfdPage; let $tbl = $page.find('#snippet--ratings table tbody'); let starsDict = this.getStars(); $tbl.find('tr').each(function () { let $row = $(this); let url = $($row).find('.name').find('a').attr('href'); let ratingNum = starsDict[url]; let $span = ""; if (ratingNum == 0) { $span = `<span class="stars trash">odpad!</span>`; } else { $span = `<span class="stars stars-${ratingNum}"></span>`; } $row.find('td:nth-child(2)').after(` <td class="star-rating-only"> <span class="star-rating"> ${$span} </span> </td> `); }); } createRefreshButton() { let button = document.createElement("button"); button.innerHTML = `<span style="text-transform: initial;">CSFD-Compare reload<br>${this.localStorageRatingsCount}/${this.userRatingsCount}</span>`; button.className = "csfd-compare-reload"; // button.setAttribute("style", "margin-top: 3px; margin-left: 20px; align: right; font-size: 0.7em;"); // Add at the end of the user main-menu let menu = document.getElementsByClassName("main-menu")[0]; menu.insertBefore(button, menu.lastChild); // Add event to refresh all rating into LocalStorage on click $(button).on("click", function () { let csfd = new Csfd($('div.page-content')); csfd.userUrl = csfd.getCurrentUser(); csfd.userRatingsUrl = `${csfd.userUrl}/hodnoceni`; csfd.storageKey = `${SCRIPTNAME}_${csfd.userUrl.split("/")[2].split("-")[1]}`; csfd.REFRESH_RATINGS(); }); } openControlPanelOnHover() { let btn = $('.button-control-panel'); let panel = $('#dropdown-control-panel'); $(btn).on('hover mouseover', function () { if (!panel.hasClass('active')) { panel.addClass('active'); } }); $(panel).on('hover mouseover', function () { if (!panel.hasClass('active')) { panel.addClass('active'); } }); $(panel).on('mouseleave', function () { if (panel.hasClass('active')) { // setTimeout(function () { panel.removeClass('active'); // }, 500); } }); $(btn).on('mouseleave', function () { if (panel.hasClass('active')) { // setTimeout(function () { panel.removeClass('active'); // }, 500); } }); } hideControlPanel() { let btn = $('.button-control-panel'); btn.addClass('hidden'); } } // SCRIPT START let csfd = new Csfd($('div.page-content')); csfd.userUrl = csfd.getCurrentUser(); // Either logged in or not, do this... // If not logged in, hide control panel if (csfd.userUrl === undefined) { csfd.hideControlPanel(); } // If logged in, do some stuff if (csfd.userUrl !== undefined) { csfd.storageKey = `${SCRIPTNAME}_${csfd.userUrl.split("/")[2].split("-")[1]}`; csfd.userRatingsUrl = `${csfd.userUrl}/hodnoceni`; csfd.stars = csfd.getStars(); if (location.href.includes('/film/')) { let currentFilmRating = csfd.getCurrentFilmRating(); console.log("currentFilmRating:", currentFilmRating); if (currentFilmRating == null) { // Check if record exists, if yes, remove it csfd.removeFromLocalStorage(); } else { // Check if current page rating corresponds with that in LocalStorage, if not, update it csfd.updateInLocalStorage(csfd.getCurrentFilmRating()); } } csfd.userRatingsCount = csfd.getCurrentUserRatingsCount(); csfd.localStorageRatingsCount = csfd.getLocalStorageRatingsCount(); csfd.openControlPanelOnHover(); csfd.createRefreshButton(); // Show user that his 'user ratings' and 'local storage ratings' are not the same and he should refresh let ratingsCountOk = csfd.userRatingsCount == csfd.localStorageRatingsCount; console.log("ratingsCountOk:", ratingsCountOk); if (!ratingsCountOk) { console.warn(`Current ${csfd.userRatingsCount} != LocalStorage ${csfd.localStorageRatingsCount}.`); Glob.popup(` ${SCRIPTNAME}: Je třeba obnovit hodnocení<br> - váš počet: ${csfd.userRatingsCount}<br> - uloženo v prohlížeči: ${csfd.localStorageRatingsCount}<br> <b>Nastavení uživatele --> CSFD-Compare reload</b>`, 8, 310); } console.log("ratingsCountOk:", ratingsCountOk); if (ratingsCountOk) { // Show user ratings on any other user but mine if (csfd.onOtherUserHodnoceniPage()) { csfd.addRatingsColumn(); } } } })();