Amazon CPU Tamer

It reduces CPU usage on Amazon shopping pages. Enjoy your snappy shopping.

Version au 25/12/2020. Voir la dernière version.

Avant de procéder à l'installation, Greasy Forkattention ce script contient des contre-fonctionnalités, qui sont là pour le bénéfice de l'auteur du script, plutôt que pour le vôtre.

Ce script comporte une ou plusieurs commissions pour l'auteur, par exemple en réécrivant des liens ou en fournissant des codes promo pour inclure un code de parrainage ou d'affiliation. L'auteur de ce script explique: This script may add an associate ID to visited Amazon URLs. It doesn't replace any existed ID. Thank you.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name        Amazon CPU Tamer
// @name:ja     Amazon CPU Tamer
// @name:zh-CN  Amazon CPU Tamer
// @namespace   knoa.jp
// @description It reduces CPU usage on Amazon shopping pages. Enjoy your snappy shopping.
// @description:ja AmazonのショッピングページでのCPU使用率を削減します。お買いものをサクサク楽しみましょう。
// @description:zh-CN 减少Amazon购物页面上的CPU利用率。顺利地享受买东西吧。
// @include     https://www.amazon.com/*
// @include     https://www.amazon.co.jp/*
// @include     https://www.amazon.co.uk/*
// @include     https://www.amazon.es/*
// @include     https://www.amazon.fr/*
// @include     https://www.amazon.de/*
// @include     https://www.amazon.it/*
// @include     https://www.amazon.*
// @include     https://*.amazon-*.com/*
// @include     https://*.*-amazon.com/*
// @exclude     */cart/*
// @exclude     */buy/*
// @version     1.4.4
// @grant       none
// @run-at      document-start
// @antifeature referral-link This script may add an associate ID to visited Amazon URLs. It doesn't replace any existed ID. Thank you.
// @antifeature:ja referral-link ありがとうございます。本スクリプトは、訪れたAmazonページのURLにアソシエイトIDを付与することがあります。別のIDがすでに付与されている場合は、置き換えることはしません。
// @antifeature:zh-CN referral-link 本脚本可能会为访问过的Amazon页面的URL授予联盟ID。如果已经授予了另一个ID,则不会进行替换。谢谢。
// @contributionURL https://paypal.me/kantankikaku
// ==/UserScript==

/*
[update]
Update @antifeature descriptions. Minor fix.

[memo]
top:
  interval インタラクション要素にも使われるので、1インスタンスにまとめた上で前面タブのみやむなく125msごとに実行。
    もっとゆるい頻度にしつつ、click や  keydown 時のみ頻度を上げる手はあるが、前面タブで1-2%なら許されるだろう。
    ゆるい interval による把握できている問題は詳細画像の切り替え表示だけなので、自分でやっちゃう手もあるが。
  timeout  インタラクションのみで定常なしなので、そのまま実行してもよい。
iframe(ad):
  interval 初期化時のみなのでそのまま実行してもよい。
  timeout  定常 100ms が iframe ごとに1つずつなので、1秒ごとに頻度を落とす。
iframe(cloudfront.net ad)
  ローカルソースのiframeから事後生成されるのでTampermonkeyが機能しない。
  広告除去することはできるが、このスクリプトの役目ではない。
*/
(function(){
  const SCRIPTID = 'AmazonCpuTamer';
  console.log(SCRIPTID, location.href);
  const BUNDLEDINTERVAL    =     125;/* the bundled interval */
  const BACKGROUNDINTERVAL = 60*1000;/* take even longer interval on hidden tab */
  const IFRAMETIMEOUT      =  1*1000;/* amazon uses timeouts instead of intervals on iframes */
  /*
    [interval]
    tame quick intervals
  */
  if(window === top){
    /* integrate each of intervals */
    const bundle = {};/* {0: {f, interval, lastExecution}} */
    let index = 0;/* use it instead of interval id */
    let lastExecution = 0;
    /* bundle intervals */
    const originalSetInterval = window.setInterval.bind(window);
    window.setInterval = function(f, interval, ...args){
      //console.log(SCRIPTID, 'original interval:', interval, location.href);
      bundle[index] = {
        f: f.bind(null, ...args),
        interval: interval,
        lastExecution: 0,
      };
      return index++;
    };
    window.clearInterval = function(id){
      //console.log(SCRIPTID, 'clearInterval:', id, location.href);
      delete bundle[id];
    };
    /* execute bundled intervals */
    /* a bunch of intervals does cost so much even if the processes do nothing */
    originalSetInterval(function(){
      const now = Date.now();
      if(document.hidden && now < lastExecution + BACKGROUNDINTERVAL) return;
      Object.keys(bundle).forEach(id => {
        const item = bundle[id];
        if(item === undefined) return;/* it could be occur on tiny deletion chance */
        if(now < item.lastExecution + item.interval) return;/* not yet */
        item.f();
        item.lastExecution = now;
      });
      lastExecution = now;
    }, BUNDLEDINTERVAL);
  }
  /*
    [timeout]
    tame quick timeouts on iframe ads
  */
  if(window !== top){
    const originalSetTimeout = window.setTimeout.bind(window);
    window.setTimeout = function(f, timeout, ...args){
      if(document.hidden) return;
      if(timeout < IFRAMETIMEOUT){
        //console.log(SCRIPTID, 'timeout:', timeout, 'to', IFRAMETIMEOUT, location.href);
        timeout = IFRAMETIMEOUT;
      }
      return originalSetTimeout(f, timeout, ...args);
    };
  }
  /*
    [associate]
    add an associate tag
  */
  if(window === top){
    const IDS = {
      'www.amazon.com':   'knoa-20',
      'www.amazon.co.jp': 'knoa-22',
      'www.amazon.co.uk': 'knoa01-21',
      'www.amazon.es':    'knoa0c-21',
      'www.amazon.fr':    'knoa09-21',
      'www.amazon.de':    'knoa03-21',
      'www.amazon.it':    'knoa0a-21',
    };
    if(IDS[location.host]){
      addTag(IDS[location.host]);
    }
    function addTag(tag){
      const url = new URL(location.href);
      if(url.searchParams.get('tag') !== null) return;/* do not overwrite */
      console.log(SCRIPTID, 'associate tag:', tag);
      document.documentElement.addEventListener('mousedown', function(e){
        for(let target = e.target; target; target = target.parentNode){
          if(target.href && target.href.startsWith(location.origin) && !target.getAttribute('href').startsWith('#')){
            const separator = (target.href.includes('?')) ? '&' : '?';
            target.href = target.href.replace(/(?=#)|$/, separator + 'tag=' + tag);
          }
        }
      });
      const separator = (url.search === '') ? '?' : '&';
      history.replaceState(null, document.title, location.href.replace(/(?=#)|$/, separator + 'tag=' + tag));
    }
  }
})();