Greasy Fork is available in English.

Contests helper

Показывает сколько кандидатов из турнира есть в твоих списках.

Verze ze dne 21. 02. 2025. Zobrazit nejnovější verzi.

// ==UserScript==
// @name         Contests helper
// @icon         https://www.google.com/s2/favicons?domain=shikimori.me
// @namespace    https://shikimori.one
// @version      1.4
// @description  Показывает сколько кандидатов из турнира есть в твоих списках.
// @author       LifeH
// @match        *://shikimori.org/*
// @match        *://shikimori.one/*
// @match        *://shikimori.me/*
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';
      const CopyBtnI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABN2lDQ1BBZG9iZSBSR0IgKDE5OTgpAAAokZWPv0rDUBSHvxtFxaFWCOLgcCdRUGzVwYxJW4ogWKtDkq1JQ5ViEm6uf/oQjm4dXNx9AidHwUHxCXwDxamDQ4QMBYvf9J3fORzOAaNi152GUYbzWKt205Gu58vZF2aYAoBOmKV2q3UAECdxxBjf7wiA10277jTG+38yH6ZKAyNguxtlIYgK0L/SqQYxBMygn2oQD4CpTto1EE9AqZf7G1AKcv8ASsr1fBBfgNlzPR+MOcAMcl8BTB1da4Bakg7UWe9Uy6plWdLuJkEkjweZjs4zuR+HiUoT1dFRF8jvA2AxH2w3HblWtay99X/+PRHX82Vun0cIQCw9F1lBeKEuf1UYO5PrYsdwGQ7vYXpUZLs3cLcBC7dFtlqF8hY8Dn8AwMZP/fNTP8gAAAAJcEhZcwAAAE8AAABPAWOK/dcAAAXRaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0MiA3OS4xNjA5MjQsIDIwMTcvMDcvMTMtMDE6MDY6MzkgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE4IChXaW5kb3dzKSIgeG1wOkNyZWF0ZURhdGU9IjIwMjUtMDEtMzFUMDI6Mzg6MjMrMDE6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDI1LTAxLTMxVDAyOjU4OjUxKzAxOjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDI1LTAxLTMxVDAyOjU4OjUxKzAxOjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo2YWFkNjQ5Zi0yZjgzLTFhNGMtYjRlNi0wNTVjOWUyYTE2YTgiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDpiYzY3YzUwMS0yOWE4LTAwNDctYjIzYy04Mjg5NDQwMWVhZWEiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDplYWE5Njg2Zi0zYzM5LWUzNDUtODQwMi1kYzM3YTIyYThmYWQiPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOmVhYTk2ODZmLTNjMzktZTM0NS04NDAyLWRjMzdhMjJhOGZhZCIgc3RFdnQ6d2hlbj0iMjAyNS0wMS0zMVQwMjozODoyMyswMTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTggKFdpbmRvd3MpIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo2YWFkNjQ5Zi0yZjgzLTFhNGMtYjRlNi0wNTVjOWUyYTE2YTgiIHN0RXZ0OndoZW49IjIwMjUtMDEtMzFUMDI6NTg6NTErMDE6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE4IChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5BTpLUAAAAz0lEQVQ4jc3SMUuCURjF8Z/2OjlY30IQ5yAnF1EIGhrDyQ/iB2ipOQoXN8FRF0GCaA8awo8QKO5qDb5DvNzuW04euMvDc/73nMstzCZj6KCBxO/6xBNWP4dJah5him0E0MYlmlnAeWq+jpihhofssIgCNjlmeMdFCJBVz77nV+Rs8Yyz0KPdoo+XSJoiHtENASqY4y0CgAVOQxX+peMArFFF/VDAAEsMDwEkqbmZtxhLkNUOJ3+8fBf6B6/2tT4i5hJauAsBrnCDck6Ce8y/AVeuKCJx/FChAAAAAElFTkSuQmCC";
      const CopyBtnSelI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABN2lDQ1BBZG9iZSBSR0IgKDE5OTgpAAAokZWPv0rDUBSHvxtFxaFWCOLgcCdRUGzVwYxJW4ogWKtDkq1JQ5ViEm6uf/oQjm4dXNx9AidHwUHxCXwDxamDQ4QMBYvf9J3fORzOAaNi152GUYbzWKt205Gu58vZF2aYAoBOmKV2q3UAECdxxBjf7wiA10277jTG+38yH6ZKAyNguxtlIYgK0L/SqQYxBMygn2oQD4CpTto1EE9AqZf7G1AKcv8ASsr1fBBfgNlzPR+MOcAMcl8BTB1da4Bakg7UWe9Uy6plWdLuJkEkjweZjs4zuR+HiUoT1dFRF8jvA2AxH2w3HblWtay99X/+PRHX82Vun0cIQCw9F1lBeKEuf1UYO5PrYsdwGQ7vYXpUZLs3cLcBC7dFtlqF8hY8Dn8AwMZP/fNTP8gAAAAJcEhZcwAAAE8AAABPAWOK/dcAAAahaVRYdFhNTDpjb20uYWRvYmUueG1wAAAAAAA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjYtYzE0MiA3OS4xNjA5MjQsIDIwMTcvMDcvMTMtMDE6MDY6MzkgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE4IChXaW5kb3dzKSIgeG1wOkNyZWF0ZURhdGU9IjIwMjUtMDEtMzFUMDI6Mzg6MjMrMDE6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDI1LTAxLTMxVDAyOjU5OjIzKzAxOjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDI1LTAxLTMxVDAyOjU5OjIzKzAxOjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3MzA2ZWI4NC05YThjLTYzNDktOTA2MC1iYzRjZGU3NWExNDYiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDo5ZTI3OTc1Ny1kODk4LTc0NGUtOGM3MC0xNjBhZDc5ODg3N2YiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDozMGYyYzIwOC0wZGRiLWYzNDktODVjNi01NzQ0ZWUxNDFjZGMiPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjMwZjJjMjA4LTBkZGItZjM0OS04NWM2LTU3NDRlZTE0MWNkYyIgc3RFdnQ6d2hlbj0iMjAyNS0wMS0zMVQwMjozODoyMyswMTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTggKFdpbmRvd3MpIi8+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoyOWRmOWVkNC0wOTM3LTExNGItOGIxNS04MTI5ZTFhNTJlOTUiIHN0RXZ0OndoZW49IjIwMjUtMDEtMzFUMDI6NTk6MjMrMDE6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE4IChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6NzMwNmViODQtOWE4Yy02MzQ5LTkwNjAtYmM0Y2RlNzVhMTQ2IiBzdEV2dDp3aGVuPSIyMDI1LTAxLTMxVDAyOjU5OjIzKzAxOjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+2wWMfwAAANBJREFUOI3N0rFKQlEcx/GPdp0azLcQwjnI6S6SEDQ4SlMv4Bv4AC01i9Hi5gM0ShDugUP0CIHi7jUH7yCX07nl1A/O8uf/+57f73Aq2aAJXbSR+FlfeMLqcJjk5ilekEUAV7hGWgRc5OZexAznGBWHVVSwKTHDApchQFF39j2/IyfDKxqhR7vHEG+RNFWMcRsC1DHDewQAnzgLVfiT/gdgjSZaxwKescTkGECSm9OyxViCorY4+eXl29A/mNvX+oiYa+jgIQS4QR+nJQkeMdsBGJMnlGUPSdMAAAAASUVORK5CYII=";
  
  function main() {
        const path = window.location.pathname;
        if (!path.startsWith('/contests/')) {
            return;
        }
  
        const entries = document.querySelectorAll('.c-column.b-catalog_entry.c-anime, .c-column.b-catalog_entry.c-manga');
        if (entries.length === 0) {
            return;
        }
  
        const list = {
            'completed': 0,
            'planned': 0,
            'dropped': 0,
            'on_hold': 0,
            'watching': 0,
            'rewatching': 0,
            'no_list': 0
        };
  
        const colors = {
            'completed': '#419541',
            'planned': '#176093',
            'dropped': '#FC575E',
            'on_hold': '#7b8084',
            'watching': '#176093',
            'rewatching': '#176093',
            'no_list': '#000'
        };
  
        const entryIds = new Set();
  
        entries.forEach(article => {
            const entryId = article.getAttribute('id');
            if (entryIds.has(entryId)) {
                return;
            }
  
            entryIds.add(entryId);
  
            let found = false;
            for (let key in list) {
                if (article.classList.contains(key)) {
                    list[key]++;
                    found = true;
                    break;
                }
            }
            if (!found) {
                list['no_list']++;
            }
        });
  
        showR(list, entryIds.size, colors);
    }
  
    function showR(list, size, colors) {
        const existingContainer = document.querySelector('.list-container');
        if (existingContainer) {
            existingContainer.remove();
        }
  
        const container = document.createElement('div');
        container.classList.add('list-container');
        container.style.marginTop = '20px';
        container.style.fontSize = '32px';
        container.style.padding = '30px';
        container.style.maxWidth = '250px';
        container.style.position = 'relative';
  
        let resultHTML = '';
        let clipboardText = '';
  
        Object.entries(list).forEach(([key, value]) => {
            if (value > 0) {
                resultHTML += `
                <div class="b-add_to_list ${key}">
                    <div class="trigger">
                        <span class="status-name">${getStatusName(key)}&nbsp;&nbsp;–&nbsp;&nbsp;${value}</span>
                    </div>
                </div>`;
                clipboardText += `[color=${colors[key]}][b]${getStatusName(key)}[/b][/color] – ${value}\n`;
            }
        });
  
        container.innerHTML = resultHTML;
        addCopyButton(container, clipboardText);
  
        const element = document.querySelector('.b-contests-menu');
        if (element) {
            element.parentNode.appendChild(container);
        }
    }
  
    function addCopyButton(container, text) {
        let button = document.createElement("span");
        button.classList.add("copy-list-button");
        button.title = "Скопировать";
        button.style.backgroundImage = `url(${CopyBtnI})`;
        button.style.backgroundRepeat = "no-repeat";
        button.style.backgroundSize = "contain";
        button.style.width = "16px";
        button.style.height = "16px";
        button.style.cursor = "pointer";
        button.style.position = "absolute";
        button.style.top = "5px";
        button.style.right = "5px";
        button.style.zIndex = "10";
  
        button.onmouseover = () => button.style.backgroundImage = `url(${CopyBtnSelI})`;
        button.onmouseout = () => button.style.backgroundImage = `url(${CopyBtnI})`;
  
        button.onclick = (event) => {
            event.stopPropagation();
            event.preventDefault();
            navigator.clipboard.writeText(text).then(() => {
                button.style.transform = "scale(1.1)";
                setTimeout(() => button.style.transform = "scale(1)", 200);
            }).catch(err => console.error(err));
        };
  
        container.appendChild(button);
    }
  
   function getStatusName(status) {
        const names = {
            'planned': 'Запланировано',
            'dropped': 'Брошено',
            'on_hold': 'Отложено',
            'watching': 'Смотрю',
            'rewatching': 'Пересматриваю',
            'completed': 'Просмотрено',
            'no_list': 'Не в списках'
        };
        return names[status] || status;
    }
  
    function ready(fn) {
        document.addEventListener('page:load', fn);
        document.addEventListener('turbolinks:load', fn);
        if (document.attachEvent ? document.readyState === "complete" : document.readyState !== "loading") {
            fn();
        } else {
            document.addEventListener('DOMContentLoaded', fn);
        }
    }
  
    ready(main);
  
  })();