xchina

good

// ==UserScript==
// @name        xchina
// @version      2025.04.24
// @author       You
// @include     https://xchina.co/*
// @include     https://img.xchina.store/*
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// @grant        GM_download
// @grant        GM_xmlhttpRequest
// @connect       *
// @require     https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.5.1.min.js
// @require		https://code.jquery.com/jquery-3.6.0.min.js
// @require https://update.greasyfork.org/scripts/480132/1534996/Get_all_img_Library.js
// @require https://update.greasyfork.org/scripts/522187/1532433/Kquery.js
// @namespace https://greasyfork.org/users/1210231
// @description good
// ==/UserScript==

$(function(){
	add_bu()
		.click(()=>{sessionStorage.setItem('startAjax','true');location.reload(true)})  //先清除缓存,再ajax
	Add_new_container()
	if(sessionStorage.getItem('startAjax')=='true'){get_list(get_big_img);sessionStorage.setItem('startAjax','false')}  //判断是否ajax
})
function add_bu(){
	let bu = $('<button>Ajax10</button>')
			.css({
				width:'100%',
				'font-size':'10vw'
			})
	$('.photos').before(bu);
	$('.breadcrumb').after(bu);
	return bu
}
function Add_new_container(){
	const box = $('<div></div>').css({
		width:'100vw',
		height:'100vh',
		'overflow':'auto',
		'position':'fixed',
		top:0,
		left:0,
		'z-index':9999,
	})
	
}
function get_list(callback){
	if(window.location.href.match(/xchina\.co\/photo\/id-\w+\.html/g)){}else{sessionStorage.removeItem('page');return}
 
	let key = "xchina"
	let atag = $('a.next[href]:first')
	let nums = (()=>{
					if(atag.length>0&&atag.prev().length>0){
						return Number(atag.prev().text())
					}else{
						return 1
					}
				})()
	atag = $('a[current="true"]:first')
	if(atag.length==0){callback($('.photos').children());return}
	$('.photos').children().remove()
	//page记录当前ajax到了第几页
	let page = sessionStorage.getItem('page')
	if(!page){page=0}else{page = Number(page)}
	if(page>=nums-1){page=0}
 
	let geturl = function(i){
		            if(i>=10){sessionStorage.setItem('page',i+page);return false}
					if(i+page>=nums){sessionStorage.setItem('page',0);return false}
					return atag[0].href.replace(/\d+(?=\.)/,(i+1+page))
				}
	let getimg = function(data){return $(data).find('.photos').children().attr('ccc','yes')}
	let putimg = function(img,i){
		$('.photos').append(img)
		setTimeout(function(){$('.mass_top').css('font-size','10vw').text(`${page + i + 1}/${nums}`)},1000)
 
		$('.photos').children('*:not([ccc])').remove()
		del_ad();
		callback(img)
	}
	window.GAIL.get_img_obo_ajax_href(key,nums,geturl,getimg,putimg)
}
let showbox = new ShowBox();
showbox.Set_donwloadType("blob");
function Put_img_to_ClickShowBox(imgs){
	showbox.Add(imgs)
	console.log('Put_img_to_ClickShowBox is run');
}
function get_big_img(img){
	let iimg = img.find('img')
	iimg.each(function(){
        let parent = $(this).parent().before($(this).attr('big','yes'))
        parent.hide()
		$(this).attr('big_src',this.src.replace(/_[^\.]+/g,"").replace(/\w+$/g,"jpg"))
		//this.src = this.src.replace(/_[^\.]+/g,"").replace(/\w+$/g,"jpg")
		$('body').append($('<p></p>').text(this.src))
		$(this).parents('a:first[href]').removeAttr('href')
		$(this).click(function(){
			let name = document.title + new Date().getTime() + ".jpg"
			let src = $(this).attr('big_src')
			let _this = this
			GM_download({
				url:src,
				name:name,
				onload:()=>{$(_this).remove()}
			})
		})
	})
	Put_img_to_ClickShowBox(iimg);
	$(".push-bottom").remove()
	return
 
}
function checkimg_unloaded(){
	let checking = function(){
		let img = $('img[big]:visible').filter(function(){return this.naturalWidth == 0})
		if(img.length>0){
			img.each(function(){
				var clone = $(this).clone(true)
				$(this).after(clone)
				$(this).remove()
				clone[0].scrollIntoView()
			})
		}else{}
	}
	let check = setInterval(checking,500)
}
function del_ad(){
	$('*:not(.download_bu,.mass_top,.clickShowBox,.clickShowBox *,.clickShowBox_ShowBu,.one_scroll_box)').filter(function(){return $(this).css('position')=="fixed"}).remove()
}
$('body').on('touchend',del_ad);

