Hide Your Games on PSN

Search and hide games on PSN management site

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name               Hide Your Games on PSN
// @name:zh-CN         隐藏PSN游戏
// @namespace          http://tampermonkey.net/
// @version            0.2
// @description        Search and hide games on PSN management site
// @description:zh-CN  在PSN管理网页上搜索和隐藏游戏
// @author             Nathaniel Wu
// @include            *id.sonyentertainmentnetwork.com/*
// @license            Apache-2.0
// @grant              GM_addStyle
// @supportURL         https://github.com/Nathaniel-Wu/userscript-hide-psn-games/issues
// ==/UserScript==

(function () {
    'use strict';
    const text_tags = {
        text_search: 0,
        regex_search: 1,
        cancel: 2,
        game_found: 3,
        total_games_found: 4,
        game_classifier: 5,
        new_games_ready_to_be_hidden: 6,
        save_reminder: 7
    }
    const localization = {
        "zh-Hans": ['文本搜索', '正则表达式搜索', '取消', '游戏已找到:', '共找到:', '款', '可供隐藏的新游戏:', '点击保存按钮隐藏'],
        "zh-Hant": ['文本搜索', '正則表達式搜索', '取消', '遊戲已找到:', '共找到:', '款', '可供隱藏的新遊戲:', '點擊保存按鈕隱藏'],
        "en-US": ['Text Search', 'RegEx Search', 'Cancel', 'Game Found: ', 'Total Game(s) Found: ', '', 'New Games(s) Ready To Be Hidden: ', 'Click the Save button to hide the game(s)']
    };
    function localized_text(text_tag) {
        let site_lang = document.documentElement.lang;
        let lang = localization.hasOwnProperty(site_lang) ? site_lang : "en-US";
        return localization[lang][text_tag];
    }
    function repeat_until_successful(function_ptr, interval) {
        if (!function_ptr())
            setTimeout(() => {
                repeat_until_successful(function_ptr, interval);
            }, interval);
    }
    function search_and_hide_game(pattern) {
        let regex_search = typeof (pattern) === 'object';
        let lower_case_pattern = null;
        if (!regex_search)
            lower_case_pattern = pattern.toLowerCase();
        let game_titles = [];
        let new_games_ready_to_be_hidden = 0;
        repeat_until_successful(() => {
            let found = false;
            let load_more_button_container_candidates = Array.prototype.slice.call(document.querySelectorAll('div.columns-center.fitting-width, ul#ps4-games-list'));
            let UL_index = load_more_button_container_candidates.findIndex((e) => e.tagName === 'UL');
            let game_elements = load_more_button_container_candidates[UL_index].querySelectorAll('.pdr-list-column.main-text.ps4-game-name-text.text-selectionitem');
            game_elements.forEach((e) => {
                if (e === game_elements[game_elements.length - 1] && !found)
                    e.scrollIntoView();
                if (regex_search) {
                    if (!Boolean(e.innerHTML.match(pattern)))
                        return;
                } else {
                    if (!Boolean(e.innerHTML.toLowerCase().match(lower_case_pattern)))
                        return;
                }
                found = true;
                let parent = e;
                while (parent.classList.length != 2 || (!parent.classList.contains('pdr-list-item')) || ((!parent.classList.contains('gamelist-check-on')) && (!parent.classList.contains('gamelist-check-off'))))
                    parent = parent.parentElement;
                let not_checked_before;
                if (not_checked_before = parent.classList.contains('gamelist-check-off')) {
                    parent.querySelector('.pdr-list-item.inner-list-item.list-thumbnail.check-box-item.game-list').click();
                    new_games_ready_to_be_hidden++;
                }
                let game_title = e.innerText;
                if (game_titles.indexOf(game_title) < 0) {
                    game_titles.push(game_title);
                    console.log(`${localized_text(text_tags.game_found)}${game_title}${not_checked_before ? '✅' : ''}`);
                    e.scrollIntoView();
                }
            });
            if (UL_index != load_more_button_container_candidates.length - 1) {
                load_more_button_container_candidates[UL_index + 1].querySelector('button.secondary-button.row-button.text-button').click();
                return false;
            } else {
                let alert_message = `${localized_text(text_tags.total_games_found)}${game_titles.length}${localized_text(text_tags.game_classifier)}
${localized_text(text_tags.new_games_ready_to_be_hidden)}${new_games_ready_to_be_hidden}${localized_text(text_tags.game_classifier)}
${localized_text(text_tags.save_reminder)}`
                console.log(alert_message);
                alert(alert_message);
                return true;
            }
        }, 3500 + Math.random() * 1000);
    }
    window.addEventListener('popstate', () => {
        if (Boolean(window.location.href.match(/privacy_settings\/group\/games\/hidden_games/))) {
            const search_menu = document.createElement('div');
            search_menu.id = 'search_menu';
            search_menu.innerHTML = `
                <div class="columns-center">
                    <form>
                        <input type="text" id="search_pattern" value="">
                        <div data-components="pdr-button" class="column-flex button ember-view">
                            <button id="text_search_button" tabindex="0" class="primary-button row-button text-button">
                                <span dir="ltr" class="caption">${localized_text(text_tags.text_search)}</span>
                            </button>
                        </div>
                        <div data-components="pdr-button" class="column-flex button ember-view">
                            <button id="regex_search_button" tabindex="0" class="primary-button row-button text-button">
                                <span dir="ltr" class="caption">${localized_text(text_tags.regex_search)}</span>
                            </button>
                        </div>
                        <div data-components="pdr-button" class="column-flex button ember-view">
                            <button id="cancel_button" tabindex="0" class="secondary-button row-button text-button">
                                <span dir="ltr" class="caption">${localized_text(text_tags.cancel)}</span>
                            </button>
                        </div>
                    </form>
                </div>
            `;
            document.querySelector('body').appendChild(search_menu);
            document.querySelector('#text_search_button').onclick = () => {
                let pattern = document.querySelector('#search_pattern').value;
                setTimeout(() => search_and_hide_game(pattern), 200);
                search_menu.remove();
            };
            document.querySelector('#regex_search_button').onclick = () => {
                let pattern = new RegExp(document.querySelector('#search_pattern').value);
                setTimeout(() => search_and_hide_game(pattern), 200);
                search_menu.remove();
            };
            document.querySelector('#cancel_button').onclick = () => {
                search_menu.remove();
            };
            GM_addStyle(`
                #search_menu {
                    position: absolute;
                    display: block;
                    padding: 10px;
                    background: #f0f0f0;
                    z-index: 999;
                    left: 50%;
                    top: 50%;
                    margin-left: -97px;
                    margin-top: -80px;
                }
            `);
        }
    });
})();