Greasy Fork is available in English.
6月新增功能:支持大部分网站视频、音频、图片等资源的下载,并以缩略图形式展示,便于选择下载内容,节省时间和流量。部分加密视频无法下载,请知悉。欢迎留言增加新功能。
当前为
// ==UserScript==
// @name 【自用工具箱】整合好玩好用的各种功能,不定时持续更新中...
// @version 1
// @author Paladin-M
// @namespace Z3JlYXN5Zm9yaw==
// @description 6月新增功能:支持大部分网站视频、音频、图片等资源的下载,并以缩略图形式展示,便于选择下载内容,节省时间和流量。部分加密视频无法下载,请知悉。欢迎留言增加新功能。
// @match *://*/*
// @require https://cdn.staticfile.org/jquery/2.1.4/jquery.min.js
// @require https://cdn.bootcdn.net/ajax/libs/toastr.js/2.1.4/toastr.min.js
// @license End-User License Agreement
// @grant unsafeWindow
// @grant GM_xmlhttpRequest
// @grant GM_setClipboard
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM_openInTab
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM.getValue
// @grant GM.setValue
// @grant GM_info
// @grant GM_notification
// @grant GM_getResourceText
// @grant GM_openInTab
// @grant GM_addStyle
// @grant GM_download
// @noframes
// ==/UserScript==
/*
食用方法:
安装插件成功后,
会在页面最左边的中间出现一个橙色小竖条,
鼠标移动到上面即可出现菜单页面
所有功能都会被整合到此菜单中
点击菜单即可享受
2023.06.12 第一个版本,支持大部分网站视频、音频、图片等资源的下载
并以缩略图形式展示,便于选择下载内容,
节省时间和流量。
部分加密视频无法下载,
请知悉。欢迎留言增加新功能
*/
(function() {
'use strict';
var link = document.createElement('link');
link.href = 'https://cdn.bootcdn.net/ajax/libs/toastr.js/2.1.4/toastr.min.css';
link.rel = 'stylesheet';
link.type = 'text/css';
document.head.appendChild(link);
var $menu = $('<div id="mytoolzxmenu"></div>');
$menu.css({
'position': 'fixed',
'left': '0',
'top': '50%',
'transform': 'translateY(-50%)',
'z-index': '9999',
'cursor': 'pointer',
'background-color': '#ff9900',
'width': '3px',
'height': '60px',
'border-radius': '1px',
'transition': 'width .5s'
})
.appendTo('body');
// Add the click and hover events to the menu
$('body').on('click mouseenter',"#mytoolzxmenu",function(){
if ($("#mytoolzxmenuPage").is(':visible')) {
$(this).animate({width: '3px'}, 300);
$("#mytoolzxmenuPage").fadeOut();
}else{
$("#mytoolzxmenuPage").fadeIn();
$(this).animate({width: '2px'}, 300);
}
});
$('body').on('mouseleave',"#mytoolzxmenuPage",function(){
$("#mytoolzxmenu").animate({width: '3px'}, 300);
$(this).fadeOut();
});
// Set up the menu items
var Menuall = {
download: {
name: "常用功能",
items: [
{ name: "下载页面资源" ,val: "img-down"},
]
},
search: {
name: "其他功能",
items: [
{ name: "待开发",val: "0" },
]
},
// recommend: { }
};
// Set up the menu page
var $menuPage = $('<div id="mytoolzxmenuPage"></div>');
$menuPage.css({
'position': 'fixed',
'left': '0',
'top': '50%',
'transform': 'translateY(-50%)',
'z-index': '9998',
'padding': '20px',
'background-color': '#fff',
'width': '500px',
'height': '700px',
'border-radius': '0 5px 5px 0',
'box-shadow': '5px 0 15px rgba(0,0,0,0.3)',
'display': 'none',
'flex-direction': 'column',
'align-items': 'stretch',
'overflow-y': 'auto'
})
.appendTo('body');
// Add the menu items to the menu page
for (var key in Menuall) {
var $menuItem = $('<div class="menuItem"></div>');
$menuItem.css({
'display': 'flex',
'flex-wrap': 'wrap',
'align-items': 'center',
'justify-content': 'center',
'width': '100%',
'border-radius': '10px',
'margin-bottom': '10px',
'margin-top': '50px',
'cursor': 'pointer',
'transition': 'all .2s',
'position': 'relative'
})
.appendTo($menuPage);
var $categoryName = $('<div class="categoryName"></div>');
$categoryName.text(Menuall[key].name);
$categoryName.css({
'color': '#ff9900',
'font-size': '16px',
'position': 'absolute',
'top': '-25px',
'left': '50%',
'transform': 'translateX(-50%)',
})
.appendTo($menuItem);
var totalHeight = 0;
var subItemCount = Menuall[key].items.length;
for (var i in Menuall[key].items) {
var $subItem = $('<div class="subItem"></div>');
$subItem.text(Menuall[key].items[i].name);
$subItem.css({
'padding': '5px',
'border-radius': '5px',
'cursor': 'pointer',
'transition': 'all .2s',
'flex-grow': 1,
'min-width': '80px',
'max-width': '100px',
'font-size': '15px',
'font-weight': '500',
'justify-content': 'center',
'align-items': 'center',
'text-align': 'center',
})
.attr("gotool", Menuall[key].items[i].val)
.hover(function() {
$(this).css({'background-color': '#ff9900', 'color': '#fff'});
if ($(this).index() == 0) {
$(this).parent().find('.categoryName').css('visibility', 'visible');
}
}, function() {
$(this).css({'background-color': '#fff', 'color': '#000'});
if ($(this).index() == $(this).parent().children().length - 1) {
$(this).parent().find('.categoryName').css('visibility', 'visible');
}
})
.appendTo($menuItem);
totalHeight += $subItem.outerHeight(true)-5;
}
// Set the height of menuItem to the total height of subItems plus 40px padding
$menuItem.css('height', totalHeight + 40);
// Calculate the border radius based on whether it's the first or last row
if (subItemCount == 1) {
$menuItem.css('border-radius', '10px');
} else if (key == 0) {
$menuItem.css('border-top-left-radius', '10px');
$menuItem.css('border-top-right-radius', '10px');
} else if (key == Object.keys(Menuall).length - 1) {
$menuItem.css('border-bottom-left-radius', '10px');
$menuItem.css('border-bottom-right-radius', '10px');
}
}
// Inject the CSS
GM_addStyle('#mytoolzxmenuPage .menuItem:first-child { margin-top: 0; }');
GM_addStyle(`
#mytoolzxmenuPage .menuItem {
background-color: #fff;
color: #000;
font-size: 20px;
font-weight: bold;
box-shadow: 0 5px 15px rgba(0,0,0,0.3);
}
#mytoolzxmenuPage .subItem:hover {
}
`);
var numselected=0;
// create thumbnail container
var thumbnailContainer = $("<div>")
.css({
"position": "fixed",
"top": "50%",
"left": "50%",
"transform": "translate(-50%, -50%)",
"z-index": 999,
"width": "80vw",
"height": "80vh",
"background-color": "#eee",
"overflow": "auto",
"text-align": "center"
})
.hide()
.attr("class", "data-down-ui")
.appendTo($("body"));
// create media type switch buttons
var switchBtnContainer = $("<div>")
.css({
"position": "absolute",
"top": "0",
"left": "0",
"right": "0",
"width": "100%",
"background-color": "#fff",
"padding": "10px",
"text-align": "center",
"box-shadow": "0 2px 5px rgba(0, 0, 0, 0.3)"
})
.appendTo(thumbnailContainer);
var switchBtnVideo = $("<button>")
.css({
"margin-right": "10px"
})
.text("视频列表")
.attr("data-down-button", "video")
.attr("class", "data-down-button")
.appendTo(switchBtnContainer);
var switchBtnAudio = $("<button>")
.css({
"margin-right": "10px"
})
.text("音频列表")
.attr("data-down-button", "audios")
.attr("class", "data-down-button")
.appendTo(switchBtnContainer);
var switchBtnImage = $("<button>")
.text("图片列表")
.css({
"margin-right": "10px"
})
.attr("data-down-button", "images")
.attr("class", "data-down-button")
.appendTo(switchBtnContainer);
var switchBtnselected = $("<button>")
.text("选择全部")
.css({
"margin-right": "10px"
})
.attr("data-down-button", "selected")
.attr("class", "data-down-buttonselected")
.appendTo(switchBtnContainer);
var switchBtnselected = $("<button>")
.text("过滤小图片")
.css({
"margin-right": "10px"
})
.attr("data-down-button", "small")
.attr("class", "data-down-buttonsmall")
.appendTo(switchBtnContainer);
var switchBtndown = $("<button>")
.text("下载所选资源")
.css({
"margin-right": "10px"
})
.attr("data-down-button", "down")
.attr("class", "data-down-down")
.appendTo(switchBtnContainer);
var switchBtnurl = $("<button>")
.text("导出链接")
.css({
"margin-right": "10px"
})
.attr("data-down-button", "url")
.attr("class", "data-down-url")
.appendTo(switchBtnContainer);
// create thumbnail list
var thumbnailList = $("<div>")
.css({
"margin-top": "50px"
})
.attr("thumbnailList", "thumbnailList")
.appendTo(thumbnailContainer);
// create close button
var closeBtn = $("<button>")
.css({
"position": "absolute",
"top": "10px",
"right": "10px",
"background-color": "rgb(167 166 166)",
"border": "1px solid rgb(204, 204, 204)",
"padding": "5px",
"font-size": "16px",
"color": "aliceblue",
"font-weight": "600",
})
.text("×")
.appendTo(thumbnailContainer);
// bind click event to download button
$("body").on('click', '[gotool="img-down"]', function() {
$("#mytoolzxmenu").animate({width: '3px'}, 300);
$("#mytoolzxmenuPage").fadeOut();
var mediaLinks = [];
var mediaTypes = ["video", "audio", "img"];
// get all media links
mediaTypes.forEach(function(mediaType) {
$(mediaType).each(function() {
let src=$(this).attr("src");
if (src){
}else{
if ($("video source:last-of-type").attr("src")){
src=$("video source:last-of-type").attr("src");
}
}
if (src){
if (src.includes(',') || src.includes(';')) {
src=false;
}
}
if (src){
if (mediaType=="img"){
src=src.replace(/webp/g, 'png');
}
let width = $(this).width();
src=completeUrl(src);
mediaLinks.push({
"type": mediaType,
"src": src,
"width": width,
});
}
});
});
$('div, a, span').each(function() {
// 获取元素的计算样式
var computedStyle = window.getComputedStyle(this);
// 判断元素是否存在 background-image 样式
var backgroundImage = computedStyle.getPropertyValue('background-image');
if (backgroundImage !== 'none') {
let src=backgroundImage;
var matchaa = src.match(/url\(["']?(.*?)["']?\)/);
if (matchaa && matchaa.length > 1) {
src = matchaa[1];
}
if (src.includes(',') || src.includes(';')) {
src=false;
}
if (src){
let width = $(this).width();
src=src.replace(/webp/g, 'png');
src=completeUrl(src);
mediaLinks.push({
"type": 'img',
"src":src,
"width": width,
});
return;
}
}
// 判断元素是否存在 background: url() 样式
var backgroundUrl = computedStyle.getPropertyValue('background');
var matches = backgroundUrl.match(/url\(['"]?([^'"\(\)]*)['"]?\)/);
if (matches && matches.length > 1) {
let src=matches[1];
var matchaa = src.match(/url\(["']?(.*?)["']?\)/);
if (matchaa && matchaa.length > 1) {
src = matchaa[1];
}
if (src.includes(',') || src.includes(';')) {
src=false;
}
if (src){
let width = $(this).width();
src=src.replace(/webp/g, 'png');
src=completeUrl(src);
mediaLinks.push({
"type": 'img',
"src":src,
"width": width,
});
}
}
});
// generate thumbnail list
var videonum=0;
var audionum=0;
var imgnum=0;
mediaLinks.forEach(function(mediaLink, index, array) {
var thumbnail = $("<div>")
.css({
"display": "inline-block",
"margin": "10px",
"cursor": "pointer"
})
.attr("class", "data-down-list");
if (mediaLink.type === "video") {
var videoThumbnail = $("<video>")
.attr("src", mediaLink.src)
.attr("height", "120px")
.attr("controls", "controls");
thumbnail.attr("data-url", mediaLink.src)
thumbnail.append(videoThumbnail);
videonum++
$('[data-down-button="video"]').text('视频列表('+videonum+')');
}
else if (mediaLink.type === "audio") {
var audioThumbnail = $("<audio>")
.attr("src", mediaLink.src)
.attr("controls", "controls");
thumbnail.attr("data-url", mediaLink.src)
thumbnail.append(audioThumbnail);
audionum++
$('[data-down-button="audios"]').text('音频列表('+audionum+')');
}
else {
var imageThumbnail = $("<img>")
.attr("src", mediaLink.src)
.attr("data-width", mediaLink.width)
.attr("height", "120px");
thumbnail.attr("data-url", mediaLink.src)
thumbnail.append(imageThumbnail);
imgnum++
$('[data-down-button="images"]').text('图片列表('+imgnum+')');
}
thumbnailList.append(thumbnail);
// bind click event to thumbnails
thumbnail.on("click", function() {
GM_setClipboard(mediaLink.src);
toastr.success('已选择并复制了此资源链接!', '', { positionClass: 'toast-bottom-right', showDuration: 300, hideDuration: 1000, timeOut: 3000, extendedTimeOut: 1000, showEasing: 'swing', hideEasing: 'linear', showMethod: 'fadeIn', hideMethod: 'fadeOut' });
if (mediaLink.type === "video") {
}
});
});
// show thumbnail container
thumbnailContainer.show();
});
// bind click event to switch buttons
switchBtnVideo.on("click", function() {
thumbnailList.find("div").hide();
thumbnailList.find("video").parent().show();
});
switchBtnAudio.on("click", function() {
thumbnailList.find("div").hide();
thumbnailList.find("audio").parent().show();
});
switchBtnImage.on("click", function() {
thumbnailList.find("div").hide();
thumbnailList.find("img").parent().show();
});
// bind click event to close button
closeBtn.on("click", function() {
thumbnailContainer.hide();
thumbnailList.empty();
});
// add custom styles
GM_addStyle(`
::selection {
background-color: #4285f4;
color: #fff;
}
`);
$("body").on('click', '.data-down-list', function() {
if ($(this).hasClass('selected')) {
$(".data-down-buttonselected").removeClass("selected");
}
$(this).toggleClass("selected");
getallnum();
})
$("body").on('click', '.data-down-button', function() {
$(".data-down-button").removeClass("selected");
$(this).toggleClass("selected");
$(".data-down-buttonsmall").removeClass("selected");
getallnum();
})
$("body").on('click', '.data-down-buttonselected', function() {
var list=false;
$(".data-down-list").each(function(k,v){
if ($(this).hasClass('selected')) {
list=true;
}
})
if (list){
$(".data-down-list").removeClass("selected");
$(this).removeClass("selected");
$(this).text("选择全部");
}else{
$(".data-down-list").addClass("selected");
$(this).addClass("selected");
getallnum();
}
})
function getallnum() {
let selectedindex=0;
$(".data-down-list.selected").each(function(k,v){
if ($(this).is(':visible')){
selectedindex++;
}
})
$(".data-down-buttonselected").text("选择全部("+selectedindex+")");
numselected=selectedindex;
}
$("body").on('click', '.data-down-buttonsmall', function() {
if ($(this).hasClass('selected')) {
$(".data-down-list").find("img").each(function(k,v){
$(this).parent().show();
})
$(this).removeClass("selected");
} else{
$(".data-down-list").find("img").each(function(k,v){
if ($(this).attr('data-width')) {
let width=$(this).attr('data-width');
if (width<120){
$(this).parent().hide();
}
}
})
$(this).addClass("selected");
}
getallnum();
})
$("body").on('click', '.data-down-url', function() {
var urls = [];
let selectedindex=0;
$(".data-down-list.selected").each(function(k,v){
if ($(this).is(':visible')){
urls.push($(this).attr('data-url'));
selectedindex++;
}
})
let downstr='导出失败';
if (selectedindex==0){
if ($(".data-down-list").length>0){
downstr=downstr+",请选择需要导出的资源。点击屏幕中的资源即可选中";
}else{
downstr=downstr+",当前没有搜索到任何资源";
}
toastr.error(downstr, '', { positionClass: 'toast-top-center', showDuration: 300, hideDuration: 1000, timeOut: 3000, extendedTimeOut: 1000, showEasing: 'swing', hideEasing: 'linear', showMethod: 'fadeIn', hideMethod: 'fadeOut' });
}
else{
var myText = urls.join('\n\n');
GM_setClipboard(myText);
var container = document.createElement('div');
container.style.backgroundColor = '#fff';
container.style.border = '1px solid #ccc';
container.style.borderRadius = '5px';
container.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.2)';
container.style.width= '600px';
container.style.top = '50%';
container.style.left = '50%';
container.style.transform = 'translate(-50%, -50%)';
container.style.textAlign = 'center';
container.style.zIndex = '9999';
container.style.position = 'absolute';
document.body.appendChild(container);
// 创建复制按钮
var copyButton = document.createElement('button');
copyButton.innerText = '复制';
copyButton.style.width = '50px';
copyButton.style.height = '25px';
copyButton.style.borderRadius = '5px';
copyButton.style.backgroundColor = '#6175bd';
copyButton.style.margin='8px 10px';
copyButton.style.border= 'none';
copyButton.style.marginRight= '10px';
copyButton.style.color= 'white';
copyButton.onclick = function() {
myTextarea.select();
document.execCommand('copy');
alert('已复制到剪贴板');
};
container.appendChild(copyButton);
// 创建关闭按钮
var closeButton = document.createElement('button');
closeButton.innerText = '关闭';
closeButton.style.width = '50px';
closeButton.style.height = '25px';
closeButton.style.borderRadius = '5px';
closeButton.style.backgroundColor = '#6175bd';
closeButton.style.margin='8px 10px';
closeButton.style.border= 'none';
closeButton.style.marginRight= '10px';
closeButton.style.color= 'white';
closeButton.onclick = function() {
container.style.display = 'none';
};
container.appendChild(closeButton);
// 创建文本框
var myTextarea = document.createElement('textarea');
var style = myTextarea.style;
style.width = '600px';
style.height = '700px';
style.resize = 'none';
style.textAlign = 'left';
style.display= 'inline-block';
style.caretColor='black';
myTextarea.value = myText;
container.appendChild(myTextarea);
// 将复制按钮和关闭按钮添加到文本框上方
container.insertBefore(copyButton, myTextarea);
container.insertBefore(closeButton, myTextarea);
}
})
$("body").on('click', '.data-down-down', function() {
let selectedindex=0;
var urls = [];
$(".data-down-list.selected").each(function(k,v){
if ($(this).is(':visible')){
selectedindex++;
urls.push($(this).attr('data-url'))
}
})
let downstr='下载失败';
if (selectedindex==0){
if ($(".data-down-list").length>0){
downstr=downstr+",请选择需要下载的资源。点击屏幕中的资源即可选中";
}else{
downstr=downstr+",当前没有搜索到任何资源";
}
toastr.error(downstr, '', { positionClass: 'toast-top-center', showDuration: 300, hideDuration: 1000, timeOut: 3000, extendedTimeOut: 1000, showEasing: 'swing', hideEasing: 'linear', showMethod: 'fadeIn', hideMethod: 'fadeOut' });
return
}else{
urls.forEach(function(url, index) {
if (url.startsWith('data:image')){
var blob = b64toBlob(base64Data);
url=URL.createObjectURL(blob);
}
let fileName=getFileNameFromUrl(url);
GM_download({
url: url,
name: fileName,
saveAs: false,
onload: function() {
toastr.success('已下载'+(index+1)+"个资源,剩余"+(selectedindex-(index+1 ))+"...", '', { positionClass: 'toast-bottom-right', showDuration: 300, hideDuration: 1000, timeOut: 3000, extendedTimeOut: 1000, showEasing: 'swing', hideEasing: 'linear', showMethod: 'fadeIn', hideMethod: 'fadeOut' });
},
onerror: function(err) {
console.error('第'+(index)+'个资源下载失败'+err , err);
}
});
});
}
})
$("<style>")
.prop("type", "text/css")
.html(`
.data-down-ui .data-down-list:hover {
border: 2px solid #00BFFF;
box-shadow: 0 0 5px #00BFFF;
}
.data-down-ui .selected {
border: 2px solid #ed3f68;
box-shadow: 0 0 5px #ff8ef1;
}
.data-down-ui .data-down-button, .data-down-buttonselected, .data-down-buttonsmall, .data-down-down, .data-down-url{
border: none;
border-radius: 10px;
background-color: #6175bd;
color: white;
padding: 8px 10px;
font-size: 15px;
}
`)
.appendTo("head");
function completeUrl(url) {
if (url){
if (/^https?:\/\//i.test(url)) {
return url;
}
if (/^\/\//.test(url)) {
if (location.protocol === 'https:') {
return 'https:' + url;
}else{
return 'http:' + url;
}
}
if (url.startsWith('data:')) {
var commaIndex = url.indexOf(',');
if (commaIndex !== -1) {
var base64String = url.slice(commaIndex + 1);
return url;
}
}
var origin = window.location.origin;
if (url.indexOf('http') == -1){
if (url.startsWith('/')){
return origin + url;
}else{
return origin +'/'+ url;
}
}
return url;
}
}
function b64toBlob(base64Data) {
var byteString = atob(base64Data.split(',')[1]);
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], {type: 'image/jpeg'});
}
function getFileNameFromUrl(url) {
var fileName = '';
if (url.indexOf('?') >= 0) {
url = url.split('?')[0]; // 去掉查询参数
}
var pos = url.lastIndexOf('/');
if (pos < 0) {
pos = url.lastIndexOf('\\');
}
if (pos >= 0) {
fileName = url.substring(pos + 1);
} else {
fileName = url;
}
return fileName;
}
})();