raingart / pixiv - show resolution

// ==UserScript==
// @name         pixiv - show resolution
// @name:ja      pixiv - 解像度を表示します
// @name:zh-cn   pixiv - 显示作品分辨率
// @name:zh-tw   pixiv - 顯示作品解像度
// @namespace    pixiv-show-resolution
// @description       show works resolution
// @description:ja    イラストの解像度を表示します。
// @description:zh-cn 在图片的左下角显示显示作品分辨率。
// @description:zh-tw 在圖片的左下角顯示作品解像度。
// @version      0.1
// @author       raingart
// @license      Apache-2.0
// @include      https://www.pixiv.net/*
// @exclude      https://www.pixiv.net/*#ppixiv
// @run-at       document-end
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// @grant        GM_registerMenuCommand
// @require      https://cdn.jsdelivr.net/gh/kufii/My-UserScripts@c7f613292672252995cb02a0cab3b6acb18ccac5/libs/gm_config.js
// ==/UserScript==
/*jshint esversion: 6 */

(function() {
const config = GM_config([
   {
      key: 'color-5m',
      label: 'Color areas more 5M pixels',
      default: 'coral',
      type: 'text',
      values: 'coral',
   },
   {
      key: 'color-1m',
      label: 'Color areas more 1M pixels',
      default: 'blue',
      type: 'text',
      values: 'blue',
   },
   {
      key: 'color-500k',
      label: 'Color areas more 500k pixel',
      default: 'red',
      type: 'text',
      values: 'red',
   },
   {
      key: 'color-default',
      label: 'Default color',
      default: 'black',
      type: 'text',
      values: 'black',
   },
   {
      key: 'color-background',
      label: 'Background color',
      default: '#fafafa',
      type: 'text',
      values: '#fafafa',
   },
]);
const conf = config.load();
config.onsave = cfg => (conf = cfg);
GM_registerMenuCommand('Options hotkeys', config.setup);

const
  class_name = 'sc-'+ Math.random().toString(36).slice(2, 7).slice(-5);
  selector = [
      {url: /pixiv.net\/(cate_r18|manga|en\/$|$)/, sel: 'ul div>div>div:nth-of-type(1)>a'},
      {url: /pixiv.net\/(en\/)?artworks/, sel: 'main nav div>div>div>a, ul div>div>div>a'},
      {url: 'pixiv.net/bookmark_new_illust', sel: 'ul div>div>div>a'},
      {url: 'pixiv.net/contest', sel: '.thumbnail-container>a'},
      {url: 'pixiv.net/discovery', sel: 'ul div>div>div:nth-of-type(1)>a'},
      {url: 'pixiv.net/new_illust', sel: 'ul div>div:nth-of-type(1)>div>a'},
      {url: 'pixiv.net/ranking', sel: '.ranking-image-item>a'},
      {url: /pixiv.net\/(en\/)?tags/, sel: 'ul div>div>div>a'},
      {url: /pixiv.net\/(en\/)?users/, sel: 'ul div>div:nth-of-type(1)>div:nth-of-type(1)>a, ul div>div div>div>a:nth-child(1)'},
      {url: /pixiv.net\/user\/\d+\/series\/\d+/, sel: 'ul div>div>div>a'}
  ]
    .map(i => {i.sel += `[href*="/artworks/"]:not(.${class_name})`; return i});

 document.head.insertAdjacentHTML('beforeend',
  `<style>
  .${class_name} > .size {
    position: absolute;
    left: 4px;
    bottom: 4px;
    padding: 4px;
    background-color: ${conf['color-background']};
    border-radius: 4px;
    font-family: Verdana;
    font-size: 10pt;
    font-weight: bold;
    line-height: 1;
  }
  </style>`);

const App = {
  //prevURL: document.URL,

  // onUrlChange
  isURLChanged() {
    return (this.prevURL == document.URL) ? false : this.prevURL = document.URL;
  },

  init() {
    const url = 'https://www.pixiv.net/rpc/illust_list.php?page=discover&illust_ids=';
    const match = selector.find(s => document.URL.match(s.url));

    match && document.body.querySelectorAll(match.sel)
      ?.forEach(async a => {
          a.classList.add(class_name);
          const json = await (await fetch(url + a.href.replace(/.*(\/artworks\/|illust_id=)(\d+)(\D.*)?/, '$2'), {credentials: 'same-origin'})).json();
          if (illust = json.find(v => v.illust_id == a.href.replace(/.*(\/artworks\/|illust_id=)(\d+)(\D.*)?/, '$2'))) {
            const pixels = illust.illust_width * illust.illust_height;
            const color = (pixels >= 5000000) ? conf['color-5m'] : (pixels >= 1000000) ? conf['color-1m'] : (pixels >= 500000) ? conf['color-500k'] : conf['color-default'];
            a.insertAdjacentHTML('beforeend', `<span class="size" style="color:${color};">${illust.illust_width}x${illust.illust_height}</span>`);
          }
    });
  },
};

window.addEventListener('load', App.init);
window.addEventListener('transitionend', () => App.isURLChanged() && App.init());

})();