Nonogram tweaker

A script for listing unsolved nonograms of a category

2018-09-19 기준 버전입니다. 최신 버전을 확인하세요.

// ==UserScript==
// @name         Nonogram tweaker
// @namespace    http://tampermonkey.net/
// @version      1.0.1
// @description  A script for listing unsolved nonograms of a category
// @author       myklosbotond
// @match        http://www.nonograms.org/nonograms*
// @match        http://www.nonograms.org/nonograms2*
// @exclude      http://www.nonograms.org/nonograms/i/*
// @exclude      http://www.nonograms.org/nonograms2/i/*
// @require      https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js
// @grant        GM_addStyle
// ==/UserScript==

(function () {
    'use strict';
    const baseUrl = getCurrentBase();
    const lastPage = getLastPage();

    setupHtml();
    loadAllUnsolved(baseUrl, lastPage);
})();

function setupHtml() {
    GM_addStyle(`
        #unsolved-list-wrapper {
            position: absolute;
            top: 275px;
            right: 50px;
        }

        #unsolved-list {
            list-style-type: none;
            padding: 0;
            max-height: 500px;
            overflow: auto;
        }

        #unsolved-list li {
            text-align: center;
            border-bottom: 1px solid #eeeeee;
        }

        #unsolved-list li a {
            padding: 3px;
            display: block;
            transition-duration: .2s;
        }

        #unsolved-list li a:hover {
            background: #f4f4f4;
        }

        #unsolved-list li .page-link {
            padding: 6px 0;
        }

        li.page-link-li {
            border-bottom: 1px solid #9e9e9e !important;
        }

        a.page-link {
            color: #04259a;
            font-weight: bold;
        }

        #unsolved-list li:not(:last-child) {
            border-bottom: 1px solid #eeeeee;
        }

    `);

    const html = `
        <div id="unsolved-list-wrapper">
            <section id="unsolved-header">
                <h2>List of unsolved puzzles (<span id="unsolved-counter">0</span>):</h2>
            </section>
            <ul id="unsolved-list">
            </ul>
        </div>
    `;
    $('.content').append(html);
}

function loadAllUnsolved(baseUrl, lastPage) {
    const pagedUrl = `${baseUrl}/p/`;
    for (let i = 1; i <= lastPage; ++i) {
        loadUnsolvedFrom(pagedUrl + i, i);
    }
}

function loadUnsolvedFrom(url, pageNo) {
    fetch(url, {
        method: 'GET',
        credentials: 'include'
    })
        .then(resp => resp.text())
        .then(html => {
            const dom = $(html);
            const table = dom.find('.nonogram_list');
            const rows = table.find('> tbody > tr');

            const unsolvedRows = rows.filter(isUnsolvedRow);
            insertIntoList(unsolvedRows, url, pageNo);
        });
}

function insertIntoList(unsolvedRows, url, pageNo) {
    if (unsolvedRows.length > 0) {
        const list = $('#unsolved-list');

        list.append(pageLi(url, pageNo))

        const html = unsolvedRows
            .map(toLiElements)
            .get()
            .join('');
        list.append(html);

        const counter = $("#unsolved-counter");
        let count = counter.text();
        count = parseInt(count, 10);
        count += unsolvedRows.length;
        counter.text(count);
    }
}

function pageLi(pageUrl, pageNo) {
    return `<li class="page-link-li">
            <a href="${pageUrl}" class="page-link">Page ${pageNo}:</a>
        </li>`;
}

function toLiElements(_index, row) {
    row = $(row);
    const url = row.find('.nonogram_title').attr('href');
    const sId = url.match(/[0-9]+$/)[0];

    return `<li>
            <a href="${url}">#${sId}</a>
        </li>`;
}

function isUnsolvedRow(index, row) {
    row = $(row);

    if (row.has('.nonogram_title').length == 0) {
        return false;
    }

    const url = row.find('.nonogram_title').attr('href');
    const sId = url.match(/[0-9]+$/)[0];
    const id = parseInt(sId, 10);

    return !usrsvl.includes(id);
}

function getCurrentBase() {
    'use strict';

    const regex = /\/p\/[0-9]+$/;
    return window.location.href.replace(regex, '');
}

function getLastPage() {
    'use strict';

    const navWrapper = $('.pager div');
    const navLinks = navWrapper.children();
    const lastLink = navLinks.last();
    const lastText = lastLink.text();

    const nextRegex = /Next/;

    if (nextRegex.test(lastText)) {
        const lastNumber = navLinks.eq(-2);
        const lastNumText = lastNumber.text();
        if (lastNumText == '...') {
            const sPageNum = lastNumber.attr('href').match(/[0-9]+$/)[0];
            return parseInt(sPageNum, 10);
        }
        else {
            return parseInt(lastNumText, 10);
        }
    } else {
        const sPageNum = lastText.replace(/[\[\]]/g, '');
        return parseInt(sPageNum, 10);
    }
}