ヤフオクで非表示とメモ

q:非表示 w:アンドゥ b:NGワード Shift+Q/Shift+B:NG編集 12:メモを追加 34:自由メモ Shift+!:メモを編集 Shift+":自動メモのみ全削除 .:上限価格

目前為 2019-07-19 提交的版本,檢視 最新版本

// ==UserScript==
// @name ヤフオクで非表示とメモ
// @description q:非表示 w:アンドゥ b:NGワード Shift+Q/Shift+B:NG編集 12:メモを追加 34:自由メモ Shift+!:メモを編集 Shift+":自動メモのみ全削除 .:上限価格
// @match *://auctions.yahoo.co.jp/search/*
// @match *://page.auctions.yahoo.co.jp/jp/auction/*
// @match *://auctions.yahoo.co.jp/seller/*
// @version     0.4
// @grant       GM_setValue
// @grant       GM_getValue
// @grant       GM_deleteValue
// @run-at      document-idle
// @namespace https://gf.qytechs.cn/users/181558
// ==/UserScript==

(function() {
  const ENABLEAUTOMEMO = 1; // 0で自動メモをオフ 1でオン 2以上大きくするほど表示が崩れる代わりに確実性が増す
  const CUSTOMAUTOMEMORE = [/(Windows.*bit)/gmi, /(HDD.*?GB)/gmi, /(SSD.*?GB)/gmi, /(10.?key)|(10キー)|(テンキー)/mi, /(768.576)|(800.600)|(832.624)|(1024.768)|(1152.864)|(1280.960)|(1400.1050)|(1440.1080)|(1600.1200)|(2048.1536)|(2304.1728)|(3200.2400)|(854.480)|(1024.576)|(1136.640)|(1280.720)|(1366.768)|(1920.1080)|(1920.1080)|(2048.1152)|(2560.1440)|(3200.1800)|(3840.2160)|(3840.2160)|(7680.4320)|( 640.400)|(1280.800)|(1440.900)|(1680.1050)|(1920.1200)|(2560.1600)|(2880.1800)|(3840.2400)|(480.320)|(960.640)|(176.144)|(400.240)|(352.288)|(640.350)|(720.480)|(800.480)|(864.480)|(1024.480)|(1024.600)|(1280.600)|(1120.750)|(1280.768)|(1152.870)|(1280.1024)|(1600.1024)|(2048.1080)|(4096.2160)|(8192.4320)/m, /^(.*リカバリ.*)$/mi, /(仕事率[^0-90-9\n]*[0-9,0-9,]*\s*[wW])/mi, /(\[?\s?関東[^0-9,0-9,\n]*[0-9,0-9,]*\s*円[-~]?)/m];
  //  const CUSTOMAUTOMEMORE = [/$()^/]; // 無指定
  const ENABLEREPORT = 1; // 0だとレポートを表示しない
  const debug = 0; //Math.random() > 0.5;

  const COLOR1 = "#6080ff",
    COLOR2 = "#c03020",
    COLOR3 = "#808080",
    KEYHIDE = "q",
    KEYUNDO = "w",
    KEYBW = "b",
    KEYEDIT = "Shift+Q",
    KEYEDIT2 = "Shift+B",
    KEYMAXP = ".",
    KEYMEMO1 = "1",
    KEYMEMO2 = "2",
    KEYMEMO1S = "3",
    KEYMEMO2S = "4",
    KEYRESETMEMO = "Shift+!",
    KEYRESETMEMOAUTO = "Shift+\"";
  var mousex = 0;
  var mousey = 0;
  document.addEventListener('keydown', function(e) {
    if (/input|textarea/i.test(e.target.tagName) == false) {
      var key = (e.shiftKey ? "Shift+" : "") + (e.altKey ? "Alt+" : "") + (e.ctrlKey ? "Ctrl+" : "") + e.key;
      if (key === KEYHIDE) { // hide
        e.preventDefault();
        var ele = location.href.indexOf("://page.auctions.yahoo.co.jp/jp/auction/") != -1 ? eleget0('//h1[@class="ProductTitle__text"]') : document.elementFromPoint(mousex, mousey);
        blockElement(ele);
      }
      if (key == KEYUNDO) { // undo
        e.preventDefault();
        let undoTitle = (pref('YAJSearchHideTitle') || "").match(/\|[^\|]*$|^[^|]*$/);
        pref('YAJSearchHideTitle', (pref('YAJSearchHideTitle') || "").replace(/\|[^\|]*$|^[^|]*$/, ""))
        if (undoTitle[0]) {
          showByTitle(undoTitle[0].replace(/^\|/, ""))
          popup2(undoTitle[0].replace(/^\|/, "") + "<br>を非表示登録から削除しました<br><br>編集後:<br>" + (pref('YAJSearchHideTitle') || "").substr(0, 500));
        }
      }
      if (key == KEYBW) { // NGword
        e.preventDefault();
        addNGWord();
      }

      if (key === KEYEDIT || key === KEYEDIT2) { // edit NGs
        e.preventDefault();
        let tmp = prompt(KEYEDIT + "/" + KEYEDIT2 + ":\n非表示にするタイトルを正規表現で編集してください\n|で区切ると複数指定できます\n\n" + (pref('YAJSearchHideTitle') || ""), pref('YAJSearchHideTitle') || "");
        if (tmp !== null) {
          pref('YAJSearchHideTitle', tmp || "")
          document.body.remove();
          location.reload();
        }
      }
      if (key == KEYMEMO1) { // 1memo
        e.preventDefault();
        var ele = location.href.indexOf("://page.auctions.yahoo.co.jp/jp/auction/") != -1 ? eleget0('//h1[@class="ProductTitle__text"]') : document.elementFromPoint(mousex, mousey);
        memoElement(ele, document);
      }
      if (key == KEYMEMO2) { // 2memo
        e.preventDefault();
        var ele = location.href.indexOf("://page.auctions.yahoo.co.jp/jp/auction/") != -1 ? eleget0('//h1[@class="ProductTitle__text"]') : document.elementFromPoint(mousex, mousey);
        memoElement(ele, document, COLOR2);
      }
      if ((key == KEYMEMO1S || key == KEYMEMO2S)) { // free memo
        e.preventDefault();
        var target = (prompt("メモを付けたい出品物のタイトルが含むキーワードを入力してください") || "").trim();
        if (!target) return;
        var memo = (prompt("「" + target + "」\nのメモを書いてください") || "").trim();
        if (!memo) return;
        storeMemo(target.trim(), memo, key == KEYMEMO1S ? COLOR1 : COLOR2)
      }
      if (key == KEYRESETMEMO) { // reset
        e.preventDefault();
        //console.log(pref('YAJSearchMyMemo'))
        let tmp = prompt(KEYRESETMEMO + ":\nメモをJSON形式で編集してください\n空欄を入力すれば全削除されます\n\n" + JSON.stringify(pref('YAJSearchMyMemo') || []), JSON.stringify(pref('YAJSearchMyMemo') || []));
        if (tmp !== null) {
          pref('YAJSearchMyMemo', tmp || []);
          document.body.remove();
          location.reload();
        }
      }
      if (key == KEYRESETMEMOAUTO) { // reset auto
        e.preventDefault();
        //console.log(pref('YAJSearchMyMemo'))
        var str = pref('YAJSearchMyMemo') || '[]';
        var newstr = str.filter(e => !(e.c == COLOR3));
        var newstr2 = str.filter(e => (e.c == COLOR3));
        if (confirm(KEYRESETMEMOAUTO + ":\n自動メモのみ全て削除します。良いですか?\n\n消すもの:\n" + JSON.stringify(newstr2))) {
          pref('YAJSearchMyMemo', JSON.stringify(newstr));
          popup2("自動メモをクリアしました", 1);
          document.body.remove();
          location.reload();
        }
      }
      if (location.href.indexOf("://page.auctions.yahoo.co.jp/jp/auction/") == -1) {
        if (key == KEYMAXP) { // maxprice
          e.preventDefault();
          let ele = eleget0('//input[@class="InputText__input" and @name="max"]');
          if (ele) {
            ele.focus();
            ele.scrollIntoView({ behavior: "smooth", block: "center", inline: "center" });
            ele.select();
          }
          popup2("上限価格にフォーカス", 1);
        }
      }
    }
  }, false);

  document.addEventListener("mousemove", function(e) {
    mousex = e.clientX;
    mousey = e.clientY;
  }, false);

  setTimeout(() => { run() }, 100);
  document.body.addEventListener('AutoPagerize_DOMNodeInserted', function(evt) { run(evt.target); }, false);

  if (location.href.indexOf("://page.auctions.yahoo.co.jp/jp/auction/") == -1) {
    for (let kw of [{ t: "タイトルからのみ検索する", s: "&f=0x2" }, { t: "タイトルと商品説明から検索する", s: "&f=0x4" }]) {
      var ele = eleget0('//div[@class="ptsOption"]/a/../../..');
      if (ele && !(location.href.match(kw.s))) {
        var ele2 = ele.parentNode.insertBefore(document.createElement("a"), ele.nextSibling);
        ele2.innerHTML = kw.t + " ";
        ele2.href = location.href.replace(/\&f\=.*(\&|$)/, "") + kw.s;
      }
    }
  }

  function run(node = document) {
    if (pref('YAJSearchMyMemo')) {
      for (let a of pref('YAJSearchMyMemo')) {
        memoByTitle(a.t, a.m, node, a.c || COLOR1);
      }
    }

    let help = KEYHIDE + ":非表示 " + KEYUNDO + ":アンドゥ " + KEYBW + ":NGワード " + KEYEDIT + "/" + KEYEDIT2 + ":NG編集 " + KEYMEMO1 + KEYMEMO2 + ":メモを追加 " + KEYMEMO1S + KEYMEMO2S + ":自由メモ " + KEYRESETMEMO + ":メモを編集 " + KEYRESETMEMOAUTO + ":自動メモのみ全削除 " + KEYMAXP + ":上限価格";
    if (pref('YAJSearchHideTitle')) {
      var i = 0;
      for (let title of pref('YAJSearchHideTitle').split("|")) {
        i += hideByTitle(title, node);
      }
      if (i && ENABLEREPORT) { help = i + "個の出品を非表示にしました<BR>" + help; }
    }
    popup2(help, 1)
    for (let t = 0; t < ENABLEAUTOMEMO; t++) { setTimeout(makeautomemo, 500 + t * 3000); } //debug&&t>0?popup3( t * t / 2 * 1000,2,1):0; }

    function makeautomemo() {
      if (ENABLEAUTOMEMO && (location.href.indexOf("://page.auctions.yahoo.co.jp/jp/auction/") != -1)) {
        for (let am of CUSTOMAUTOMEMORE) { autoMemo(am); }
        //        autoMemo(/(\[?\s?関東[^0-9,0-9,\n]*[0-9,0-9,]*\s*円[-~]?)/m);
        autoMemo(/(レターパック[^0-90-9\n]*[0-9,0-9,]*円[-~]?)/m);
        autoMemo(/(クリックポスト[^0-90-9\n]*[0-9,0-9,]*円[-~]?)/m);
        autoMemo(/(ゆうメール[^0-90-9\n]*[0-9,0-9,]*円[-~]?)/m);
        autoMemo(/(ゆうパケット[^0-90-9\n]*[0-9,0-9,]*円[-~]?)/m);
        autoMemo(/(ゆうパック[^0-90-9\n]*[0-9,0-9,]*円[-~]?)/m);
        autoMemo(/(定形外[^0-90-9\n]*[0-9,0-9,]*円[-~]?)/m);
        autoMemo(/送料\s*(全国一律[0-9,0-9,]*円[-~]?)/m);
        autoMemo(/送料\s*[::]?(.*は[0-9,0-9,]*円[-~]?)/m);
        autoMemo(/^(.*GHz)/gmi) ? 0 :
          autoMemo(/(CPU[\s\S]{1,30}?GHz)/mi) ? 0 :
          autoMemo(/(Pentium\s?[\s\S]{1,50}?$)|(Celeron\s?[\s\S]{1,50}?$)|(Atom\s?[\s\S]{1,50}?$)|(Core\s?i[\s\S]{1,50}?$)/mi);

        autoMemo(/([0-90-9]{2,4}年製)/m, ) ? 0 :
          autoMemo(/([0-90-9]{2,4}年)/m, ) ? 0 :
          autoMemo(/([0-90-9]{2,4}年製)/m, ) ? 0 :
          autoMemo(/([0-90-9]{2,4}年)/m);
        /*        autoMemo(/^(.*ジャンク.*)$/m) ? 0 :
                  autoMemo(/(^.*ジャンク.*)$/m);*/
        autoMemo(/発送元:(.{1,4}[都道府県])/m);
        //autoMemo(/()/m, document.body);
        //autoMemo(/()/m, document.body);
      }
    }
    return;
  }

  function eletext(ele, xp) {
    let e = eleget0(ele);
    if (e) debugEle(e);
    return e ? e.innerText : "";
  }

  function autoMemo(re, text) {
    let automemotarget = eletext('//div[@class="ProductExplanation__commentArea"]') + "\n" + eletext('//div[@id="ProductProcedures"]') + "\n" + eletext('//h1[@class="ProductTitle__text"]') + '\n' + eletext('//ul[@class="ProductInformation__items"]/li[2]');
    let node = document.body;
    let sou = automemotarget.match(re);
    if (sou) {
      sou.shift();
      var memo = Array.from(new Set(sou)).join(" ").replace(/\s{2,99}| /gm, " ").trim();
      //node.innerHTML=node.innerHTML.replace(re,"<mark>$1</mark>");
      var title = getTitle();
      var tmp = pref('YAJSearchMyMemo') || [];
      var isExist = tmp.filter(e => e.t == title && e.m == memo);
      if (isExist.length == 0) {
        debug ? popup3(memo, 2, 1, 5000) : 0;
        storeMemo(title, memo, COLOR3, node);
      }
      return true;
    }
    return false;
  }

  function getTitle(x, y) {
    var ele = location.href.indexOf("://page.auctions.yahoo.co.jp/jp/auction/") != -1 ? eleget0('//h1[@class="ProductTitle__text"]') : document.elementFromPoint(mousex, mousey);
    if (!ele) return;
    var title = checkSome(ele);
    if (!title) return;
    return title;
  }

  function memoElement(ele, node, color = COLOR1) { //A memo
    if (!ele) return;
    var title = checkSome(ele);
    if (!title) return;
    var memo = (prompt("「" + title + "」\nのメモを書いてください") || "").trim();
    storeMemo(title, memo, color, node);
    return true;
  }

  function storeMemo(title, memo, color = COLOR1, node = document) {
    if (title && memo) {
      let tmp = pref('YAJSearchMyMemo') || [];
      tmp.push({ t: title, m: memo, c: color })
      pref('YAJSearchMyMemo', tmp)
      memoByTitle(title, memo, node, color);
    }
  }

  function memoByTitle(title, memo, node, color) {
    var xp = '//a[contains(@class,"Product__titleLink") and contains(text(),"' + title + '")]/../..|.//h1[@class="ProductTitle__text" and contains(text(),"' + title + '")]/..|.//div[@class="a1wrp"]/h3/a[contains(text(),"' + title + '")]';
    for (var titleEle of elegeta(xp, node)) {
      if (titleEle) {
        var ele = titleEle.parentNode.parentNode.insertBefore(document.createElement("span"), titleEle.parentNode.nextSibling);
        ele.innerHTML = '<span class="' + escape(title + memo + color) + '" title="' + title + '" style="font-size:90%; font-weight:bold; margin:0px 1px; text-decoration:none !important; text-align:center; padding:1px 6px 1px 6px; line-height: 1.4em; border-radius:12px; background-color:' + color + '; color:white;">' + memo + '</span>';
        setRemoveMemo(ele, title, memo, color)
      }
    }
  }

  function setRemoveMemo(ele, title, memo, color) {
    ele.onclick = (e) => {
      pref('YAJSearchMyMemo', (pref('YAJSearchMyMemo') || []).filter(n => !(n.t == title && n.m == memo && n.c == color)))
      for (let e of elegeta('//span[@class="' + escape(title + memo + color) + '"]')) e.remove(); //ele.remove();
    }
  }

  function checkSome(ele) {
    if (ele.className == "ProductTitle__text") return ele.innerText.replace(/\|/g, '\|').trim();
    for (let i = 0; i < 4; i++) {
      var ele2 = elegeta('//a[@class="Product__titleLink"]|.//a[@class="Product__titleLink u-textBold"]|.//div[@class="a1wrp"]/h3/a', ele);
      if (ele2.length == 1) { return ele2[0].innerText.replace(/\|/g, '\|').trim(); }
      ele = ele.parentNode;
    }
    return;
  }

  function blockElement(ele) { //Q toggle
    if (!ele) return;
    var title = checkSome(ele);
    if (!title) return;
    if ((pref('YAJSearchHideTitle') || "").match(new RegExp("(^|\|)" + title.replace(/(\(|\)|\[|\]|\?|\*|\^|\$|\.|\+|\{|\}|\|)/gm, "\\$1") + "($|\|)"))) {
      pref('YAJSearchHideTitle', (pref('YAJSearchHideTitle') || "").replace(new RegExp("(^|\|)" + title.replace(/(\(|\)|\[|\]|\?|\*|\^|\$|\.|\+|\{|\}|\|)/gm, "\\$1") + "($|\|)"), "").replace(/(^\|)|(\|\|)|(\|$)/gm, ""));
      showByTitle(title);
      popup2(title + "<br>を非表示登録から削除しました<br><br>編集後:<br>" + (pref('YAJSearchHideTitle') || "").substr(0, 500));
      return;
    } else {
      if ((pref('YAJSearchHideTitle') || "").indexOf(title) != -1) return;
    }
    hideByTitle(title);
    if (pref('YAJSearchHideTitle')) pref('YAJSearchHideTitle', pref('YAJSearchHideTitle') + "|" + title);
    else pref('YAJSearchHideTitle', title);
    popup2(title + "<br>を非表示登録しました(" + KEYUNDO + ":取り消し " + KEYEDIT + "/" + KEYEDIT2 + ":編集)<br><br>編集後:<br>" + pref('YAJSearchHideTitle').substr(0, 500));
  }

  function hideByTitle(title, node) {
    let i = 0;
    var xp = '//a[contains(@class,"Product__titleLink") and contains(text(),"' + title + '")]/../../../../..|.//div[@class="a1wrp"]/h3/a[contains(text(),"' + title + '")]/../../../..';
    for (let ele of elegeta(xp, node)) {
      console.log(ele.style.display);
      i++;
      setTimeout(function() { ele.style.opacity = "0.75" }, 17 * 0);
      setTimeout(function() { ele.style.opacity = "0.50" }, 17 * 1);
      setTimeout(function() { ele.style.opacity = "0.25" }, 17 * 2);
      setTimeout(function() {
        ele.style.display = "none";
        ele.style.opacity = "0"
      }, 17 * 3);
    }
    var xp = '//h1[@class="ProductTitle__text" and contains(text(),"' + title + '")]/../../../..';
    for (let ele of elegeta(xp, node)) {
      i++;
      ele.style.opacity = "0.5";
    }
    return i;
  }

  function showByTitle(title) {
    var xp = '//a[contains(@class,"Product__titleLink") and contains(text(),"' + title + '")]/../../../../..|.//div[@class="a1wrp"]/h3/a[contains(text(),"' + title + '")]/../../../..';
    for (let ele of elegeta(xp)) {
      setTimeout(function() {
        ele.style.display = "block";
        ele.style.opacity = "0.25"
      }, 17 * 0);
      setTimeout(function() { ele.style.opacity = "0.50" }, 17 * 1);
      setTimeout(function() { ele.style.opacity = "0.75" }, 17 * 2);
      setTimeout(function() { ele.style.opacity = "1" }, 17 * 3);
    }
    var xp = '//h1[@class="ProductTitle__text" and contains(text(),"' + title + '")]/../../../..';
    for (let ele of elegeta(xp)) { ele.style.opacity = "1"; }
  }

  function addNGWord() {
    var newWord = (prompt("非表示にしたい出品物が含むNGワードを入力してください") || "").trim();
    if (newWord) {
      hideByTitle(newWord)
      if (pref('YAJSearchHideTitle')) pref('YAJSearchHideTitle', pref('YAJSearchHideTitle') + "|" + newWord);
      else pref('YAJSearchHideTitle', newWord);
      popup2(title + "<br>を非表示登録しました(" + KEYUNDO + ":取り消し " + KEYEDIT + "/" + KEYEDIT2 + ":編集)<br><br>編集後:<br>" + pref('YAJSearchHideTitle').substr(0, 500));
    }
  }

  function elegeta(xpath, node = document) {
    if (!xpath) return [];
    try {
      var array = [];
      var ele = document.evaluate("." + xpath, node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
      for (var i = 0; i < ele.snapshotLength; i++) array[i] = ele.snapshotItem(i);
      return array;
    } catch (e) { return []; }
  }

  function eleget0(xpath, node = document) {
    if (!xpath) return null;
    try {
      var ele = document.evaluate("." + xpath, node, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
      return ele.snapshotLength > 0 ? ele.snapshotItem(0) : "";
    } catch (e) { popup2(e, 1); return null; }
  }

  var maey = 0;

  function popup3(text, i = 0, lf = 0, timer = 5000) {
    let id = Math.random().toString(36).substring(2);
    let ele = document.body.appendChild(document.createElement("span"));
    ele.outerHTML = '<span id="mllbox' + id + '" style="all:initial; position: fixed; right:1em; bottom: ' + ((maey + i) * 2 + 1) + 'em; z-index:2147483647; opacity:1; font-size:90%; margin:0px 1px; text-decoration:none !important;  padding:1px 6px 1px 6px; word-break: break-all !important; border-radius:12px; background-color:#6080ff; color:white; ">' + text + '</span>';
    maey += lf;
    setTimeout(() => {
      eleget0('//span[@id="mllbox' + id + '"]').remove();
      maey = 0;
    }, timer);
  }
  var maet;

  function popup2(text, i = 0) {
    var mae = eleget0('//span[@id="mllbox"]');
    if (maet && mae) {
      mae.remove();
      clearTimeout(maet);
    }
    var ele = document.body.appendChild(document.createElement("span"));
    ele.outerHTML = '<span id="mllbox" style="all:initial; position: fixed; right:1em; bottom: ' + (i * 2 + 1) + 'em; z-index:2147483647; opacity:1; font-size:90%; margin:0px 1px; text-decoration:none !important;  padding:1px 6px 1px 6px; word-break: break-all !important; border-radius:12px; background-color:#6080ff; color:white; ">' + text + '</span>';
    maet = setTimeout(function() {
      var mae = eleget0('//span[@id="mllbox"]');
      if (mae) { mae.remove(); }
    }, 5000);
  }


  function pref(name, store = null) {
    if (store === null) { // 読み出し
      let data = GM_getValue(name)
      if (data == undefined) return; // 値がない
      if (data.substr(0, 1) === "[") { // 配列なのでJSONで返す
        try { return JSON.parse(data || '[]'); } catch (e) {
          console.log("データベースがバグってるのでクリアします\n" + e);
          pref(name, []);
          return;
        }
      } else return data;
    }
    if (store === "" || store === []) { // 書き込み、削除
      GM_deleteValue(name);
      return;
    } else if (typeof store === "string") { // 書き込み、文字列
      GM_setValue(name, store);
      return store;
    } else { // 書き込み、配列
      try { GM_setValue(name, JSON.stringify(store)); } catch (e) {
        console.log("データベースがバグってるのでクリアします\n" + e);
        pref(name, "");
      }
      return store;
    }
  }

  function debugEle(ele) {
    if (debug) {
      let col = '#' + (0x1000000 + (Math.random()) * 0xffffff).toString(16).substr(1, 6);
      ele.style.outline = "3px dotted " + col;
      ele.style.boxShadow = " 0px 0px 4px 4px " + col + "30, inset 0 0 100px " + col + "20";
      //      ele.title='\n@class="'+ele.className+'"\n@id="'+ele.id+'"';
    }
  }

})()

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址