// ==UserScript== // @name Amazon eBook Mark // @namespace https://greasyfork.org/users/34380 // @version 20210724 // @description 标记已购的电子书。 // @match https://www.amazon.cn/* // @grant GM_setValue // @grant GM_getValue // @downloadURL https://update.greasyfork.icu/scripts/429768/Amazon%20eBook%20Mark.user.js // @updateURL https://update.greasyfork.icu/scripts/429768/Amazon%20eBook%20Mark.meta.js // ==/UserScript== (function () { 'use strict'; const is_autosave = GM_getValue('is_autosave', false); const loc = location.href; let asins_s = GM_getValue('asins_saved', []); let asins_a = GM_getValue('asins_added', []); if (loc.match(/\/kindle-dbs\/thankYouPage/) && is_autosave) { autoSaveBookPage(); } setTimeout(() => { addBookButton(); if (document.querySelector('#ng-app')) { saveAllBooksPage(); } else if (loc.match(/\/dp\//) || loc.match(/\/product\//)) { viewBookDetailPage(); } markBooksPage(); }, 5000); function addBookButton() { document.querySelector('#nav-xshop').insertAdjacentHTML('afterbegin', ` 添加书籍 `); document.querySelector('body').insertAdjacentHTML('afterbegin', `
`); document.querySelector('#display-panel').addEventListener('click', () => { document.querySelector('#fixed-panel').style.display = 'block'; }); document.querySelector('#refresh-page').addEventListener('click', () => { const nodes_added = document.querySelectorAll('.added'); for (const node of nodes_added) { const href = node.parentNode.href; const matched = href.match(/dp\/(\w+)\//) || href.match(/\/product\/(\w+)\?/); if (!asins_a.includes(matched[1])) { node.classList.remove('added'); } } markOwnedAdded(document); }); document.querySelector('#btn-add-book').addEventListener('click', () => { const input_link = document.querySelector('#book-link'); const asin = input_link.value.match(/\/dp\/(\w+)/) || input_link.value.match(/\/product\/(\w+)/); if (!asins_a.includes(asin[1])) { asins_a.push(asin[1]); GM_setValue('asins_added', asins_a); input_link.value = ''; input_link.setAttribute('placeholder', '添加成功'); } else { input_link.value = ''; input_link.setAttribute('placeholder', '已添加'); } }); document.querySelector('#btn-delete-book').addEventListener('click', () => { const input_link = document.querySelector('#book-link'); const asin = input_link.value.match(/\/dp\/(\w+)/) || input_link.value.match(/\/product\/(\w+)/); if (asins_a.includes(asin[1])) { asins_a.splice(asins_a.indexOf(asin[1]), 1); GM_setValue('asins_added', asins_a); input_link.value = ''; input_link.setAttribute('placeholder', '删除成功'); } else { input_link.value = ''; input_link.setAttribute('placeholder', '已删除'); } }); } function saveAllBooksPage() { document.querySelector('.myx-spacing-top-mini').insertAdjacentHTML('beforeend', `
已保存 ${asins_s.length} 本,添加已购 ${asins_a.length}本。
`); document.querySelector('#save-asins').addEventListener('click', () => { const items = document.querySelectorAll('.listItem_myx > div'); for (const item of items) { const asin = item.getAttribute('name').replace('contentTabList_', ''); if (!asins_s.includes(asin)) { asins_s.push(asin); } } GM_setValue('asins_saved', asins_s); document.querySelector('#saved').innerText = asins_s.length; }); document.querySelector('#clear-asins-added').addEventListener('click', () => { GM_setValue('asins_added', []); }); document.querySelector('#cb-autosave').checked = GM_getValue('is_autosave', false); document.querySelector('#cb-autosave').addEventListener('click', function () { GM_setValue('is_autosave', this.checked); }); } function autoSaveBookPage() { const asin_loc = loc.match(/asin=(\w+)&/)[1]; if (!asins_s.includes(asin_loc)) { asins_s.push(asin_loc); GM_setValue('asins_saved', asins_s); document.title = '已购电子书自动保存成功。'; } } function viewBookDetailPage() { const asin_loc = loc.match(/\/dp\/(\w+)/) || loc.match(/\/product\/(\w+)/); if (!asins_s.includes(asin_loc[1])) { document.querySelector('#title').insertAdjacentHTML('afterbegin', ` `); document.querySelector('#cb-add-book').checked = asins_a.includes(asin_loc[1]); document.querySelector('#cb-add-book').addEventListener('click', function () { if (this.checked) { asins_a.push(asin_loc[1]); GM_setValue('asins_added', asins_a); } else { asins_a.splice(asins_a.indexOf(asin_loc[1]), 1); GM_setValue('asins_added', asins_a); } }); } } function markBooksPage() { markOwnedAdded(document); const config = { attributes: false, childList: true, subtree: true }; const threadMutation = (mutationsList) => { for (let mutation of mutationsList) { if (mutation.type == 'childList' && mutation.addedNodes.length > 0) { for (let node of mutation.addedNodes) { if (node.nodeName == 'DIV') { markOwnedAdded(node); } } } } }; let container = document.querySelector("#a-page"); let threadObserver = new MutationObserver(threadMutation); threadObserver.observe(container, config); } function markOwnedAdded(node) { // 1/2 common top and bottom 3 search 4 recommend 5 bestseller 6 product const title_class1 = ['.acs-product-block__product-title', '.a-spacing-top-small > .a-link-normal', '.s-line-clamp-2 > .a-link-normal.a-text-normal']; const titles1 = node.querySelectorAll(title_class1.join(',')); for (const title of titles1) { const href = title.href; const asin = href.match(/\/dp\/(\w+)/)[1] ; if (asins_s.includes(asin)) { title.querySelector('*').classList.add('owned'); } else if (asins_a.includes(asin)) { title.querySelector('*').classList.add('added'); } } const title_class2 = ['.a-carousel-card > div > .a-link-normal:nth-last-of-type(1)', '.aok-inline-block.zg-item > .a-link-normal']; const titles2 = node.querySelectorAll(title_class2.join(',')); for (const title of titles2) { const href = title.href; const asin = href.match(/\/dp\/(\w+)/)[1]; if (asins_s.includes(asin)) { title.querySelector(':nth-child(2)').classList.add('owned'); } else if (asins_a.includes(asin)) { title.querySelector(':nth-child(2)').classList.add('added'); } } const title_class3 = ['.a-box-group.a-spacing-top-micro >.a-size-small.a-link-normal']; const titles3 = node.querySelectorAll(title_class3.join(',')); for (const title of titles3) { const href = title.href; const asin = href.match(/\/product\/(\w+)/)[1]; if (asins_s.includes(asin)) { title.classList.add('owned'); } else if (asins_a.includes(asin)) { title.classList.add('added'); } } } document.querySelector('head').insertAdjacentHTML('beforeend', ``); })();