function Add_to_one_div(){
	let box = `
	<div class="one_scroll_box"></div>
	<style>
		.one_scroll_box{
			width:100vw;
			height:100vh;
			overflow:scroll;
			position:fixe;
			top:0;
			left:0;
			z-index:99999;
		}
	</style>
	`
	$('body').append(box);
	$('.one_scroll_box').append($('body').children());
}
$(function(){
	Add_to_one_div();
})

/**
 * 把图片全部添加到一个Showbox里的类,只能new一次
 * @class
 * @example
 const showBox = new ShowBox();
 showBox.Add(imgs);
 
 @ps Add函数只能调用一次
*/
function ShowBox(){
	let imgs = null;
	let num = 10;
	let showNum = num;
	let nowIndex = 0;
	/**
	 * @type {Downloader}
	*/
	let downloader = window.Downloader ? new window.Downloader() : (() => { throw new DOMException("Downloader does not exist"); })();
	let box = $('.clickShowBox').length > 0 ? $('.clickShowBox') : CreateShowBox()
	downloader.Set_downloadType("GM_download");
	
	this.downloader = {get obj(){return downloader;}}
	/**
	 * 把图片全部添加到一个Showbox里
	 * @example Add(imgs)
	 * @param {JQuery} iimgs
	 * @ps 只能调用一次,等图片获取完了再调用
	*/
	this.Add = (iimgs)=>{
		imgs = iimgs;
		AddImgs();
	}
	
	/**
	 * @example controlType = "mouse"
	*/
	this.controlType = "mouse";
	
	/**
	 * 设置一次预加载多少图片,默认是10
	 * @example SetShowNum = 20
	 * @param {number} n 
	 * @ps 未加载的图片src为空,只有small_src和big_src
	*/
	this.SetShowNum = (n) => {showNum = num = n;}
	
	/**
	 * @param {string} type - {GM_download / atag / blob}
	*/
	this.Set_donwloadType = (type)=>{downloader.Set_downloadType(type);}

	/**
	 * 重写下载图片的方法
	 * @example SetDonloadFunction((imgs)=>{...})
	 * @param {function(JQuery)} foo - (imgs)=>{}
	*/
	this.SetDonloadFunction = (foo)=>{downloader.Download_img = foo;}
	
	function AddImgs(){
		imgs.each(function(){
			const item = $('<div class="item"></div>')
				.append($('<img>').attr({'small_src':this.src,src:"",'big_src':$(this).attr('big_src')}));
			$('.clickShowBox').append(item);
		})
		ClickShowNext({img:$('img'),onlyDown:false});
	}
	function CreateShowBox(){
		let box = `
		<div class="clickShowBox">
			<p class="pages">1/10</p>
			<button class="close">x</button>
			<div class="downloadBU">
				<button class="download">↓</button>
				<button class="downloadall">↓↓</button>
			</div>
		</div>
		<div class="clickShowBox_ShowBu"></div>
		`
		box = $(box);
		$('body').prepend(box);
		
		$('.clickShowBox .close').click(function(){
			$('.clickShowBox').fadeOut();
			$('.clickShowBox_ShowBu').show()
		})
		$('.clickShowBox_ShowBu').click(function(){
			$('.clickShowBox').fadeIn();
			$(this).hide();
			Show_imgs(num);
		})
		$('.clickShowBox .download').click(function(){
			BU_nomal($(this))
			const img = $('.clickShowBox .item img').eq(nowIndex);
			let src = img[0].src;
			if(img.attr('big_src')){
				src = img.attr('big_src');
				img[0].src = src;
			}
			let name = document.title + new Date().getTime() + src.match(/\.jpg|\.jpeg|\.webp|\.png/g)[0];
			if(img.attr('name')){
				name = img.attr('name');
			}
			BU_busy($(this))
			try{
				GM_download({
					url:src,
					name:name,
					onload:function(){
						BU_done($('.download'));
					},
					error:function(){
						BU_error($('.download'));
					}
				})
			}catch(error){
				console.log(error);
				BU_error($('.download'));
			}
		})
		
		$('.clickShowBox .downloadall').click(function(){
			BU_busy($(this));
			try{
				console.log(downloader)
				downloader.Download_img($('.clickShowBox .item img'));
			}catch(error){
				console.log(error);
				BU_error($(this));
			}
		})
		downloader.AllComplete(()=>{
			BU_done($('.clickShowBox .downloadall'));
		});
		downloader.OneSuccess((img)=>{
			var src = img.attr('big_src') || img.attr('big-src') || null;
			console.log(src);
			if(!src){return;}
			img.attr('src',src);
			// $('.clickShowBox .item img').filter(function(){return $(this).attr('big_src')||$(this).attr('small_src') == img[0].src})
			// 							.attr('src',img[0].src);
		});
		Add_ClickShowBox_css();
		$('.clickShowBox').hide();
		Add_keyControl()
		return box;
	}
	
	function Add_ClickShowBox_css(){
		let css = `
		.clickShowBox{
			width: 100%;
			height: 100%;
			background-color: #2d2d2d;
			overflow: hidden;
			border-radius: 0vw;
			position: fixed;
			z-index: 9999;
		}
		.clickShowBox .item{
			width: 100%;
			height: 100%;
			background-color: #2D2D2D;
			display: flex;
			align-items: center;
			justify-content: center;
		}
		.clickShowBox .item img{
			max-width: 100%;
			height: auto;
			max-height: 100%;
		}
		.clickShowBox .pages{
			font-size: 5vw;
			color: rgba(255,255,255,0.5);
			position: fixed;
			top: 1.5vw;
			margin: 2vw;
			right:12vw
		}
		.clickShowBox .close{
			width: 10vw;
			height:10vw;
			font-size: 6vw;
			border-radius: 10vw;
			background-color: rgba(255,255,255,0.1);
			color: rgba(255,255,255,0.1);
			position: fixed;
			right: 0;
			top:0;
			margin: 2vw;
			font-weight: bold;
			border: none;
		}
		.clickShowBox .close:active{
			filter:invert(100%);
		}
		.clickShowBox .downloadBU{
			display: flex;
			flex-direction: row;
			position: fixed;
			bottom:0;
		}
		.clickShowBox .download
		,.clickShowBox .downloadall{
		    width:100%;
			font-size: 5vmin;
			aspect-ratio: 1/1;
			border-radius: 2vmin;
			background-color: #ff8a17;
			color: white;
			margin: 0 0 2vw 2vw;
			border: none;
			opacity: .4;
			position: relative;
		}
		.clickShowBox .download:active
		,.clickShowBox .downloadall:active{
			opacity: .6;
		}
		.clickShowBox .busy{
			animation: BU_busy infinite 1s linear;
		}
		@keyframes BU_busy{
			0%{top:0}
			25%{top:2vw}
			75%{top:-2vw}
			100%{top:0}
		}
		.clickShowBox .error{
			background-color: red;
		}
		.clickShowBox_ShowBu{
			width: 10vw;
			height: 10vw;
			border-radius: 10vw;
			background-color: orange;
			position: fixed;
			bottom: 30%;
			right: -5vw;
			z-index: 999999;
			display: flex;
			align-items: center;
			justify-content: center;
	
		}
		.clickShowBox_ShowBu::after{
			content: "";
			width: 70%;
			height: 70%;
			background-image: url('data:image/svg+xml;utf8,<svg width="10" height="10" xmlns="http://www.w3.org/2000/svg"><path d="M 10 10 L 0 5 L 10 0 Z" fill="White"/></svg>');
			background-size: cover;
			background-repeat: no-repeat;
			transform: scaleX(0.8);
		}
		`
		Add_css(css)
	}
	function BU_busy(bu){
		bu.addClass('busy');
	}
	function BU_done(bu){
		bu.removeClass('busy');
	}
	function BU_error(bu){
		bu.removeClass('busy');
		bu.addClass('error');
	}
	function BU_nomal(bu){
		bu.removeClass('busy').removeClass('error');
	}
	
	function Add_keyControl(){
		let downItem = $('<button><button>').click(function(){
			simulateClick($(window).width()/2,$(window).height()*0.8);
		})
		let upItem = $('<button><button>').click(function(){
			simulateClick($(window).width()/2,$(window).height()*0.2);
		})
		window.GAIL.AddKeyControl(downItem,upItem,null,null,true);
	}
	
	function ClickShowNext({img,onlyDown}){
		if(!$){return;}
		if(img.length<=1){console.log('only one img');return;}
		let item = $('.clickShowBox .item');
		$('.clickShowBox .pages').text(1+"/"+item.length);
		item.on("touchstart mousedown",function(event){
			if ($(window).height()>$(window).width() && event.type === 'mousedown'){return;}
			let y = event.clientY;
			if(event.touches){y = event.touches[0].clientY;}
			let index = item.index($(this));
			index = !onlyDown && y<$(this).height()/2 ? index-1:index+1;
			index = index>=0?Math.min(index,item.length-1):0
			item.eq(index)[0].scrollIntoView();
			$('.clickShowBox .pages').text((index+1)+"/"+item.length);
			nowIndex = index;
			Show_imgs(showNum);
		});
	}
	function Show_imgs(i){
		let img = $('.clickShowBox .item img[small_src][src=""]');
		let start = Math.max(0,nowIndex-i);
		let end = Math.min(img.length,nowIndex+i);
		img.slice(start,end).each(function(){
			this.src = $(this).attr('small_src');
		});
		console.log(`${start} ${end} ${img.length}`)
	}
	function Add_css(cssString){
		var style = document.createElement('style');
		style.type = 'text/css';
		style.innerHTML = cssString;
		document.body.appendChild(style);
	}
}

