Greasy Fork

来自缓存

pixiv获取原图

pixiv页面生成按钮用于复制原图链接和下载原图

// ==UserScript==
// @name         pixiv获取原图
// @namespace    https://github.com/MuXia-0326/twitter-auto-original-picture
// @version      1.5
// @description  pixiv页面生成按钮用于复制原图链接和下载原图
// @author       Mossia
// @icon         https://raw.githubusercontent.com/MuXia-0326/drawio/master/angri.png
// @match        *://www.pixiv.net/*
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @grant        GM_download
// @license      MIT
// ==/UserScript==

const css = `
.pixiv-Btn {
  z-index: 1000;
  position: relative;
  display: inline-block;
  margin-right: 5px;
  padding: 10px;
  text-align: center;
  font-size: 18px;
  letter-spacing: 1px;
  text-decoration: none;
  color: rgb(0, 150, 250);
  background: transparent;
  cursor: pointer;
  transition: ease-out 0.5s;
  border: 2px solid rgb(0, 150, 250);
  border-radius: 10px;
  box-shadow: inset 0 0 0 0 rgb(0, 150, 250);
}
.pixiv-Btn:hover {
  color: white;
  box-shadow: inset 0 -100px 0 0 rgb(0, 150, 250);
}
.pixiv-Btn:active {
  transform: scale(0.9);
}
.pixiv-Btn:hover svg {
  fill: white;
}
.pixiv-Btn:active svg, .pixiv-Btn svg {
  fill: rgb(0, 150, 250);
}


.Btn {
  position: absolute;
  right: 0px;
  bottom: 0px;
}
.svgClass {
  display: flex;
}

.share-btn {
  display:none;
}
`;

let styleTag = document.createElement('style');
styleTag.innerText = css;
document.head.append(styleTag);

function ILog() {
  this.prefix = '';

  this.v = function (value) {
    if (level <= this.LogLevel.Verbose) {
      console.log(this.prefix + value);
    }
  };

  this.i = function (info) {
    if (level <= this.LogLevel.Info) {
      console.info(this.prefix + info);
    }
  };

  this.w = function (warning) {
    if (level <= this.LogLevel.Warning) {
      console.warn(this.prefix + warning);
    }
  };

  this.e = function (error) {
    if (level <= this.LogLevel.Error) {
      console.error(this.prefix + error);
    }
  };

  this.d = function (element) {
    if (level <= this.LogLevel.Verbose) {
      console.log(element);
    }
  };

  this.setLogLevel = function (logLevel) {
    level = logLevel;
  };

  this.LogLevel = {
    Verbose: 0,
    Info: 1,
    Warning: 2,
    Error: 3,
  };

  let level = this.LogLevel.Warning;
}
var iLog = new ILog();

// let pixiv_proxy = 'https://i.pixiv.cat';
let pixiv_proxy = 'https://pixiv.mossia.top';
let g_getArtworkUrl = '/ajax/illust/#id#/pages';

let share_url = '';
let share_url_two = '';
let userName = '';

// 当前页面类型
let g_pageType = -1;

// 页面相关的一些预定义,包括处理页面元素等
let PageType = {
  // 作品详情页
  Artwork: 0,

  // 总数
  PageTypeCount: 1,
};

/* Pages 必须实现的函数
 * PageTypeString: string,字符串形式的 PageType
 * bool CheckUrl: function(string url),用于检查一个 url 是否是当前页面的目标 url
 * ProcessPageElements: function(),处理页面(寻找图片元素、添加按钮)
 */
let Pages = {};

