// ==UserScript== // @name 时光机查询特定条目评价 // @namespace https://bgm.tv/group/topic/411925 // @version 0.2.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 // @downloadURL https://update.greasyfork.icu/scripts/520607/%E6%97%B6%E5%85%89%E6%9C%BA%E6%9F%A5%E8%AF%A2%E7%89%B9%E5%AE%9A%E6%9D%A1%E7%9B%AE%E8%AF%84%E4%BB%B7.user.js // @updateURL https://update.greasyfork.icu/scripts/520607/%E6%97%B6%E5%85%89%E6%9C%BA%E6%9F%A5%E8%AF%A2%E7%89%B9%E5%AE%9A%E6%9D%A1%E7%9B%AE%E8%AF%84%E4%BB%B7.meta.js // ==/UserScript== (function() { 'use strict'; const style = document.createElement('style'); style.innerHTML = ` div.userSynchronize.userSynchronizeSpecial { #subjectList { .tip { color: #666; } li:hover small { color: #EEE; } img.avatar { border-radius: 5px; } } input[type=search]:focus { &:focus { outline: none; } } select { color: #222; } } html[data-theme="dark"] div.userSynchronize.userSynchronizeSpecial { #subjectList { .tip { color: #d8d8d8; } small { color: #999; } li:hover small { color: #EEE; } } select { color: #e0e0e1; } } `; document.body.append(style); 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', 'userSynchronizeSpecial'); 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.enterkeyhint = 'search'; input.type = 'search'; input.autocomplete = 'false'; input.addEventListener('keydown', (event) => { if (event.key === 'Enter') searchAndRender(); }); 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'); searchSelect.onchange = searchAndRender; const searchBtn = makeBtn('🔍'); const makeSearching = () => document.createTextNode('搜索中……'); searchBtn.onclick = searchAndRender; const dataBtn = makeBtn('🆔'); dataBtn.onclick = async () => { const subject_id = input.value; if (!/\d+/.test(subject_id)) return; dataResult.innerHTML = '查询中……'; const collection = await getUserCollection(subject_id); const name = collection.subject?.name; renderCollection(collection, dataResult, `/subject/${ subject_id }`, name); } 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 = ` `; inner.style = `display: flex; flex-wrap: wrap;`; searchPanel.style.flex = '0 1 300px'; dataPanel.style.flex = '1 1 200px'; searchInputs.style = `width: fit-content; border-radius: 100px; box-shadow: none; border: 1px solid rgba(200, 200, 200, 0.5); background-color: rgba(255, 255, 255, 0.2);`; searchSelect.style = `font-size: 1em; padding: 4px 0 4px 5px; width: fit-content; border: none; outline: none; box-shadow: none; background-color: transparent; background-image: none; -webkit-appearance: none; -moz-appearance: none; appearance: none; border-radius: 0; border-right: 1px solid rgba(200, 200, 200, 0.5)`; input.style = `font-size: 1em; width: 120px; -webkit-appearance: none; -moz-appearance: none; box-shadow: none; background: transparent; line-height: 20px; border: none;`; synchronize.after(frag); async function searchAndRender() { const keyword = input.value; if (keyword === '') return; searchResult.innerHTML = ''; const searching = makeSearching(); searchResult.append(searching); const type = searchSelect.value; const data = await search(keyword, type); const list = data?.list; if (!list) { searchResult.innerText = '搜索失败'; return; } if (list.length === 0) { searchResult.innerText = '未找到相关条目'; return; } renderList(list, keyword, type, searchResult, async ({ href, textContent }) => { const subject_id = href.split('/').pop(); dataResult.innerHTML = '查询中……'; renderCollection((await getUserCollection(subject_id)), dataResult, href, textContent); }); searching.remove(); } function makeBtn(text) { const btn = document.createElement('a'); btn.href = 'javascript:;'; btn.innerText = text; btn.style = `text-wrap: nowrap; border: none; border-left: 1px solid rgba(200, 200, 200, 0.5); padding: 4px 5px; cursor: pointer;` return btn; } async function search(keyword, type, start=0) { try { const response = await fetch(`https://api.bgm.tv/search/subject/${encodeURI(keyword)}?type=${type}&max_results=10&start=${start}`); if (!response.ok) throw new Error(`API request ${ response.status } ${ response.statusText }`); return await response.json(); } catch (error) { console.error(error); return null; } } function listHTML(list) { return list.reduce((m, { id, type, images, name, name_cn }) => { type = ['书籍', '动画', '音乐', '游戏', '', '三次元'][type - 1]; const grid = images?.grid; m += `
${ rate ? `` : '' } ${updated_at.slice(0, 10)} / ${[`想${verb}`, `${verb}过`, `在${verb}`, '搁置', '抛弃'][type - 1]} ${ ep_status ? ` / ${ ep_status }${ eps ? ` / ${eps}` : ''}话 ` : ''} ${ vol_status ? ` / ${ vol_status }${ eps ? ` / ${volumes}` : ''}卷 ` : ''}
${ comment ? `