window.ShowBox = ShowBox;

window.ShowBox.ShowInNewPage = (url)=>{
	GM_setValue('ShowBoxInNewPage','yes');
	window.open(url);
	const img = $('.clickShowBox img');
	GM_setValue('ShowBoxInNewPage_img',img.eq(0)[0].src);
	GM_setValue('ShowBoxInNewPage_num',img.length);
	let i = 1;
	let obo = setInterval(()=>{
		if(i==img.length){clearInterval(obo);return;}
		if(!GM_getValue('ShowBoxInNewPage_img')){
			GM_setValue('ShowBoxInNewPage_img',img.eq(++i).html());
		}
	},100);
}
window.ShowBox.Linsening_ShowInNewPage = ()=>{
	if(!GM_getValue('ShowBoxInNewPage')){
		return;
	}
	GM_deleteValue('ShowBoxInNewPage');
	const box = new window.ShowBox();
	let i = 0;
	let img = ''
	const num = Number(GM_getValue('ShowBoxInNewPage_num'));
	let obo = setInterval(()=>{
		if(i==num){GM_deleteValue('ShowBoxInNewPage_num');box.AddImgs($(img));clearInterval(obo);return;}
		if(GM_getValue('ShowBoxInNewPage_img')){
			img += GM_getValue('ShowBoxInNewPage_img')
			GM_deleteValue('ShowBoxInNewPage_img');
		}
	},100);
}
$(function(){
	window.ShowBox.Linsening_ShowInNewPage();
})