Pages[PageType.Artwork] = {
  PageTypeString: 'ArtworkPage',
  CheckUrl: function (url) {
    return /^https:\/\/www.pixiv.net\/artworks\/.*/.test(url) || /^https:\/\/www.pixiv.net\/en\/artworks\/.*/.test(url);
  },
  ProcessPageElements: function () {
    if (userName === '') {
      getUserName();
    }

    // 动图不处理
    if (document.querySelector('main figure canvas')) {
      return;
    }

    // 未加载完不处理
    if (!document.querySelector('main figure')) {
      return;
    }

    let allImage = document.querySelector('main figure').parentNode.querySelector('section + button');
    if (allImage) {
      allImage.click();
    }

    let matched = location.href.match(/artworks\/(\d+)/);
    if (!matched) {
      return;
    }

    let pid = matched[1];
    let url = g_getArtworkUrl.replace('#id#', pid);

    let original = [];

    //生成按钮
    let divImages = document.querySelectorAll('main figure div:first-child div[role="presentation"]');
    divImages.forEach((e, i) => {
      let _this = e;
      let image = _this.querySelector('a').parentNode;
      if (image.querySelector('.Btn') && image.querySelector('.Btn').getAttribute('data-pid') === pid) {
        return;
      }

      fetch(url, {
        method: 'GET',
      })
        .then((response) => response.json())
        .then((json) => {
          iLog.i('Got artwork urls:');

          if (json.error === true) {
            iLog.e('Server responsed an error: ' + json.message);
            return;
          }

          for (let i = 0; i < json.body.length; i++) {
            original.push(json.body[i].urls.original);
          }
        })
        .catch((error) => {
          iLog.e('Request image urls failed!');
          if (error) {
            iLog.e(error);
          }
        });

      let btns = image.querySelectorAll('.Btn');
      if (btns.length > 0) {
        btns.forEach((btn) => btn.remove());
      }
      let div = document.createElement('div');

      div.innerHTML = `
            <div class="Btn" data-pid=${pid}>
                <button class="pixiv-Btn" id="cp_${i}">
                    <div class="svgClass">
                        <svg t="1694962361717" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5412" width="20" height="20">
                            <path d="M761.088 715.3152a38.7072 38.7072 0 0 1 0-77.4144 37.4272 37.4272 0 0 0 37.4272-37.4272V265.0112a37.4272 37.4272 0 0 0-37.4272-37.4272H425.6256a37.4272 37.4272 0 0 0-37.4272 37.4272 38.7072 38.7072 0 1 1-77.4144 0 115.0976 115.0976 0 0 1 114.8416-114.8416h335.4624a115.0976 115.0976 0 0 1 114.8416 114.8416v335.4624a115.0976 115.0976 0 0 1-114.8416 114.8416z" p-id="5413" ></path>
                            <path d="M589.4656 883.0976H268.1856a121.1392 121.1392 0 0 1-121.2928-121.2928v-322.56a121.1392 121.1392 0 0 1 121.2928-121.344h321.28a121.1392 121.1392 0 0 1 121.2928 121.2928v322.56c1.28 67.1232-54.1696 121.344-121.2928 121.344zM268.1856 395.3152a43.52 43.52 0 0 0-43.8784 43.8784v322.56a43.52 43.52 0 0 0 43.8784 43.8784h321.28a43.52 43.52 0 0 0 43.8784-43.8784v-322.56a43.52 43.52 0 0 0-43.8784-43.8784z" p-id="5414" ></path>
                        </svg>
                    </div>
                </button>
                <button class="pixiv-Btn" id="download_${i}">
                    <div class="svgClass">
                        <svg t="1694962091616" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4129" id="mx_n_1694962091617" width="20" height="20">
                            <path d="M160 579.2a28.8 28.8 0 0 1 28.8 28.8v170.672c0 30.4 25.664 56.528 59.2 56.528h528c33.536 0 59.2-26.144 59.2-56.528V608a28.8 28.8 0 0 1 57.6 0v170.672c0 63.856-53.12 114.128-116.8 114.128h-528c-63.68 0-116.8-50.272-116.8-114.128V608a28.8 28.8 0 0 1 28.8-28.8z"  p-id="4130"></path><path d="M540.8 176l0 464a28.8 28.8 0 0 1-57.6 0L483.2 176a28.8 28.8 0 0 1 57.6 0z"  p-id="4131"></path>
                            <path d="M331.632 459.632a28.8 28.8 0 0 1 40.736 0l160 160a28.8 28.8 0 0 1-40.736 40.736l-160-160a28.8 28.8 0 0 1 0-40.736z" p-id="4132"></path><path d="M692.368 459.632a28.8 28.8 0 0 0-40.736 0l-160 160a28.8 28.8 0 0 0 40.736 40.736l160-160a28.8 28.8 0 0 0 0-40.736z" p-id="4133"></path>
                        </svg>
                    </div>
                </button>
                <button class="pixiv-Btn share-btn" id="share_${i}">
                    <div class="svgClass">
                        <svg t="1713618483987" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2790" width="20" height="20">
                            <path d="M720.020242 809.16812c0-49.233308 39.919175-89.151459 89.151459-89.151459s89.150436 39.918151 89.150436 89.151459c0 49.227168-39.918151 89.159646-89.150436 89.159646S720.020242 858.397335 720.020242 809.16812zM571.433112 214.824717c0-49.234331 39.919175-89.152483 89.151459-89.152483 49.234331 0 89.152483 39.918151 89.152483 89.152483 0 49.232285-39.918151 89.151459-89.152483 89.151459C611.352287 303.976176 571.433112 264.057001 571.433112 214.824717zM125.674792 675.441443c0-82.07018 66.530252-148.586107 148.585083-148.586107 82.056877 0 148.58713 66.515926 148.58713 148.586107 0 82.071204-66.531276 148.58713-148.58713 148.58713C192.205045 824.028573 125.674792 757.511623 125.674792 675.441443zM66.240145 675.441443c0 114.89375 93.142353 208.027917 208.019731 208.027917 81.402985 0 151.8525-46.752814 186.03809-114.870214l200.360284 35.288714-0.073678 5.28026c0 82.07632 66.531276 148.594293 148.58713 148.594293s148.586107-66.517973 148.586107-148.594293c0-82.072227-66.530252-148.586107-148.586107-148.586107-59.507302 0-110.815875 34.927487-134.554532 85.436858l-195.454554-34.403554c2.059915-11.738345 3.119037-23.839965 3.119037-36.174897 0-54.311976-20.822235-103.748922-54.892191-140.779304l180.740434-180.755784c16.309454 6.152117 33.983999 9.503445 52.454676 9.503445 82.056877 0 148.58713-66.514903 148.58713-148.586107 0-82.07018-66.530252-148.58713-148.58713-148.58713-82.055854 0-148.585083 66.51695-148.585083 148.58713 0 41.674145 17.165961 79.32772 44.792159 106.317421L381.013225 496.92056c-31.211862-18.71934-67.703985-29.499871-106.753349-29.499871C159.382499 467.421712 66.240145 560.549739 66.240145 675.441443z" p-id="2791"></path>
                        </svg>
                    </div>
                </button>
            </div>
            `;

      image.appendChild(div);

      document.getElementById(`cp_${i}`).addEventListener('click', function () {
        let newUrl = original[i].replace('https://i.pximg.net', pixiv_proxy);
        navigator.clipboard.writeText(newUrl);
      });

      document.getElementById(`download_${i}`).addEventListener('click', function () {
        // 点击喜欢按钮
        let likeDiv = document.querySelector('main section section div.sc-181ts2x-3.cXSAgn');
        if (likeDiv) {
          let a = likeDiv.querySelector('a');
          if (!a) {
            likeDiv.querySelector('button').click();
          }
        }

        let newUrl = original[i];

        GM_xmlhttpRequest({
          method: 'GET',
          url: newUrl,
          headers: {
            Referer: 'https://www.pixiv.net/',
          },
          responseType: 'blob', // 添加这一行
          onload: function (response) {
            if (response.status === 200) {
              var blobUrl = URL.createObjectURL(response.response);
              GM_download(blobUrl, newUrl.substring(newUrl.lastIndexOf('/') + 1));
            } else {
              console.error('Download failed:', response.statusText);
            }
          },
        });

        GM_xmlhttpRequest({
          method: 'POST',
          url: 'https://api.mossia.top/add/pPidQueue',
          headers: {
            'Content-Type': 'application/json',
          },
          data: JSON.stringify({
            pidList: [pid],
            createBy: userName,
          }),
          onload: function (response) {
            let result = JSON.parse(response.responseText);
          },
          onerror: function (error) {
            console.error('Request failed:', error);
          },
        });
      });

      document.getElementById(`share_${i}`).addEventListener('click', function () {
        let newUrl = original[i].replace('https://i.pximg.net', pixiv_proxy);
        GM_xmlhttpRequest({
          method: 'POST',
          url: share_url, // 目标 URL
          headers: {
            'Content-Type': 'application/json',
          },
          data: JSON.stringify({ imageUrl: newUrl }),
          onload: function (response) {
            var responseData = JSON.parse(response.responseText);
            console.log('Received response:', responseData);
          },
          onerror: function (error) {
            console.error('Request failed:', error);
          },
        });
        GM_xmlhttpRequest({
          method: 'POST',
          url: share_url_two, // 目标 URL
          headers: {
            'Content-Type': 'application/json',
          },
          data: JSON.stringify({ urls: [newUrl] }),
          onload: function (response) {
            var responseData = JSON.parse(response.responseText);
            console.log('Received response:', responseData);
          },
          onerror: function (error) {
            console.error('Request failed:', error);
          },
        });
      });
    });
  },
};

function main() {
  // 匹配当前页面
  for (let i = 0; i < PageType.PageTypeCount; i++) {
    if (Pages[i].CheckUrl(location.href)) {
      g_pageType = i;
      break;
    }
  }

  if (g_pageType >= 0) {
    iLog.i('当前页面类型:' + Pages[g_pageType].PageTypeString);
  } else {
    iLog.i('当前页面类型:未知');
    clearInterval(mainInterval);
    return;
  }

  // 执行操作
  Pages[g_pageType].ProcessPageElements();
}

function getUserName() {
  var div = document.querySelectorAll('.sc-pkfh0q-0.kYDpSN .sc-1asno00-0.feBRRY');
  div.forEach((e, i) => {
    userName = e.getAttribute('title');
    console.log(userName);
  });
}

let mainInterval = setInterval(main, 200);