Greasy Fork

Greasy Fork is available in English.

时光机查询特定条目评价

经济的同步率查询

当前为 2024-12-13 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         时光机查询特定条目评价
// @namespace    https://bgm.tv/group/topic/411925
// @version      0.0.1
// @description  经济的同步率查询
// @author       mmv
// @include      /^https?:\/\/(((fast\.)?bgm\.tv)|chii\.in|bangumi\.tv)\/user\/[^/]+$/
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bgm.tv
// @license      MIT
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const username = location.pathname.split('/').pop();
    const synchronize = document.querySelector('.userSynchronize');
    if (!synchronize) return;
    const frag = document.createDocumentFragment();

    const box = document.createElement('div');
    box.classList.add('userSynchronize');

    const inner = document.createElement('div');

    const title = document.createElement('h3');
    title.textContent = '特定同步率';

    const searchPanel = document.createElement('div');
    const dataPanel = document.createElement('div');
    const searchInputs = document.createElement('div');

    const input = document.createElement('input');
    input.classList.add('inputtext');
    input.type = 'text';
    input.placeholder = '条目ID查看或条目名搜索';
    input.style.width = 'auto';
    input.style.fontSize = '1em';

    const searchResult = document.createElement('div');
    searchResult.classList.add('subjectListWrapper');
    searchResult.style = `
      max-height: 200px;
      overflow-y: scroll;
    `;
    const dataResult = document.createElement('div');

    const searchSelect = document.createElement('select');

    const searchBtn = makeBtn('搜索');
    searchBtn.onclick = async () => {
        const keyword = input.value;
        if (keyword === '') return;
        searchResult.innerText = '搜索中……';
        const data = await search(keyword, searchSelect.value);
        renderList(data, searchResult, async (href) => {
            const subject_id = href.split('/').pop();
            console.log(subject_id)
            renderCollection((await getUserCollection(subject_id)), dataResult);
        });
    }

    const dataBtn = makeBtn('查看评价');
    dataBtn.onclick = async () => {
        const subject_id = input.value;
        if (!/\d+/.test(subject_id)) return;
        renderCollection((await getUserCollection(subject_id)), dataResult);
    }

    frag.append(box);
    box.append(title, inner);
    inner.append(searchPanel, dataPanel);
    searchPanel.append(searchInputs, searchResult);
    searchInputs.append(searchSelect, input, searchBtn, dataBtn);
    dataPanel.append(dataResult);
    searchSelect.innerHTML = `<option value="all">全部</option>
                              <option value="2">动画</option>
                              <option value="1">书籍</option>
                              <option value="4">游戏</option>
                              <option value="3">音乐</option>
                              <option value="6">三次元</option>`;
    inner.style = `
      display: flex;
      flex-wrap: wrap;
    `;
    searchPanel.style.flex = '0 1 300px';
    dataPanel.style.flex = '1 1 200px';
    searchSelect.style = `
      background: transparent;
      border: none;
      padding: 0 5px;
      font-size: 1em;
    `;

    synchronize.after(frag);

    function makeBtn(text) {
        const btn = document.createElement('a');
        btn.classList.add('chiiBtn');
        btn.href = 'javascript:;';
        btn.innerText = text;
        btn.style.textWrap = 'nowrap';
        return btn;
    }

    async function search(keyword, type) {
        const response = await fetch(`https://api.bgm.tv/search/subject/${encodeURI(keyword)}?type=${type}`);
        if (!response.ok) throw new Error('API request failed');
        return await response.json();
    }

    function renderList(data, container, clickHandler) {
        const { list } = data;
        if (!list) {
            container.textContent = '搜索失败';
            return;
        }
        const html = `<ul id="subjectList" class="subjectList ajaxSubjectList">
        ${ list.reduce((m, { id, type, images, name, name_cn }) => {
            type = ['书籍', '动画', '音乐', '游戏', '', '三次元'][type - 1];
            const grid = images?.grid;
            m += `<li class="clearit">
                    <a href="/subject/${id}" class="avatar h">
                      ${grid ? `<img src="${grid}" class="avatar ll">` : ''}
                    </a>
                    <div class="inner">
                      <small class="grey rr">${type}</small>
                      <p><a href="/subject/${id}" class="avatar h">${name}</a></p>
                      <small class="tip">${name_cn}</small>
                    </div>
                  </li>`;
            return m;
        }, '') }
        </ul>`;
        container.innerHTML = html;
        container.querySelectorAll('a').forEach(a => {
            a.addEventListener('click', e => {
                e.preventDefault();
                clickHandler(a.href);
            });
        });
    }

    async function getUserCollection(subject_id) {
        const response = await fetch(`https://api.bgm.tv/v0/users/${username}/collections/${subject_id}`);
        if (response.ok) {
            const data = await response.json();
            return data;
        } else if (response.status === 404) {
            const data = { not_found: true }
            return data;
        } else {
            throw new Error('Network response was not ok: ', response);
        }
    }

    function renderCollection(data, container) {
        const { not_found, rate, comment, updated_at, ep_status, vol_status, subject } = data;
        if (not_found) {
            container.textContent = '未找到本作标记';
            return;
        }
        const { id, type, name, name_cn, volumes, eps } = subject;
        const verb = ['读', '看', '听', '玩', '', '看'][type - 1];
        const html = `<li id="item_${id}" class="item even clearit">
                        <div class="inner" style="margin-left: 10px">
                        <h3>
                          ${ name_cn ? `<a href="/subject/${id}" class="l">${name_cn}</a> <small class="grey">${name}</small>`
                                     : `<a href="/subject/${id}" class="l">${name}</a>`
                          }
                        </h3>
                        <p class="collectInfo">
                          ${ rate ? `<span class="starstop-s"><span class="starlight stars${rate}"></span></span>`
                                  : ''
                          }
                          <span class="tip_j">${updated_at}</span>
                          <span class="tip_i">/</span>
                          <span class="tip"> ${[`想${verb}`, `${verb}过`, `在${verb}`, '搁置', '抛弃'][type-1]}</span>
                          ${ ep_status ? `
                          <span class="tip_i">/</span>
                          <span class="tip">
                          ${ ep_status }${ eps ? ` / ${eps}` : ''}话
                          </span>
                          ` : ''}
                          ${ vol_status ? `
                          <span class="tip_i">/</span>
                          <span class="tip">
                          ${ vol_status }${ eps ? ` / ${volumes}` : ''}卷
                          </span>
                          ` : ''}
                        </p>
                        ${ comment ? `
                          <div id="comment_box"><div class="item"><div class="text_main_even" style="float:none;width:unset">
                            <div class="text"> ${comment}</div>
            		        <div class="text_bottom"></div>
            		      </div></div></div></div>
                        ` : '' }
                    </li>`;
        container.innerHTML = html;
    }
})();