您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
ふたばちゃんねるのスレッド上で貼られたAmazonのURLからtitleとあれば画像を取得する
当前为
- // ==UserScript==
- // @name buyNow!
- // @namespace http://2chan.net/
- // @version 0.1.2
- // @description ふたばちゃんねるのスレッド上で貼られたAmazonのURLからtitleとあれば画像を取得する
- // @author ame-chan
- // @match https://*.2chan.net/b/res/*
- // @match https://kako.futakuro.com/futa/*
- // @match https://tsumanne.net/si/data/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=2chan.net
- // @grant GM_xmlhttpRequest
- // @connect https://amazon.co.jp/*
- // @connect https://www.amazon.co.jp/*
- // @connect https://amzn.to/*
- // @connect https://amzn.asia/*
- // @license MIT
- // ==/UserScript==
- (function () {
- 'use strict';
- const WHITE_LIST_URLS = [
- 'https://amazon.co.jp/',
- 'https://www.amazon.co.jp/',
- 'https://amzn.to/',
- 'https://amzn.asia/',
- ];
- const isAmazon = (path) => ['amazon.co.jp', 'amzn.to', 'amzn.asia'].some((url) => path.includes(url));
- const WHITE_LIST_SELECTORS = (() => WHITE_LIST_URLS.map((url) => `a[href^="${url}"]`).join(','))();
- const isProductPage = (url) =>
- /https:\/\/(www\.)?amazon\.co\.jp\/.*(?:gp\/product|dp)\/[A-Z0-9]{10}/.test(url) ||
- /https:\/\/amzn.(asia|to)\//.test(url);
- const addedStyle = `<style id="userjs-get-title-link">
- .userjs-title {
- display: block;
- margin: 8px 0 16px;
- padding: 8px 16px;
- line-height: 1.6 !important;
- color: #dc143c !important;
- background-color: #fff;
- border-radius: 4px;
- }
- </style>`;
- if (!document.querySelector('#userjs-get-title-link')) {
- document.head.insertAdjacentHTML('beforeend', addedStyle);
- }
- class FileReaderEx extends FileReader {
- /**
- * FileReaderのPromiseラッパー
- * @example
- * ```js
- * const blob = await (await fetch(url)).blob();
- * const result = await new utils.FileReaderEx().readAsArrayBuffer(blob);
- * const buffer = new Uint8Array(result as ArrayBuffer);
- * buffer;
- * ```
- */ constructor() {
- super();
- }
- #readAs(blob, ctx) {
- return new Promise((res, rej) => {
- super.addEventListener('load', ({ target }) => target?.result && res(target.result));
- super.addEventListener('error', ({ target }) => target?.error && rej(target.error));
- super[ctx](blob);
- });
- }
- readAsArrayBuffer(blob) {
- return this.#readAs(blob, 'readAsArrayBuffer');
- }
- readAsDataURL(blob) {
- return this.#readAs(blob, 'readAsDataURL');
- }
- }
- const getHTMLData = (url) =>
- new Promise((resolve) => {
- GM_xmlhttpRequest({
- method: 'GET',
- url,
- timeout: 10000,
- onload: (result) => {
- if (result.status === 200) {
- return resolve(result.responseText);
- }
- return resolve(false);
- },
- onerror: (err) => err && resolve(false),
- ontimeout: () => resolve(false),
- });
- });
- const setFailedText = (linkElm) => {
- linkElm.insertAdjacentHTML('afterend', `<span class="userjs-title">データ取得失敗</span>`);
- };
- const setTitleText = (targetDocument, linkElm) => {
- const titleElm = targetDocument.querySelector('title');
- if (!titleElm || !titleElm?.textContent) return;
- linkElm.insertAdjacentHTML('afterend', `<span class="userjs-title">${titleElm.textContent}</span>`);
- };
- const setImageElm = async (targetDocument, titleTextElm) => {
- const imageEventHandler = (e) => {
- const self = e.currentTarget;
- if (!(self instanceof HTMLImageElement)) return;
- if (self.width === 100) {
- self.width = 600;
- } else {
- self.width = 100;
- }
- };
- const imageElm =
- targetDocument.querySelector('#landingImage') ||
- targetDocument.querySelector('.unrolledScrollBox li:first-child img');
- if (!(imageElm instanceof HTMLImageElement)) return;
- const blob = await (await fetch(imageElm.src)).blob();
- const dataUrl = await new FileReaderEx().readAsDataURL(blob);
- const img = document.createElement('img');
- img.src = dataUrl;
- img.width = 100;
- img.classList.add('userjs-image');
- titleTextElm.insertAdjacentElement('afterend', img);
- img.addEventListener('click', imageEventHandler);
- };
- const setLoading = (linkElm) => {
- const loadingSVG =
- '<svg data-id="userjs-loading" width="16" height="16" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg" stroke="#000"><g fill="none" fill-rule="evenodd"><g transform="translate(1 1)" stroke-width="2"><circle stroke-opacity=".5" cx="18" cy="18" r="18"/><path d="M36 18c0-9.94-8.06-18-18-18"> <animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="1s" repeatCount="indefinite"/></path></g></g></svg>';
- const parentElm = linkElm.parentElement;
- if (parentElm instanceof HTMLFontElement || !isProductPage(linkElm.href)) {
- return;
- }
- linkElm.insertAdjacentHTML('afterend', loadingSVG);
- };
- const removeLoading = (targetElm) => targetElm.parentElement?.querySelector('[data-id="userjs-loading"]')?.remove();
- const insertURLData = async (linkElm) => {
- const parentElm = linkElm.parentElement;
- if (parentElm instanceof HTMLFontElement || !isProductPage(linkElm.href)) {
- return;
- }
- const htmlData = await getHTMLData(linkElm.href);
- if (!htmlData) {
- setFailedText(linkElm);
- return;
- }
- const parser = new DOMParser();
- const targetDocument = parser.parseFromString(htmlData, 'text/html');
- setTitleText(targetDocument, linkElm);
- const titleTextElm = parentElm?.querySelector('.userjs-title');
- if (isAmazon(linkElm.href) && titleTextElm) {
- await setImageElm(targetDocument, titleTextElm);
- }
- removeLoading(linkElm);
- };
- const searchLinkElements = (targetElm) => {
- const linkElms = targetElm.querySelectorAll(WHITE_LIST_SELECTORS);
- if (!linkElms.length) return;
- for (const linkElm of linkElms) {
- if (!(linkElm instanceof HTMLElement)) continue;
- setLoading(linkElm);
- void insertURLData(linkElm);
- }
- };
- const mutationLinkElements = async (mutations) => {
- for (const mutation of mutations) {
- for (const addedNode of mutation.addedNodes) {
- if (!(addedNode instanceof HTMLElement)) continue;
- searchLinkElements(addedNode);
- }
- }
- };
- const threadElm = document.querySelector('.thre');
- if (threadElm) {
- searchLinkElements(threadElm);
- const observer = new MutationObserver(mutationLinkElements);
- observer.observe(threadElm, {
- childList: true,
- });
- }
- })();