AO3: [Wrangling] UW Tag Snooze Buttons

Adds snooze buttons for unwrangled tags

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Greasemonkey lub Violentmonkey.

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Violentmonkey.

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Violentmonkey.

Aby zainstalować ten skrypt, wymagana będzie instalacja rozszerzenia Tampermonkey lub Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

Aby zainstalować ten skrypt, musisz zainstalować rozszerzenie menedżera skryptów użytkownika.

(Mam już menedżera skryptów użytkownika, pozwól mi to zainstalować!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

Będziesz musiał zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

Będziesz musiał zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

Musisz zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

(Mam już menedżera stylów użytkownika, pozwól mi to zainstalować!)

// ==UserScript==
// @name         AO3: [Wrangling] UW Tag Snooze Buttons
// @description  Adds snooze buttons for unwrangled tags
// @version      0.4

// @author       endofthyme
// @namespace    http://tampermonkey.net/
// @license      GPL-3.0 <https://www.gnu.org/licenses/gpl.html>

// @match        *://*.archiveofourown.org/tags/*/wrangle?*&status=unwrangled
// @require      https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js
// @grant        GM.getValue
// @grant        GM_getValue
// @grant	 GM.deleteValue
// @grant        GM_deleteValue
// ==/UserScript==

var DEFAULT_DAYS_TO_SNOOZE = 7;
var DRAFT_DAYS_TO_SNOOZE = 2;

var SHOW_CROSSOVER_FANDOMS = true;

// 1: hide snoozed, 2: hide unsnoozed, 3: show all tags
var DEFAULT_BUTTON_OPTION = 1;

// Set to true to migrate old GM_ map to new localStorage map.
// Set to false if you're encountering compatibility issues with GM_ functions.
var MIGRATION_IN_PROGRESS = true;

(function($) {

    if (MIGRATION_IN_PROGRESS) {
        var old_saved_date_map = GM_getValue('tags_saved_date_map', '{}');
        if (old_saved_date_map != '{}') {
            localStorage.setItem('tags_saved_date_map', old_saved_date_map);
            GM_deleteValue('tags_saved_date_map');
        }
    }

    var saved_date_map = localStorage.getItem('tags_saved_date_map');
    saved_date_map = saved_date_map == null ? new Map() : new Map(JSON.parse(saved_date_map));
    var today = new Date();
    clearOldSnoozes();

    console.log("Snoozes active:");
    console.log(saved_date_map);

    // Load icons
    var font_awesome_icons = document.createElement('script');
    font_awesome_icons.setAttribute('src', 'https://code.iconify.design/2/2.1.0/iconify.min.js');
    document.getElementsByTagName('head')[0].appendChild(font_awesome_icons);

    // add Snooze column header and snooze drafts button
    $('thead tr th:contains("Canonical")').before('<th scope="col">Snooze</th>');
    var snooze_draft_button = $('<ul class="actions" role="menu"><li><a id="snooze_drafts">Drafts</a></li></ul>');
    $("thead").find("th:contains('Snooze')").append(snooze_draft_button);

    // when snooze drafts button is pressed, check all tag pages, annotate, and snooze drafts
    $("a[id='snooze_drafts']").on("click", checkTagPages);

    // For each tag row on the page:
    $('tbody tr').each(function(i, row) {

        // Check if the tag's been snoozed.
        var tag_name = $(this).find("th[title='tag'] label").text();
        if (saved_date_map.has(tag_name) && new Date(saved_date_map.get(tag_name)) > today) {
            $(this).addClass('snoozed');

            // delete checkboxes for snoozed items (to prevent tags being wrangled accidentally)
            $(this).find("input[type='checkbox']").remove();
        } else {
            $(this).addClass('unsnoozed');
        }

        // Add snooze button for each tag.
        var snooze_button = $('<td title="snooze"><ul class="actions" role="menu"><li><a><span class="iconify" data-icon="mdi:sleep"></span></a></li></ul></td>');
        snooze_button.click(function() {
            addSnooze(tag_name, DEFAULT_DAYS_TO_SNOOZE);
        });
        var snoozecol = $(this).find('td[title="canonical?"]').before(snooze_button);
    });

    var snooze_banner = $('<div class="flash notice" id="snooze_banner">The following tags have been snoozed: </div>');

    var toggle_p = $('<p></p>').html('Show:&nbsp;&nbsp;');
    setUpToggleMenu();

    var style = $('<style type="text/css"></style>').appendTo($('head'));
    addCss(DEFAULT_BUTTON_OPTION);

    function setUpToggleMenu() {
        var only_unsnoozed_tags = $('<a style="font-weight: bold"></a>').html('[ unsnoozed ]');
        var only_snoozed_tags = $('<a></a>').html('[ snoozed ]');
        var all_tags = $('<a></a>').html('[ snoozed + unsnoozed ]');
        var clear_snoozes = $('<a></a>').html('[ clear all snoozes ]');

        only_unsnoozed_tags.click(() => onSnoozeSelection(only_unsnoozed_tags, 1));
        only_snoozed_tags.click(() => onSnoozeSelection(only_snoozed_tags, 2));
        all_tags.click(() => onSnoozeSelection(all_tags, 3));

        clear_snoozes.click(function() {
            saved_date_map = new Map();
            localStorage.removeItem('tags_saved_date_map');

            // Set all rows to unsnoozed on click.
            $('tbody tr').each(function(index) {
                $(this).removeClass('snoozed').addClass('unsnoozed');
            });
        });

        toggle_p.append(only_unsnoozed_tags, '&nbsp;&nbsp;', only_snoozed_tags, '&nbsp;&nbsp;',
                        all_tags, '&nbsp;&nbsp;-&nbsp;&nbsp;', clear_snoozes);
        $('#wrangulator').before(toggle_p);
    }

    function addSnooze(tag_name, days) {
        var tag_link_html = '';
        // Disappear the snoozed row.
        $('tbody tr').each(function(index) {
            if ($(this).find('th label').text() == tag_name) {
                $(this).removeClass('unsnoozed').addClass('snoozed');

                // delete checkboxes for snoozed items
                $(this).find("input[type='checkbox']").remove();

                // save tag link
                tag_link_html = "<a href='" + $(this).find("a[href$='/edit']").attr("href").replace(/'/g, "%27") + "'>" + tag_name + "</a>";
            }
        });

        var snoozedDate = new Date();
        snoozedDate.setDate(snoozedDate.getDate() + days);
        saved_date_map.set(tag_name, snoozedDate);
        localStorage.setItem('tags_saved_date_map', JSON.stringify(Array.from(saved_date_map.entries())));
        console.log(tag_name + ' snoozed to ' + snoozedDate);

        // Add snoozed tag to banner
        if ($('#snooze_banner').length) {
            snooze_banner.append(", " + tag_link_html);
        } else {
            snooze_banner.append(tag_link_html);
            $('#wrangulator').before(snooze_banner);
        }
    }

    function clearOldSnoozes() {
        localStorage.setItem('tags_saved_date_map',
                             JSON.stringify([...saved_date_map].filter(([k, v]) => new Date(v) > today)));
    }

    function onSnoozeSelection(button, css_option) {
        addCss(css_option);
        toggle_p.find('a').css('font-weight', 'normal');
        button.css('font-weight', 'bold');
        toggle_p.find('a').classList.remove('current');
        button.find('a').className = 'current';
    }

    // 1: hide snoozed, 2: hide unsnoozed, 3: show all tags
    function addCss(option) {
        var css_unsnoozed = '.snoozed {display: none;}';
        var css_snoozed = '.unsnoozed {display: none;}';

        switch (option) {
            case 1:
                style.html(css_unsnoozed);
                break;
            case 2:
                style.html(css_snoozed);
                break;
            default:
                style.html('');
        }
    }

    function checkTagPages() {
        // check each unsnoozed tag on page
        $("tbody tr.unsnoozed").each(function(i, row) {
            var tag_link = $(this).find("a[href$='/works']").attr("href").slice(0, -6);
            var taggings_cell = $(this).find("td[title='taggings']");
            var tag_name = $(this).find("th label").text();

            // check the tag's landing page
            $.get(tag_link, function(response) {
                // check for works
                if ($(response).find("div.work").length) {
                    // check for unrevealed works
                    var display_checkmark = true;
                    if ($(response).find("div.mystery").length) {
                        // check if there are any revealed works present
                        var total_works = $(response).find("li.work").length;
                        var total_unrevealed = $(response).find("div.mystery").length;
                        if (total_works == total_unrevealed) {
                            taggings_cell.append(" [unrevealed]");
                            display_checkmark = false;
                        }
                    }

                    // check author count
                    var authors = new Set();
                    $(response).find("div.work div.header").each(function(j, row2) {
                        var parsed_author = $(this).find("a[rel$='author']").first().text();
                        var check_pseud = parsed_author.match(/[^(]*\(([^)]*)\)/)
                        if (check_pseud) {
                            parsed_author = check_pseud[1]
                        }
                        if (parsed_author && parsed_author != "orphan_account") {
                            authors.add(parsed_author);
                        }
                    });

                    // check fandom count
                    var fandoms = new Set();
                    $(response).find("div.work div.header h5.fandoms a").each(function(j, row2) {
                        var fandom_name = $(this).text();
                        if (fandom_name != "Original Work") {
                            fandoms.add(fandom_name);
                        }
                    });

                    if (authors.size > 1 && fandoms.size > 1) {
                        taggings_cell.append(" [" + authors.size + " users/crossover]");
                        display_checkmark = false;
                    } else {
                        if (authors.size > 1) {
                            taggings_cell.append(" [" + authors.size + " users]");
                            display_checkmark = false;
                        }
                        if (fandoms.size > 1) {
                            taggings_cell.append(" [crossover]");
                            display_checkmark = false;
                            if (SHOW_CROSSOVER_FANDOMS) {
                                fandoms.forEach((value) => {
                                    taggings_cell.append("<br><small><span style='color:blue;'>" + value + "</span></small>");
                                });
                            }
                        }
                    }

                    if (display_checkmark) {
                        taggings_cell.append(" [\u2714]");
                    }

                // check for bookmarks
                } else if ($(response).find("div.bookmark").length) {
                    taggings_cell.append(" [bookmark]");

                // nothing there; is it canonical?
                } else if ($(response).find("p:contains('It\'s a common tag.')").length) {
                    taggings_cell.append(" [canonical]")

                // is it a syn?
                } else if ($(response).find("p:contains('has been made a synonym of')").length) {
                    taggings_cell.append(" [syn]")

                // must be a draft
                } else {
                    taggings_cell.append(" [draft]");
                    addSnooze(tag_name, DRAFT_DAYS_TO_SNOOZE);
                }

                var language = $(response).find("dd[class='language']").first().text();
                if (language != "English" && language != "") {taggings_cell.append(" - " + language)};
            });
        });

        // remove the button when finished
        $("ul").remove(":has(li a[id='snooze_drafts'])");
    }
})(jQuery);