azusa_partner_wall

add wall to azusa

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name        azusa_partner_wall
// @namespace   https://greasyfork.org/users/1396048-moeruotaku
// @version     2025.03.14.98
// @description add wall to azusa
// @author      moeruotaku
// @license     MIT
// @match       https://azusa.wiki/torrents.php*
// @match       https://zimiao.icu/torrents.php*
// @icon        https://bgm.tv/img/favicon.ico
// @grant       unsafeWindow
// ==/UserScript==

(function () {
    'use strict';

    let table = document.querySelector('.torrents');
    if (!table) return;

    unsafeWindow = unsafeWindow ?? window;

    let cn = 'azusa_partner_wall_card'; // class namme
    let loading = 'https://s3.bmp.ovh/imgs/2025/03/14/8cf23d2cdb203b6f.gif';

    let buttons = document.querySelector('.azusa_partner_wall_buttons');
    if (!buttons) (buttons = table.parentNode.insertBefore(document.createElement('div'), table)).style['margin-bottom'] = '4px';
    buttons.innerHTML = `
<div style="display: inline-block; padding: 4px; color: #FFFFFF; border: 1px solid #CCCCCC; font-weight: bold; cursor: pointer" onclick="window.azusa_partner_wall_set_view('table')">列表</div>
<div style="display: inline-block; padding: 4px; color: #FFFFFF; border: 1px solid #CCCCCC; font-weight: bold; cursor: pointer" onclick="window.azusa_partner_wall_set_view('cards')">卡片</div>
<div name="azusa_partner_info" style="display: inline-block; font-size: 8pt; filter: opacity(0.2)"></div>
`;

    let cards = document.querySelector(`.${cn}s`);
    if (!cards) (cards = table.parentNode.insertBefore(document.createElement('div'), table)).className = `${cn}s`;
    cards.innerHTML = `<img src="${loading}" />`;

    let load_settings = () => JSON.parse(localStorage.getItem('azusa_partner') || '{}');
    let save_settings = (k, v) => localStorage.setItem('azusa_partner', JSON.stringify({ ...load_settings(), [k]: v }));

    (unsafeWindow.azusa_partner_wall_set_view = (view) => {
        buttons.children[0].style['background-color'] = view === 'table' ? '#FF9718' : '#CCCCCC';
        buttons.children[1].style['background-color'] = view === 'cards' ? '#FF9718' : '#CCCCCC';
        table.style.display = view === 'table' ? 'table' : 'none';
        cards.style.display = view === 'cards' ? 'flex' : 'none';
        save_settings('last_view', view);
    })(load_settings().last_view || 'table');

    if (!unsafeWindow.azusa_partner_wall_css) unsafeWindow.azusa_partner_wall_css = new CSSStyleSheet();
    if (!document.adoptedStyleSheets.includes(unsafeWindow.azusa_partner_wall_css)) document.adoptedStyleSheets.push(unsafeWindow.azusa_partner_wall_css);

    unsafeWindow.azusa_partner_callback = (data, info) => {
        document.querySelector('div[name=azusa_partner_info]').innerHTML = info;
        if (!data?.bgm_a2b?.version) return;
        let count = Math.floor(table.parentNode.clientWidth / 220);
        let card_width = Math.floor(table.parentNode.clientWidth / count) - 16;
        let card_height = Math.round(card_width * 1.5);

        let cat_names = { 402: 'Comic', 403: 'Light Novel', 404: 'Game', 407: 'CG', 409: 'Music' };
        let cat_colors = { 402: '#E195A3', 403: '#E49ACB', 404: '#AA96EB', 407: '#E7BC8F', 409: '#90C0EB' };

        unsafeWindow.azusa_partner_wall_css.replaceSync(`
#nexus-preview {
    border: 1px solid #000000;
}

.${cn}s {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
}

.${cn} {
    display: flex;
    flex-direction: column;
    width: ${card_width}px;
    margin: 8px;
    overflow: hidden;
    background-color: #F5F5F5;
    border-radius: 8px;
    box-shadow: 0 1px 2px -2px rgba(0, 0, 0, 0.32), 0 3px 6px 0 rgba(0, 0, 0, 0.24), 0 5px 12px 4px rgba(0, 0, 0, 0.18);
}

.${cn}:hover {
    box-shadow: 0 1px 2px -2px rgba(0, 0, 0, 0.64), 0 3px 6px 0 rgba(0, 0, 0, 0.48), 0 5px 12px 4px rgba(0, 0, 0, 0.36);
    transform: translateY(-4px);
}

.${cn}_cover {
    position: relative;
}

.${cn}_cover:hover .${cn}_mask_middle span {
    display: initial;
}

.${cn}_image {
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: ${card_height}px;
    overflow: hidden;
    background-color: #CCCCCC;
    background-image: url('${loading}');
    background-position: center;
    background-repeat: no-repeat;
}

.${cn}_image img {
    width: auto;
    height: 100%;
    object-fit: cover;
    object-position: center;
}

.${cn}_mask {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    pointer-events: none;
}

.${cn}_mask_top {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    pointer-events: auto;
}

.${cn}_mask_top_left {
    display: flex;
    flex-wrap: wrap;
    line-height: 1;
}

.${cn}_mask_top_left > div{
    background: rgba(255, 255, 255, 0.75);
}

.${cn}_mask_top_right {
    width: 24px;
    height: 24px;
    padding: 4px;
    text-align: center;
    font-size: 18px;
    color: #E800A4 !important;
    background-color: rgba(255, 255, 255, 0.75);
    border: 2px solid #E800A4;
    border-radius: 50%;
}

.${cn}_mask_middle {
    flex-grow: 1;
    display: flex;
    flex-wrap: wrap;
    align-content: flex-end;
    pointer-events: auto;
}

.${cn}_mask_middle span {
    display: none;
    padding: 0 4px;
    margin: 4px;
    color: #000000;
    background-color: rgba(255, 255, 255, 0.75);
    border: 1px solid #CCCCCC;
    border-radius: 2px;
}

.${cn}_mask_bottom {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    width: calc(100% - 8px);
    padding: 4px;
    background-color: rgba(0, 0, 0, 0.5);
}

.${cn}_mask_bottom span {
    border-radius: 2px !important;
}

.${cn}_title {
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    justify-content: space-evenly;
    margin-top: 2px;
    text-align: center;
}

.${cn}_footer {
    display: flex;
    justify-content: space-evenly;
    font-family: auto;
    white-space: nowrap;
}
`);

        let rows = Array.from(table.children[0].children);

        // ['类型', '封面', '标题', '评论数', '存活时间', '大小', '种子数/下载数/完成数']
        let headers = Array.from(rows[0].children).map((e) => e.children.length > 0 ? Array.from(e.children).map((e) => (e.children.length > 0 ? e.children[0].title : e.innerText)).join('/') : e.innerText);

        let bodies = rows.slice(1).map((tr) => {
            let o = {};
            Array.from(tr.children).forEach((td, i) => {
                if (false);
                else if (headers[i] === '类型') o.cat = td.querySelector('a')?.href?.replace(/^.*cat=([^&]+).*$/, '$1');
                else if (headers[i] === '封面') o.cover = td.querySelector('img')?.src;
                else if (headers[i] === '标题') {
                    o.href = td.querySelector('a')?.href || '#';

                    o.process = td.querySelector('td>div:last-child');
                    if (!o.process || o.process.getAttribute('name') === 'tags' || o.process.tagName === 'SPAN') o.process = undefined;

                    o.bgm_tags = td.querySelector('div[name=tags]');
                    o.bgm_tags = o.bgm_tags ? o.bgm_tags.innerText.split('|').filter((e) => e.length) : [];

                    o.bgm_score = td.querySelector('td[name=score]');
                    o.bgm_score = o.bgm_score ? `<a class="${cn}_mask_top_right" href="${o.bgm_score.querySelector('a')?.href || '#'}" title="评分">${o.bgm_score.innerText === 'N/A' ? '-' : o.bgm_score.innerText}</a>` : '';

                    let titles = Array.from(td.querySelector('td').childNodes);
                    let ai = titles.findIndex((e) => e.tagName === 'A');
                    let ii = titles.slice(ai).findIndex((e) => e.tagName === 'IMG');
                    let bi = titles.findIndex((e) => e.tagName === 'BR');
                    o.pins = titles.slice(0, ai).map((e) => e.outerHTML);
                    o.title = titles.slice(ai)[0].outerHTML;
                    o.free = ii !== -1 ? titles.slice(ai + ii, ai + ii + 3).map((e) => e.outerHTML).join('') : '';
                    o.tags = titles.slice(bi).filter((e) => e.tagName === 'SPAN').map((e) => e.outerHTML).join('');
                    o.info = titles.slice(bi).find((e) => e.nodeType === 3)?.textContent ?? '';
                    o.buttons = Array.from(td.querySelector('td:last-child').querySelectorAll('a')).map((e) => e.outerHTML).join('');
                } else if (headers[i] === '评论数') o.comment = td.innerHTML;
                else if (headers[i] === '存活时间') o.datetime = td.innerHTML.replace(/<br>/g, '');
                else if (headers[i] === '大小') o.size = td.innerText.replace(/\n/g, ' ');
                else if (headers[i] === '种子数/下载数/完成数') o.pt = td.innerHTML.replace(/<\/?b>/g, '').split(' / ').map((e, i) => e.replace(/(<a href="[^"]+">)?([0-9]+)(<\/a>)?/, `$1<span style="color: ${['green', 'red', 'black'][i]}">${['↑', '↓', '✓'][i]}$2<span>$3`)).join('');
                return td.innerHTML;
            });
            return o;
        });

        cards.innerHTML = '';

        bodies.forEach((body, i) => {
            cards.appendChild(document.createElement('div')).outerHTML = `
<div class="${cn}">
    <div class="${cn}_cover">
        <a class="${cn}_image" href="${body.href}">${body.cover ? `<img class="nexus-lazy-load preview" src="${body.cover}" />` : `<div style="width: ${card_width}px; height: ${card_height}px"></div>`}</a>
        <div class="${cn}_mask">
            <div class="${cn}_mask_top">
                <div class="${cn}_mask_top_left"><div>${body.free}</div><div>${body.pins.join('')}</div></div>
                ${body.bgm_score}
            </div>
            <a class="${cn}_mask_middle" href="${body.href}">${body.bgm_tags.map((e) => `<span>${e}</span>`).join('')}</a>
            <div class="${cn}_mask_bottom"><a href="torrents.php?cat=${body.cat}"><span style="background-color:${cat_colors[body.cat] ?? '#CCCCCC'};color:#FFFFFF;border-radius:0;font-size:12px;margin:0 4px 0 0;padding:1px 2px;pointer-events:auto">${cat_names[body.cat] ?? ''}</span></a>${body.tags}</div>
        </div>
    </div>
    <div class="${cn}_title">
        ${body.title}
        ${body.info ? `<div style="color: #555555; font-size: 8pt">${body.info}</div>` : ''}
    </div>
    ${body.process?.outerHTML ?? '<div style="padding: 1px; margin-top: 2px; border: 1px solid #F5F5F5"><div style="width: 100%; height: 2px; background-color: #AAAAAA"></div></div>'}
    <div class="${cn}_footer">
        <span style="color: blue">${body.size}</span>${body.datetime}${body.buttons}${body.pt}
    </div>
</div>
`;
            if (i < bodies.length - 1 && !body.pins.length !== !bodies[i + 1].pins.length) cards.appendChild(document.createElement('div')).outerHTML = `<div style="margin: 32px 0; width: 100%; height: 2px; background-color: #AAAAAA"></div>`;
        });
    };
})();