/**
 * 包含多种下载方法的下载类
 * @example
 const downloader = new Downloader();
 downloader.Download_img(imgs);
*/
function Downloader(){
	
	let downloading = 0;
	let downloaded = [];
	let downloadError = [];
	let imgs = null;
	let maxDownloadingCounts = 10;
	let timeout = null;
	let downloadType = ""
	let checkSrc = false;
	
	
	/**
	 * @example Download_img(imgs)
	 */
	this.Download_img = async (imgs)=>{
		Set_download(imgs)
		if(downloadType==""){
			Download_obo("GM_download");return;
		}
 
		console.log(downloadType);
		if(downloadType=="GM_download"){
			Download_obo("GM_download");
		}else if(downloadType=="atag"){
			Download_obo("atag");
			console.log('download atag')
		}else if(downloadType=="blob"){
			Download_obo("blob");
		}else{
			alert("no this donwload type");
		}
	}
 
	this.Set_downloadType = v => downloadType = v;
 
	this.Set_maxDownloadingCounts = v => maxDownloadingCounts = v;
 
	this.Set_timeout = v => timeout = v;
	
	this.Set_checkSrc = v => checkSrc = v;
	/**
	 * @example OneSuccess((success_img)=>{...})
	 */
	function OneSuccess(img){}
	this.OneSuccess = foo=>OneSuccess = foo;
	/**
	 * @example OneError((error_img)=>{...})
	 */
	function OneError(img){}
	this.OneError = foo=>OneError = foo;
	/**
	 * @example AllComplete(()=>{...})
	 */
	function AllComplete(){}
	this.AllComplete = foo=>AllComplete = foo;
	
	this.Set_download = (iimgs)=>{Set_download(iimgs);}
	function Set_download(iimgs){
		downloaded = [];
		downloading = 0;
		downloadError = [];
		imgs = iimgs;
	}
	function Download_obo(dtype){
		async function Download_one(i){
			if(i>=imgs.length){AllComplete();return;}
			if(downloading>=maxDownloadingCounts){setTimeout(()=>{Download_one(i)},1000);return;}
			const img = imgs.eq(i);
			downloading++;
			function success(img){
				OneSuccess(img);
				downloading--;
				downloaded.push(img);
				ConsoleWrite((downloaded.length+downloadError.length)+"/"+imgs.length)
			}
			function error(img){
				OneError(img);
				downloading--;
				downloadError.push(img);
			}
			switch(dtype){
				case "GM_download":
					Donwload_img_by_GM(img)
						.then(img=>success(img))
						.catch(img=>{
							dtype = "blob"
							Download_one(i);
						});
					break;
				case "blob":
					Download_img_by_blob(img)
						.then(img=>success(img))
						.catch(img=>{
							dtype = "atagIfram";
							Download_one(i);
						});
					break;
				case "atagIfram":
					Download_img_by_atag(img)
						.then(img=>success(img))
						.catch(img=>{
							error(img);
							dtype = "GM_download";
						});
					break;
			}
			Download_one(++i);
		}
		Download_one(0);
	}
	function ConsoleWrite(mass){
		if(window.GAIL){
			window.GAIL.showmass(mass);
		}
	}
	this.ConsoleWrite = foo=>ConsoleWrite = foo;
	
	this.Donwload_img_by_GM = img=>{Donwload_img_by_GM(img);}
	function Donwload_img_by_GM(img){
		return new Promise(async(resolve,reject)=>{
			if(!img){alert("img is empty");reject(img);return;}
			if(!GM_download){alert("GM_download is undefind");reject(img);return;}
			let name = '';
			let src = '';
			try{
				await Check_and_get_nameAndsrc({img:img,checkSrc:checkSrc})
						.then((m)=>{
							name = m.name;
							src = m.src;
							console.log(m);
						});
			}catch(error){
				reject(img);
				return;
			}
			console.log(name)
			console.log(src)
			GM_download({
				url:src,
				name:name,
				onload:function(){
					resolve(img);
				},
				onerror:function(){
					reject(img);
				},
				onprogress:function(){
					
				}
			});
			if(timeout){
				setTimeout(()=>{
					reject(img);
				},timeout);
			}
		})
	}
	
	this.Download_img_by_blob = (img)=>{Download_img_by_blob(img);}
	function Download_img_by_blob(img){
		return new Promise(async(rs,rj)=>{
			if(!img){alert("imgs is empty");rj(img);return;}
			
			let name = '';
			let src = '';
			try{
				await Check_and_get_nameAndsrc({img:img,checkSrc:checkSrc})
						.then((m)=>{
							name = m.name;
							src = m.src;
							console.log(m);
						});
			}catch(error){
				rj(img);
				return;
			}
			UrlToBlob({url:src,timeout:timeout})
				.then(blob=>{
					let a = $('<a></a>').attr({
						download:name,
						href:blob
					})
					a[0].click();
					rs(img);
				})
				.catch(er=>{
					console.log(er);
					rj(img);
				});
			if(timeout){
				setTimeout(()=>{
					rj(img);
				},timeout)
			}
		})
	}
	
	this.Download_img_by_atag = (img,nowIsImgPage)=>{Download_img_by_atag(img,nowIsImgPage);}
	async function Download_img_by_atag(img,nowIsImgPage) {
		return new Promise(async(resolve,reject)=>{
			if(!img){alert("imgs is empty");reject(img);return;}
			if(!GM_setValue){alert("GM_setValue is underfind");reject(img);return;}
			if (!nowIsImgPage) {
				let name = '';
				let src = '';
				try{
					await Check_and_get_nameAndsrc({img:img,checkSrc:checkSrc})
							.then((m)=>{
								name = m.name;
								src = m.src;
								console.log(m);
							});
				}catch(error){
					reject(img);
					return;
				}
				GM_setValue("downloadType", "start");
				GM_setValue("downloadName", name);
				GM_setValue("downloadSrc", src);
				let mi = new My_iframe();
				let iframe;
				let isTimeout = false;
				if(timeout){
					setTimeout(()=>{isTimeout = true;},timeout)
				}
				await mi.Add_iframe(src).then(ifr=>iframe = ifr);
				
				const checkDownload = setInterval(() => {
					if (GM_getValue("downloadType") === "end") {
						$(iframe).remove();
						resolve(img);
						clearInterval(checkDownload);
						return;
					}
					if(isTimeout){
						reject(img);
					}
				}, 100);
			}else {
				const newimg = $("img").attr({
					name:GM_getValue("downloadName"),
				})
				await Check_and_get_nameAndsrc({img:newimg,checkSrc:true})
						.then((m)=>{
							let name = m.name;
							let src = m.src;
							$('<a></a>').attr({
								'href': src,
								'download': name,
							})[0].click();
						});
				await new Promise(resolve => setTimeout(resolve, 1000));
				GM_setValue("downloadType", "end");
				window.close();
			}
			
		})
	}
	this.Listening_Download_by_atag = ()=>{
		const locationHref = window.location.href;
		const GM_downloadSrc = GM_getValue("downloadSrc");
		if(!GM_downloadSrc){return;}
		if(GM_downloadSrc == locationHref|| locationHref.indexOf(GM_downloadSrc)>=0 || GM_downloadSrc.indexOf(locationHref)>=0 ){
			Download_img_by_atag($("img"),nowIsImgPage);
		}
	}
	
	
	/**
	 * @example Urls({url:url,timeout : 100})
    */
   this.UrlToBlob = (args)=>{UrlToBlob(args);}
	async function UrlToBlob(args) {
		return new Promise((resolve,reject)=>{
			if(!args.url){reject("no url");}
			if(args.timeout){
				const timeout = setTimeout(function() {reject("fetch timeout")}, args.timeout);
			}
			fetch(args.url)
					.then(response => {
						const contentLength = response.headers.get('Content-Length');
						const total = parseInt(contentLength, 10);
						let loaded = 0;
			
						// 克隆响应以便分别读取流和获得 Blob
						const clonedResponse = response.clone();
						const reader = clonedResponse.body.getReader();
			
						// 更新进度的函数
						function updateProgress({ done, value }) {
							if (done) {
								return; // 如果读取完毕,直接返回
							}
							loaded += value.byteLength; // 累加已加载字节
							const progress = (loaded / total) * 100; // 计算进度百分比
							console.log(`Loading: ${progress.toFixed(2)}%`);
							FetchShowProgress(progress);
							// 继续读取下一块数据
							return reader.read().then(updateProgress);
						}
			
						// 开始读取流以更新进度
						return reader.read().then(updateProgress).then(() => {
							// 完成后返回原始响应的 Blob
							return response.blob();
						});
					})
					.then(blob => {
						const blobUrl = URL.createObjectURL(blob);
						resolve(blobUrl);
					})
					.catch(error => {
						console.error('Error caching video:', error);
						reject(error);
					});
		});
	}
	this.FetchShowProgress = (pro)=>{FetchShowProgress(pro);}
	function FetchShowProgress(pro){
		if(this.maxDownloadingCounts==1 && this.imgs.length==1){
			window.GAIL.showmass(pro);
			$(".mass_top").css('font-size',"10vmin");
		}
	}
	
	this.Check_and_get_nameAndsrc = (args)=>{Check_and_get_nameAndsrc(args);}
	function Check_and_get_nameAndsrc(args){
		return new Promise(async (resolve,reject)=>{
			if(!args || !args.img){return reject();}
			let src = args.img.attr('big_src')||args.img.attr('big-src');
			if(!src){src = args.img.attr('src');}
			if(!src){src = args.img.attr('small_src')||args.img.attr('small-src');}
			if(!src){reject();}
			//console.log("check:"+src)
			if(args.checkSrc){
				try{
					await check_src_is_right(src);
				}catch(error){
					reject();
				}
			}
			let ext = src.match(/\.jpg|\.png|\.webp|\.gif|\.bmp/g);
			if(!ext){ext = '.png';}else{ext = ext[0];}
			let name = args.img.attr('name');
			if(!name){name = document.title + new Date().getTime() + ext;}
			resolve({name:name,src:src,img:args.img});
		});
	}
	
	this.check_src_is_right = (src)=>{check_src_is_right(src);}
	function check_src_is_right(src){
		return new Promise((resolve,reject)=>{
			let iimg = new Image();
			iimg.onload = function(){
				if(this.width*this.height*this.naturalWidth*this.naturalHeight==0){reject();}else{resolve();}
			}
			iimg.onerror = function(){reject();}
			iimg.src = src;
			setTimeout(function() {reject();}, 2000);
		})
	}
	
	function downloadText(text,name) {
	 
	    // 创建 Blob 对象
	    var blob = new Blob([text], { type: "text/plain" });
	 
	    // 创建下载链接
	    var url = URL.createObjectURL(blob);
	 
	    // 创建下载按钮
	    var a = document.createElement("a");
	    a.href = url;
	    a.download = name?name:"downloaded_text"+new Date().getTime()+".txt"; // 文件名
	    document.body.appendChild(a);
	 
	    // 模拟点击下载
	    a.click();
	 
	    // 清理
	    window.URL.revokeObjectURL(url);
	    document.body.removeChild(a);
	}
	this.Download_to_text = (url,name)=>{downloadText(url,name);}
}
$(function(){
	let dd = new Downloader()
	dd.Listening_Download_by_atag()
})