// ==UserScript==
// @name Extract images for pixiv
// @name:zh P站原图收割机
// @namespace https://github.com/cmheia/extract-images-for-pixiv
// @description Adds a button that get all attached images as original size to every post.
// @include http://www.pixiv.net/member_illust.php*
// @author cmheia
// @version 1.2.0
// @icon http://www.pixiv.net/favicon.ico
// @grant GM_setClipboard
// @grant GM_xmlhttpRequest
// @license MPL
// ==/UserScript==
(function () {
'use strict';
/**********************************************************************
* 长得像库
**********************************************************************/
var $id = function (o) {
// return document.getElementById(o);
return document.querySelector(`#${o}`);
};
var $class = function (o) {
// return document.getElementsByClassName(o);
return document.querySelector(`.${o}`);
};
// 去重
var unique = function (arr) {
var result = [],
hash = {};
for (let i = 0, elem; (elem = arr[i]) !== undefined; i++) {
if (!hash[elem]) {
result.push(elem);
hash[elem] = true;
}
}
return result;
};
// 插入样式表
var apendStyle = function (cssText) {
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
var textNode = document.createTextNode(cssText);
style.appendChild(textNode);
head.appendChild(style);
};
// 增加 class
var addClassName = function (elem, clas) {
var current = elem.className;
if (current) {
current += " ";
current += clas;
current = current.split(' ').filter(function (v, i) {
if (v) {
return v;
}
});
current = unique(current);
elem.className = current.join(" ");
} else {
elem.className = clas;
}
};
// 移除 class
var removeClassName = function (elem, clas) {
var current = elem.className;
if (current) {
current = current.split(' ').filter(function (v, i) {
if (clas != v) {
return v;
}
});
current = unique(current);
elem.className = current.join(" ");
}
};
// 增加/移除 class
var toggleClassName = function (elem, clas) {
var current = elem.className;
if (current) {
if (-1 === current.split(' ').indexOf(clas)) {
addClassName(elem, clas);
} else {
removeClassName(elem, clas);
}
} else {
elem.className = clas;
}
};
// 伤脑筋!
function illustCollector() {
function tergetContainer() {
// illust_id
this.id = "-1";
// 取得的原图链接
this.result = [];
// 最终的原图链接,1 -> yes,0 -> no,-1 -> failed
this.final = [];
}
this.illust = [];
// 删除重复目标
this.shrinkTarget = function () {
var elem,
hash = {},
duplicate = [];
// 第一步:找出需要删除的重复 id
for (let i = 0; (elem = this.illust[i]) !== undefined; i++) {
if (hash[elem.id]) {
duplicate.push(i); // 重复
} else {
hash[elem.id] = true;
}
}
// 第二步:删除的重复 id
for (let i = duplicate.length - 1; i >= 0; i--) {
this.illust.splice(duplicate[i], 1);
}
// console.log("删除重复 id", duplicate.length, "个");
return duplicate.length;
};
// 增加新目标
this.addTarget = function (illust_id) {
// console.group("addTarget", illust_id, this.illust.length);
var i,
index;
for (i = 0; i < this.illust.length; i++) {
if (illust_id === this.illust[i].id) {
// console.log("目标重复了");
index = -1;
break;
}
}
if (-1 !== index) {
this.shrinkTarget();
index = this.illust.length;
// console.log("新增目标", index, this.illust.length);
this.illust.push(new tergetContainer());
// illust_id
this.illust[index].id = illust_id;
}
// console.log(index, this.illust);
// console.groupEnd();
return index;
};
// 删除目标
// type: true -> target is id; false -> target is index (default)
this.removeTarget = function (target, type) {
// console.group("removeTarget", target, type);
var index = -1;
if (type) {
for (let i = 0; i < this.illust.length; i++) {
if (target === this.illust[i].id) {
index = i;
break;
}
}
} else {
index = target;
}
if (index > -1) {
this.illust.splice(index, 1);
}
// console.groupEnd();
};
// 记录指定 illust_id 包含的图片数量(取得目标 html 后调用)
// count: -1 -> 记录为失败
// type: true -> target is index; false -> target is id (default)
this.recordTargetLength = function (target, count, type) {
// console.group("recordTargetLength", target, count, type);
var index = -1;
if (type && this.illust[target] && this.illust[target].id) {
index = target;
} else {
for (let i = 0; i < this.illust.length; i++) {
if (target === this.illust[i].id) {
index = i;
break;
}
}
}
if (index > -1) {
if (0 > count) {
// 记录为失败
// 取得的原图链接
// this.illust[index].result[0] = "";
// 最终的原图链接,1 -> yes,0 -> no,-1 -> failed
this.illust[index].final[0] = -1;
// console.log(target, "被标记为获取失败,index =", index);
} else {
// 取得的原图链接
this.illust[index].result = new Array(count);
// 最终的原图链接,1 -> yes,0 -> no,-1 -> failed
this.illust[index].final = new Array(count);
// console.log("初始化 illust[", index, "] 为", count, "个原图存放区");
}
}
// console.groupEnd();
};
// 记录指定 illust_id 的原图 URL (取得目标的原图后调用, 每次调用添加一个 URL, 多图多调)
// type: true -> target is index; false -> target is id (default)
this.setTarget = function (target, content, offset, status, type) {
// console.group("setTarget", target, content, offset, status, type);
var index = -1,
result = false;
if (type && this.illust[target] && this.illust[target].id) {
index = target;
} else {
for (let i = 0; i < this.illust.length; i++) {
if (target === this.illust[i].id) {
index = i;
break;
}
}
}
if (index > -1) {
if (offset < this.illust[index].final.length) {
// console.log("记录第", offset, "个原图", content, "到", index);
// 取得的原图链接
this.illust[index].result[offset] = content;
// 最终的原图链接,1 -> yes,0 -> no,-1 -> failed
this.illust[index].final[offset] = parseInt(status);
result = true;
} else {
// console.log(offset, "已越界");
}
}
// console.groupEnd();
return result;
};
// 完工?
// final[],1 -> yes,0 -> no,-1 -> failed
// 遍历所有 final, 发现 0 即为未完成
this.isAllDone = function () {
// console.group("isAllDone", this.illust.length);
var working = false;
// console.group("loop illust[]");
for (let i = 0; i < this.illust.length && !working; i++) {
// console.log("illust[", i, "]: id =", this.illust[i].id, ", final.length =", this.illust[i].final.length);
if (0 === this.illust[i].final.length) {
working = true;
// console.warn("final.length=0, 即还未记录结果, 属未完成");
break;
}
for (let j = 0; j < this.illust[i].final.length && !working; j++) {
// console.log("\tfinal[", j, "] =", this.illust[i].final[j]);
if (0 === this.illust[i].final[j]) {
working = true;
// console.warn("illust[", i, "].final[", j, "] = 0, 还未完成");
break;
}
}
}
// console.groupEnd();
if (working) {
// console.warn("在忙");
} else {
// console.warn("完工!!!");
}
// console.groupEnd();
return !working;
};
// 导出结果
this.exportAll = function () {
// console.group("exportAll");
var j,
k,
total = 0,
failed = new Array(this.illust.length),
src = [],
result = {};
for (let i = 0; i < this.illust.length; i++) {
for (j = 0, k = 0; j < this.illust[i].final.length; j++) {
if (1 === this.illust[i].final[j]) {
src[total++] = this.illust[i].result[j];
k++;
}
}
failed[i] = j - k;
// console.log("illust[", i, "]导出", k, "个,失败", failed, "个");
}
// console.log("共导出", total, "个");
result.fail = failed;
result.done = src;
// console.groupEnd();
return result;
};
// 导出 ID
this.getID = function () {
// console.group("getID");
var result = [];
for (let i = 0; i < this.illust.length; i++) {
result[i] = this.illust[i].id;
}
// console.groupEnd();
return result;
};
}
/**********************************************************************
* 基础设施
**********************************************************************/
// 页面显示信息
var msg = function (msg) {
$id("extracted").innerHTML = msg;
};
// 创建样式表
var addStyle = function () {
apendStyle(".cmheia_checkbox {position:absolute;left:0;} .cmheia_item {padding:1px 1px 7px;} .cmheia_item_unselect {background-color:pink;}");
};
// 作品目录?
// 综合
// http://www.pixiv.net/member_illust.php?id=xxxxxxxx
// 插画
// http://www.pixiv.net/member_illust.php?type=illust&id=xxxxxxxx
// 漫画
// http://www.pixiv.net/member_illust.php?type=manga&id=xxxxxxxx
// 动图
// http://www.pixiv.net/member_illust.php?type=ugoira&id=xxxxxxxx
// 小说
// http://www.pixiv.net/novel/member.php?id=xxxxxxxx
var isWorksList = function () {
// console.group('页面类型');
var userId,
workId;
userId = window.location.search.match(/[^_]id=(\d+)/);
workId = window.location.search.match(/illust_id=(\d+)/);
if (userId) {
// console.log("作品目录,USER ID:", userId[1]);
}
if (workId) {
// console.log("作品页面,WORK ID:", workId[1]);
}
// console.groupEnd();
return null !== userId && null === workId;
};
// 匹配单个图片链接
var parseImageUrl = function (src) {
var result = src.match(/((http|https):\/\/)+(\w+\.)+(\w+)[\w\/\.\-]*(jpg|jpeg|gif|png|webp)/gi);
if (null === result || 1 !== result.length) {
return null;
}
return result[0];
};
// 提取多图页面原图链接
var parseMultiImageUrl = function (target, callback) {
// console.group("parseMultiImageUrl", target);
var num = target.length,
parsed = 0,
result = {};
var referer = target[0].replace(/big/, "medium");
// console.warn('Referer :', referer);
result.done = new Array(num);
result.fail = new Array(num);
for (let i = 0; i < num; i++) {
// console.log(target[i]);
// 下面闭包的 index 无实际必要,
// xhr.finalUrl.replace(/.*(page=\d+)/, "$1") 可取得相同的值,
// 然而
// 听说闭包很深奥,那就多练练
GM_xmlhttpRequest({
method : 'GET',
url : target[i],
headers: {
'Referer': referer
},
onload : (function (xhr) {
var index = i;
return function (xhr) {
var src;
if (200 === xhr.status) {
src = parseImageUrl(xhr.response);
if (null !== src) {
result.done[index] = src;
}
}
// console.log("parseMultiImageUrl:onload", xhr.finalUrl.replace(/.*(page=\d+)/, "$1"), parsed, src, result);
if (++parsed === num) {
callback(result);
}
};
})(),
onerror: (function (xhr) {
var index = i;
return function (xhr) {
// console.log("parseMultiImageUrl:onerror", xhr.finalUrl.replace(/.*(page=\d+)/, "$1"));
result.fail[index] = xhr.finalUrl;
if (++parsed === num) {
callback(result);
}
};
})()
});
}
// console.groupEnd();
return num;
};
/**********************************************************************
* 作品目录页面功能
**********************************************************************/
// 解析详情页链接
var extractIllustUrl = function () {
// console.group("extractIllustUrl");
var id = [],
itemList = $class('_image-items').children;
if (itemList) {
let offset = itemList[0].children[0].children[0].children.length - 1;
// console.log("offset", offset);
for (let i = 0; i < itemList.length; i++) {
// console.log(itemList[i].children[0].children[0].children);
if (itemList[i].children[0].children[0].children[offset].checked) {
let href = itemList[i].children[1].getAttribute('href');
if (href && href.match(/.*illust_id=(\d+).*/)) {
// id.push(href.replace(/.*illust_id=(\d+).*/, "$1") || "");
id.push(href);
}
}
}
}
// console.log(id);
// console.groupEnd();
return id;
};
// 选中全部图片
var ctrlSelectAll = function () {
// console.group("ctrlSelectAll");
var itemList = $class('_image-items').children;
if (itemList) {
for (let i = 0; i < itemList.length; i++) {
itemList[i].children[0].children[0].children[1].checked = !0;
removeClassName(itemList[i].children[0], 'cmheia_item_unselect');
}
}
// console.groupEnd();
};
// 反选
var ctrlSelectInvert = function () {
// console.group("ctrlSelectInvert");
var itemList = $class('_image-items').children;
if (itemList) {
for (let i = 0; i < itemList.length; i++) {
let x = itemList[i].children[0].children[0].children[1].checked;
itemList[i].children[0].children[0].children[1].checked = !x;
toggleClassName(itemList[i].children[0], 'cmheia_item_unselect');
}
}
// console.groupEnd();
};
// 提取指定页面
var fetchPageContent = function (arr, prefix, onload, onerror, referer) {
// console.group('fetchPageContent');
// console.warn('Referer :', referer);
for (let i of arr) {
// 听说闭包很深奥,那就多练练
var target = i.replace(/.*illust_id=(\d+).*/, "$1");
// console.log(prefix + i);
GM_xmlhttpRequest({
method : 'GET',
url : prefix + i,
headers: {
'Referer': referer
},
onload : (function (xhr) {
var id = target;
return function (xhr) {
onload(id, xhr);
};
})(),
onerror: (function (xhr) {
var id = target;
return function (xhr) {
onerror(id, xhr);
};
})()
});
}
// console.groupEnd();
};
// 从 html 源码提取原图链接
// 先尝试作为单图解析,解析失败再作为图集解析,解析再次失败再作为动图解析
// 返回:
// 单图 -> 原图链接(57565823);
// -> html 中包含字符串 "original-image"
// 多图 -> 包含原图的目标页面链接(第二个参数为此而生)(56207143);
// -> html 中包含字符串 "multiple"
// 动图 -> 原图压缩包链接(44588377,56083603)(动图仅包含单个 zip , 使用与单图相同的方法处理)
// -> html 中包含字符串 "ugoira_view"
var parseWorkPage = function (html, url) {
// console.group("parseWorkPage");
// 2016-07-18 更新特征:
// 单图 -> 原图链接(57565823);
// -> html 中包含字符串 "original-image"
// -> document.querySelector('.works_display').innerHTML.indexOf('manga') === -1
// -> html 中仅字符串 "manga" 仅出现一次 <meta name="keywords" content="pixiv,插画,漫画,manga,社区,SNS投稿,比赛">
// -> 即 XMLHttpRequest.responseText.match(/manga/gi).length === 1
// 多图 -> 包含原图的目标页面链接(第二个参数为此而生)(56207143);
// -> html 中包含字符串 "multiple"
// -> html 中仅字符串 "manga" 仅出现一次 <meta name="keywords" content="pixiv,插画,漫画,manga,社区,SNS投稿,比赛">
// -> document.querySelector('.works_display').innerHTML.indexOf('manga') !== -1
// -> 即 XMLHttpRequest.responseText.match(/manga/gi).length > 1
// 动图 -> 原图压缩包链接(44588377,56083603)(动图仅包含单个 zip , 使用与单图相同的方法处理)
// -> html 中包含字符串 "ugoira_view"
// -> document.querySelector('.works_display').innerHTML.indexOf('manga') === -1
// -> html 中仅字符串 "manga" 仅出现一次 <meta name="keywords" content="pixiv,插画,漫画,manga,社区,SNS投稿,比赛">
// -> 即 XMLHttpRequest.responseText.match(/manga/gi).length === 1
// 实例:
// 单图
// <div class="works_display"><div class="_layout-thumbnail ui-modal-trigger"><img src="http://i1.pixiv.net/c/600x600/img-master/img/2015/01/23/12/29/40/xxxxxxxx_p0_master1200.jpg" alt="Верный"></div></div>
// 多图(伪)
// <div class="works_display"><a href="member_illust.php?mode=big&illust_id=xxxxxxxx" target="_blank" class=" _work manga "><div class="_layout-thumbnail"><img src="http://i3.pixiv.net/c/600x600/img-master/img/2015/11/13/20/05/08/xxxxxxxx_p0_master1200.jpg" alt="COMITIA114"></div></a></div>
// 多图(真)
// <div class="works_display"><a href="member_illust.php?mode=manga&illust_id=xxxxxxxx" target="_blank" class=" _work multiple "><div class="_layout-thumbnail"><div class="multiple"><i class="_icon-20 _icon-files"></i></div><img src="http://i3.pixiv.net/c/600x600/img-master/img/2016/07/15/20/47/58/xxxxxxxx_p0_master1200.jpg" alt="シャロ生誕祭"></div></a></div>
// 动图
// <div class="works_display"><div class="_ugoku-illust-player-container ready playing"><div class="wrapper"><div class="_spinner"></div><div class="player toggle"><canvas width="477.326968973747" height="600" style="width: 477.327px; height: 600px;"></canvas></div><a href="/member_illust.php?mode=ugoira_view&illust_id=xxxxxxxx" target="_blank" class="full-screen _ui-tooltip" data-tooltip="全屏显示"><img src="http://source.pixiv.net/www/images/ugoku-illust/full-screen.png?2" width="20" height="20"></a></div></div><div class="_full-screen-container"><div class="_ugoku-illust-player-container"><div class="wrapper toggle"><div class="_spinner"></div><div class="player"></div></div><div class="exit-full-screen"><img src="http://source.pixiv.net/www/images/ugoku-illust/exit-full-screen.png" width="30" height="30"></div></div></div></div>
// 对应正则:
// /<div[^<>]*class=\"works_display\">[^<>]*<(\w*)[^<>]*class=\"([\w\s\-\_]*)\"[^<>]*>/
// /<div[^<>]*class[^<>]*=[^<>]*\"[^<>]*works_display[^<>]*\">[^<>]*<(\w*)[^<>]*class[^<>]*=[^<>]*\"([\w\s\-\_]*)\"[^<>]*>/
// 上述实例 match 结果:
// 单图
// ["<div class="works_display"><div class="_layout-thumbnail ui-modal-trigger">", "div", "_layout-thumbnail ui-modal-trigger"]
// 多图(伪)
// ["<div class="works_display"><a href="member_illust.php?mode=big&illust_id=xxxxxxxx" target="_blank" class=" _work manga ">", "a", " _work manga "]
// 多图(真)
// ["<div class="works_display"><a href="member_illust.php?mode=manga&illust_id=xxxxxxxx" target="_blank" class=" _work multiple ">", "a", " _work multiple "]
// 动图
// ["<div class="works_display"><div class="_ugoku-illust-player-container ready playing">", "div", "_ugoku-illust-player-container ready playing"]
var result = [],
target = html.match(/<div[^<>]*class=\"works_display\">[^<>]*<(\w*)[^<>]*class=\"([\w\s\-\_]*)\"[^<>]*>/);
if (target && 3 === target.length) {
// 先尝试用类名判断
if (-1 !== target[2].indexOf("trigger")) {
// 单图
target = html.match(/<img\s+alt=\"[^\"]*\".*data-src=\"([^\"]*)\".*class=\"original-image\">/);
if (target && target[1]) {
result.push(target[1]);
}
// console.log("单图", result);
// console.log(target);
} else if (-1 !== target[2].indexOf("multiple")) {
// 多图(真)
target = html.match(/<ul class=\"meta\"><li>[^<>]*<\/li><li>[^<>\d]*(\d+)P<\/li>/);
if (target && target[1]) {
let count = parseInt(target[1]);
result.push(count);
for (let i = 0; i < count; i++) {
let link = url.replace(/medium/, "manga_big");
link = `${link}&page=${i}`;
result.push(link);
}
}
// console.log("多图(真)", result);
// console.log(target);
} else if (-1 !== target[2].indexOf("_ugoku")) {
// 动图
target = html.match(/pixiv\.context\.ugokuIllustFullscreenData[\s]*=[\s]*\{[^}]*\"src\"[\s]*:[\s]*\"((http|https):[\\\/]*[\w\d\.]*pixiv\.net(.*)\/(\d+)_ugoira(\d+)x(\d+)\.zip)\"/);
if (target && target[1]) {
result[0] = target[1].replace(/\\(.)/gi, '$1');
}
// console.log("动图", result);
} else if (-1 !== target[2].indexOf("manga")) {
// 多图(伪)
result.push(1);
result.push(url.replace(/medium/, "big"));
// http://www.pixiv.net/member_illust.php?mode=big&illust_id=53517282
// 这个链接直接打开会被302导致失败
// 需要设置 Referer
// console.log("多图(伪)", result);
// console.log(target);
} else {
// 未知
// console.error("错误:未知类型", target);
}
} else {
// 不行再靠老一套
target = html.match(/<img\s+alt=\"[^\"]*\".*data-src=\"([^\"]*)\".*class=\"original-image\">/);
if (target && target[1]) {
// 单图
result[0] = target[1];
// console.log("单图", result);
} else if (-1 !== html.indexOf("multiple") && (target = html.match(/<ul class=\"meta\"><li>[^<>]*<\/li><li>[^<>\d]*(\d+)P<\/li>/)) && target && target[1]) {
// 根据 meta 判断遇到作者使用多图模式发表单张图片会失败
// meta === "一次性投稿多张作品 "(\d+)"P"
// 多图
// http://www.pixiv.net/member_illust.php?mode=manga_big&illust_id=xxxxxxxx&page=0
let count = parseInt(target[1]);
result.push(count);
for (let i = 0; i < count; i++) {
let link = url.replace(/medium/, "manga_big");
link = `${link}&page=${i}`;
result.push(link);
}
// console.log("多图", result, target);
} else if (html.match(/manga/gi).length > 1) {
// 多图模式的单图
result.push(1);
result.push(url.replace(/medium/, "big"));
// http://www.pixiv.net/member_illust.php?mode=big&illust_id=53517282
// 这个链接直接打开会被302导致失败
// 需要设置 Referer
// console.log("多图模式的单图", result, target);
} else if (-1 !==html.indexOf("ugoira_view") && (target = html.match(/pixiv\.context\.ugokuIllustFullscreenData[\s]*=[\s]*\{[^}]*\"src\"[\s]*:[\s]*\"((http|https):[\\\/]*[\w\d\.]*pixiv\.net(.*)\/(\d+)_ugoira(\d+)x(\d+)\.zip)\"/)) && target && target[1]) {
// 动图
// http://www.pixiv.net/member_illust.php?mode=medium&illust_id=xxxxxxxx
result[0] = target[1].replace(/\\(.)/gi, '$1');
// console.log("动图", result[0]);
} else {
// console.error("错误:未知类型", target);
}
}
// console.groupEnd();
return result;
};
// 提取选定的原图
var extractWorkList = function (url) {
// console.group("开始提取");
var exportImages = function () {
if (result.isAllDone()) {
var info,
arr,
res = result.exportAll();
// console.log("已采集原图:", res.done);
// console.log("提取失败: ", res.fail);
info = "搞到 " + res.done.length + " 张图啦 (⺻▽⺻ )";
arr = result.getID();
for (let i = res.fail.length - 1; i >= 0; i--) {
if (0 === res.fail[i]) {
arr.splice(i, 1);
}
}
if (arr.length) {
info += " 然而" + arr.toString() + "提取失败 (ಥ_ಥ)";
}
msg(info);
GM_setClipboard(res.done.join("\r\n"));
}
};
var recordFails = function (illustId, status) {
// console.error(illustId, "提取失败", status);
msg(illustId + "提取失败 (ಥ_ಥ) [http " + status + "]");
result.recordTargetLength(illustId, -1);
result.setTarget(illustId, null, 0, -1);
};
var progress = 0,
result;
if (0 === url.length) {
msg("至少选择一张图吧 ◔ ‸◔?");
// console.groupEnd();
return;
}
msg("正在赶工 (๑•̀_•́๑)");
// console.log("添加目标", url);
result = new illustCollector();
for (let i = 0; i < url.length; i++) {
result.addTarget(url[i].replace(/.*illust_id=(\d+).*/, "$1"));
}
fetchPageContent(url,
window.location.origin,
function (illustId, xhr) {
// console.group("得到页面", illustId, ", 开始解析", illustId == xhr.finalUrl.replace(/.*illust_id=(\d+).*/, "$1"));
progress++;
msg("进度" + progress + "/" + url.length + " (ฅ´ω`ฅ)");
// console.warn("进度" + progress + "/" + url.length + " (ฅ´ω`ฅ)");
if (200 === xhr.status) {
// 解析页面取得原图链接(单图和动图)或新的目标页面链接(多图)
let target = parseWorkPage(xhr.responseText, xhr.finalUrl);
if (target) {
// 记录原图数量
if (1 === target.length) {
result.recordTargetLength(illustId, 1);
// 单图和动图可立即取得原图链接,那就顺手录入,并标记为已完成
let i = result.setTarget(illustId, target[0], 0, 1);
// console.log("记录单图或动图", i);
// msg("到手" + parsed + "页,就剩" + (url.length - parsed) + "页啦 (ฅ´ω`ฅ)");
} else {
var count = target.shift();
result.recordTargetLength(illustId, count);
// 多图需要再次解析链接
// console.warn("多图需要再次解析链接", target);
if (1 === count && 1 === target.length) { // 伪多图
result.setTarget(illustId, target[0], 0, 0);
// console.warn("伪多图", target[0]);
} else {
for (let i = 0; i < count; i++) {
result.setTarget(illustId, target[i], i, 0);
// console.log(target[i]);
}
}
parseMultiImageUrl(target, function (obj) {
// console.warn("n:callback", obj);
// console.log("搞完这 ", count, " 张图啦 (⺻▽⺻ )");
for (let i = 0; i < count; i++) {
let status = (undefined !== obj.done[i] && undefined === obj.fail[i]) ? 1 : -1;
result.setTarget(illustId, obj.done[i], i, status);
}
exportImages();
});
}
} else {
recordFails(illustId, xhr.status);
}
} else {
recordFails(illustId, xhr.status);
}
exportImages();
// console.groupEnd();
},
function (illustId, xhr) {
// console.group("页面", illustId, ", 获取失败", illustId == xhr.finalUrl.replace(/.*illust_id=(\d+).*/, "$1"));
progress++;
msg("进度" + progress + "/" + url.length + " (ฅ´ω`ฅ)");
recordFails(illustId, xhr.status);
exportImages();
// console.groupEnd();
},
window.location.href
);
// console.groupEnd();
};
// 添加按钮
var addButtonWorkList = function () {
// console.group("addButtonWorkList");
var itemList = $class("_image-items");
if (itemList) {
let button,
menu = $class('menu-items');
// 全选按钮
button = document.createElement('li');
button.innerHTML="<a href='javascript:;'>全选</a>";
button.addEventListener("click", function () {
ctrlSelectAll();
});
menu.appendChild(button);
// 反选按钮
button = document.createElement('li');
button.innerHTML="<a href='javascript:;'>反选</a>";
button.addEventListener("click", function () {
ctrlSelectInvert();
});
menu.appendChild(button);
// 导出按钮
button = document.createElement('li');
button.innerHTML="<a href='javascript:;'>收割 ๑乛◡乛๑ (●´∀`●)</a><span id='extracted'></span>";
button.addEventListener("click", function () {
extractWorkList(extractIllustUrl());
});
menu.appendChild(button);
// 添加复选框
addStyle();
for (let i = 0; i < itemList.children.length; i++) {
button = document.createElement('input');
button.type = "checkbox";
button.className = "cmheia_checkbox";
button.checked = !0;
// a
// 删除原先的链接
// // console.log(itemList.children[i].children[0]);
itemList.children[i].children[0].removeAttribute('href');
// 增加背景
itemList.children[i].children[0].setAttribute('style', 'margin-bottom:0;');
addClassName(itemList.children[i].children[0], 'cmheia_item');
// addClassName(itemList.children[i].children[0], 'cmheia_item_unselect');
// div
// 增加点击事件
itemList.children[i].children[0].children[0].appendChild(button);
itemList.children[i].children[0].children[0].addEventListener("click", function (e) {
let offset = this.children.length - 1;
// 点击图片切换选中状态
this.children[offset].checked = !this.children[offset].checked;
toggleClassName(this.parentNode, 'cmheia_item_unselect');
});
}
}
// console.groupEnd();
};
/**********************************************************************
* 作品页面功能
**********************************************************************/
// 移除分享按钮
var removeShareButton = function () {
var shareButton = $class('share-button'),
count = shareButton.children.length;
for (let i = 0; i < count; i++) {
shareButton.removeChild(shareButton.children[0]);
}
};
// 添加导出按钮
var addButtonWorkPage = function () {
var button = document.createElement('li');
button.innerHTML="<a href='javascript:;' style='margin:0 8px;'>收割 ๑乛◡乛๑ (●´∀`●)</a><span id='extracted'></span>";
button.addEventListener("click", function () {
extractWorkList([window.location.pathname + window.location.search]);
});
$class('share-button').appendChild(button);
};
// 初始化作品列表界面
var postInitWorksListUI = function () {
let itemList = $class("_image-items");
if (itemList) {
if (1 === itemList.children.length && "" === itemList.children[0].className) {
// <li>未找到任何相关结果</li>
// console.log("未找到任何相关结果");
} else {
addButtonWorkList();
document.addEventListener("keyup", function (event) {
// F9 = 120
if (120 === event.keyCode) {
extractWorkList(extractIllustUrl());
}
}, true);
}
}
console.warn("inited");
};
// 初始化作品列表界面
var initWorksListUI = function () {
var DOMObserverTimer = false;
var DOMObserverConfig = {
childList : true,
subtree : true,
};
var DOMObserver = new MutationObserver(function () {
if (DOMObserverTimer !== 'false') {
clearTimeout(DOMObserverTimer);
}
DOMObserverTimer = setTimeout(function () {
if (!$id("extracted")) {
DOMObserver.disconnect();
postInitWorksListUI();
}
}, 100);
});
DOMObserver.observe(document.querySelector('.image-item'), DOMObserverConfig);
};
// 初始化作品界面
var initWorkPageUI = function () {
removeShareButton();
addButtonWorkPage();
document.addEventListener("keyup", function (event) {
// F9 = 120
if (120 === event.keyCode) {
extractWorkList([window.location.pathname + window.location.search]);
}
}, true);
console.warn("inited");
};
var initPEUI = function () {
if (isWorksList()) {
initWorksListUI();
} else {
initWorkPageUI();
}
};
// 运行
console.warn("P站原图收割机:开始");
initPEUI();
}) ();