Greasy Fork is available in English.
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 #### ####" 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 #### ####" 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 #### ####" 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 r###lt = 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);