User:Cdip150-bot/votecount.js

维基百科,自由的百科全书

注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。

/*
	vote count
*/
console.clear();

window.setTimeoutat=function(dateobj, func){
	return setTimeout(func, Math.max(1, dateobj.getTime()-Date.now()) );
};

setTimeoutat(new Date("2021-01-01T00:01:01+0800"), function updateDYK() {
	if(mw.util.getParamValue("botcount")!=1 ) return;
	
	var fixh=mw.util.getParamValue("fixh");
	(!fixh || isNaN(fixh) )?fixh=0:fixh*=1;
	if(fixh<0) fixh=100000-fixh;
	
	setTimeout(function step1(){
		if(fixh<100000){
			countvote();
		}else{
			updatehash(true);
		}
	}, 1);
	
	var nexttime=new Date(Date.now()+1*60*60*1000);
	nexttime.setMinutes(2);
	nexttime.setSeconds(50);
	setTimeoutat(
		nexttime
		,
		function(){
			location.replace( (""+location).replace(/\?.*$/, "")+"?botcount=1&fixh="+fixh+"&_="+nexttime.getTime() );
		}
	);
	setTimeout(
		function(){
			failDYKs=[];
			passDYKs=[];
			needchkinv=[];
			updatehash(true);
		}
		, 28.3*60*1000
	);
	

	// common variables and functions;
	var pgnames = {
		WP_DYKC : 'Wikipedia:新条目推荐/候选',
		T_DYK   : 'Template:Dyk',
		T_Pend  : 'Template:Dyk/Pending',
	};
	var maxErrTime=3;
	var failDYKs=[], passDYKs=[], DYKEntryAttrs=["hash","result","article","question","image","author","nominator","timestamp","type"];
	var botpassflag="^", botrepeatflag=":";
	
	String.prototype.replace1st=function(regex, tostr){
		var matches=this.match(regex);
		if(!matches) return this;
		if(matches.length==0) return this;

		return this.replace(matches[0], matches[0].replace(regex, tostr) );
	};
	if("function"!=typeof botpassflag.trim) String.prototype.trim=function(){
		return this.replace(/^\s+/, "").replace(/\s+$/, "");
	};
	
	var nullFunc=function(){}, nullAry=[];
	
	var mytimelog=function(str){
		console.log("-----");
		console.log((new Date()).toISOString().replace(/T|\..*$/g, " ")+"(UTC) :");
		console.log(str);
	};
	
	var getPaVal=function(partstr, attr, isTrim){
		eval("var r="+( (/\|\s*?attributes\s*?\=[ \t]*(.*?)\n/g).toString().replace("attributes", attr) ) );
		var m=partstr.match(r);
		if(!m) return "";
		
		return (isTrim?m[0].replace(r, "$1").trim():m[0].replace(r, "$1"));
	};

	var genhash=function SHA1(msg) {
	 
		function rotate_left(n,s) {
			var t4 = ( n<<s ) | (n>>>(32-s));
			return t4;
		};
	 
		function lsb_hex(val) {
			var str="";
			var i;
			var vh;
			var vl;
	 
			for( i=0; i<=6; i+=2 ) {
				vh = (val>>>(i*4+4))&0x0f;
				vl = (val>>>(i*4))&0x0f;
				str += vh.toString(16) + vl.toString(16);
			}
			return str;
		};
	 
		function cvt_hex(val) {
			var str="";
			var i;
			var v;
	 
			for( i=7; i>=0; i-- ) {
				v = (val>>>(i*4))&0x0f;
				str += v.toString(16);
			}
			return str;
		};
	 
	 
		function Utf8Encode(string) {
			string = string.replace(/\r\n/g,"\n");
			var utftext = "";
	 
			for (var n = 0; n < string.length; n++) {
	 
				var c = string.charCodeAt(n);
	 
				if (c < 128) {
					utftext += String.fromCharCode(c);
				}
				else if((c > 127) && (c < 2048)) {
					utftext += String.fromCharCode((c >> 6) | 192);
					utftext += String.fromCharCode((c & 63) | 128);
				}
				else {
					utftext += String.fromCharCode((c >> 12) | 224);
					utftext += String.fromCharCode(((c >> 6) & 63) | 128);
					utftext += String.fromCharCode((c & 63) | 128);
				}
	 
			}
	 
			return utftext;
		};
	 
		var blockstart;
		var i, j;
		var W = new Array(80);
		var H0 = 0x67452301;
		var H1 = 0xEFCDAB89;
		var H2 = 0x98BADCFE;
		var H3 = 0x10325476;
		var H4 = 0xC3D2E1F0;
		var A, B, C, D, E;
		var temp;
	 
		msg = Utf8Encode(msg);
	 
		var msg_len = msg.length;
	 
		var word_array = new Array();
		for( i=0; i<msg_len-3; i+=4 ) {
			j = msg.charCodeAt(i)<<24 | msg.charCodeAt(i+1)<<16 |
			msg.charCodeAt(i+2)<<8 | msg.charCodeAt(i+3);
			word_array.push( j );
		}
	 
		switch( msg_len % 4 ) {
			case 0:
				i = 0x080000000;
			break;
			case 1:
				i = msg.charCodeAt(msg_len-1)<<24 | 0x0800000;
			break;
	 
			case 2:
				i = msg.charCodeAt(msg_len-2)<<24 | msg.charCodeAt(msg_len-1)<<16 | 0x08000;
			break;
	 
			case 3:
				i = msg.charCodeAt(msg_len-3)<<24 | msg.charCodeAt(msg_len-2)<<16 | msg.charCodeAt(msg_len-1)<<8	| 0x80;
			break;
		}
	 
		word_array.push( i );
	 
		while( (word_array.length % 16) != 14 ) word_array.push( 0 );
	 
		word_array.push( msg_len>>>29 );
		word_array.push( (msg_len<<3)&0x0ffffffff );
	 
	 
		for ( blockstart=0; blockstart<word_array.length; blockstart+=16 ) {
	 
			for( i=0; i<16; i++ ) W[i] = word_array[blockstart+i];
			for( i=16; i<=79; i++ ) W[i] = rotate_left(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
	 
			A = H0;
			B = H1;
			C = H2;
			D = H3;
			E = H4;
	 
			for( i= 0; i<=19; i++ ) {
				temp = (rotate_left(A,5) + ((B&C) | (~B&D)) + E + W[i] + 0x5A827999) & 0x0ffffffff;
				E = D;
				D = C;
				C = rotate_left(B,30);
				B = A;
				A = temp;
			}
	 
			for( i=20; i<=39; i++ ) {
				temp = (rotate_left(A,5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff;
				E = D;
				D = C;
				C = rotate_left(B,30);
				B = A;
				A = temp;
			}
	 
			for( i=40; i<=59; i++ ) {
				temp = (rotate_left(A,5) + ((B&C) | (B&D) | (C&D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff;
				E = D;
				D = C;
				C = rotate_left(B,30);
				B = A;
				A = temp;
			}
	 
			for( i=60; i<=79; i++ ) {
				temp = (rotate_left(A,5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff;
				E = D;
				D = C;
				C = rotate_left(B,30);
				B = A;
				A = temp;
			}
	 
			H0 = (H0 + A) & 0x0ffffffff;
			H1 = (H1 + B) & 0x0ffffffff;
			H2 = (H2 + C) & 0x0ffffffff;
			H3 = (H3 + D) & 0x0ffffffff;
			H4 = (H4 + E) & 0x0ffffffff;
	 
		}
	 
		var temp = cvt_hex(H0) + cvt_hex(H1) + cvt_hex(H2) + cvt_hex(H3) + cvt_hex(H4);
	 
		return temp.toLowerCase();
	 
	};

	var getRevs=function({
			titles,
			rvstart,
			rvend,
			rvprop='timestamp|user|comment',
			tarAry=[],
			errcount=maxErrTime*1,
			doneFunc=nullFunc,
			failFunc=nullFunc,
			nloop=0,
	}){
		
		if(nloop==0) mytimelog("Start listing history of "+titles);
		
		$.post(
			'/w/api.php',
			{
				action : 'query',
				prop   : 'revisions',
				format : 'json',
				titles,
				rvprop,
				rvlimit: "max",
				rvstart: rvstart.toISOString(),
				rvend  : rvend.toISOString(),
			},
			null,
			'json'
		).fail(
			function(){
				if( errcount >0 ){
					mytimelog(errcount);
					
					setTimeout( function(){
						getRevs({
							titles,
							rvstart,
							rvend,
							rvprop,
							tarAry,
							errcount : errcount-1,
							doneFunc,
							failFunc,
							nloop,
						});
					}, 1000*10);
				}else{
					if("function"==typeof failFunc) failFunc();
				}
			}		
		).done(
			function( data ) {
				var lastts, pageid, i;
				for ( pageid in data.query.pages ) {
					lastts = (data.query.pages[pageid].revisions || nullAry).pop();
					
					i=0;
					while(i<(data.query.pages[pageid].revisions || nullAry).length){
						tarAry.push(data.query.pages[pageid].revisions[i++]);
					}
					
					
					break;
				}
				
				if( i==0 ){
					mytimelog(tarAry);
					mytimelog( "Finished listing history of "+titles );
					
					if(!!lastts) tarAry.push(lastts);
					if("function"==typeof doneFunc) doneFunc({tarAry});
				}else{
					mytimelog(  "listed part "+ (++nloop) );
					
					getRevs({
						titles,
						rvstart : new Date(lastts.timestamp),
						rvend,
						rvprop,
						tarAry,
						errcount,
						doneFunc,
						failFunc,
						nloop,
					});
				}
			}
		);
	};

	var editPage=function({
		titles,
		errcount=maxErrTime*1,
		editFunc,
		doneFunc,
		failFunc,
		beforeRetryFunc,
	}){
		
		var retryFunc=function(){
			
			if(errcount>0){
				setTimeout(
					function(){
						if("function"==typeof beforeRetryFunc) if(false===beforeRetryFunc()) return;
						
						editPage({
							titles,
							errcount:errcount-1,
							editFunc,
							doneFunc,
							failFunc,
						});
					}
					, 1000*15
				);
			}else{
				if("function"==typeof failFunc) failFunc();
			}
		};
		
		
		mytimelog("Start editing "+titles);
		mytimelog("Getting content of "+titles);
		$.post(
			'/w/api.php',
			{
				action : 'query',
				prop   : 'revisions',
				format : 'json',
				titles,
				rvprop : 'content|timestamp',
				rvslots: 'main',
			},
			null,
			'json',
		).fail(
			retryFunc
		).done(
			function(data){
				var contentstr = '',
				timestamp = '',
				pageid = '';
				
				for ( pageid in data.query.pages ) {
					if(pageid<0){
						timestamp = Math.floor(Date.now()/1000);
					}else{
						timestamp  = data.query.pages[pageid].revisions[0].timestamp;
						contentstr = data.query.pages[pageid].revisions[0].slots.main['*'];
					}
					break;
				}
				
				
				mytimelog("Got content of "+titles+", changing content");
				var content={
					value    : ""+contentstr,
					toString : function(){ return this.value },
					summary  : "",
				};
				
				if(editFunc==nullFunc || "function"!=typeof editFunc){
					if("function"==typeof doneFunc) doneFunc({content, data:nullFunc()});
				}else{
					
					if( editFunc({content})===false ) return false;
					
					if( contentstr.trim()==(""+content).trim() ){
						mytimelog("No change. Finished editing "+titles);
						if("function"==typeof doneFunc) doneFunc({content, data:nullFunc()});
					}else{
						mytimelog("Saving changes to "+titles);
						
						$.post(
							'/w/api.php',
							{
								action  : 'query',
								prop    : 'info',
								titles  : titles,
								meta    : 'tokens',
								format  : 'json',
							},
							null,
							'json',
						).fail(
							retryFunc
						).done(
							function(data){
								var startts = (pageid<0)?Math.floor(Date.now()/1000):data.query.pages[pageid].starttimestamp;
								var edittoken = data.query.tokens.csrftoken;
								content.lastrevid=data.query.pages[pageid].lastrevid;
								content.isCreate=(pageid<0);
								
								$.post (
									'/w/api.php',
									{
										action  : 'edit',
										title   : titles,
										text    : ""+content,
										token   : edittoken,
										summary : content.summary,
										format  : 'json',
										basetimestamp  : timestamp,
										starttimestamp : startts,
									},
									null,
									'json',
								).fail(
									retryFunc
								).done(
									function( data ){
										if(!!data) if(!!data.edit) if( "success"== (""+data.edit.result).toLowerCase() ){
											mytimelog("Saved changes to "+titles);
											doneFunc({content, data});
											return;
										}
										
										retryFunc();
										
									}
								);
							}
						);
					}
				}
				
			}
		);
	}
	
	var countvote=function(){
		$("s, strike, del, .zhwpVotevoid").remove();
		
		
		var $HTMLobjs=$("*"),
		DYKEntrys=[],
		votesupport=0,
		voteoppose=0,
		hash=null,
		timestamp=null,
		article=null,
		alink=null;
		
		var i=$HTMLobjs.length, $curobj;
		while(i-->0){
			$curobj=$HTMLobjs.eq(i);
			
			if($curobj.hasClass("zhwpVoteSupport") ){
				votesupport++;
			}else if($curobj.hasClass("zhwpVoteOppose") ){
				voteoppose++;
			}else if($curobj.hasClass("zhwpDYKwq") ){
				voteoppose=1e10;
			}else if($curobj.hasClass("dykarticle") ){
				article=$curobj.text().trim().replace(/ /g, '_');
				
				if($curobj.find('a').length!=1 || $curobj.find('a').eq(0).hasClass("new") ){
					alink=article;
				}else{
					alink=(""+$curobj.find('a').eq(0).attr("title")).trim().replace(/ /g, '_');
				}
			}else if($curobj.hasClass("dykentry_hash") ){
				hash=$curobj.text().trim();
			}else if($curobj.hasClass("dyktimestamp") ){
				timestamp=new Date($curobj.get(0).title.trim());
			}else if($curobj.hasClass("dykentry") ){
				if( (""+hash).trim().length>30 ){
					DYKEntrys.push({
						  "hash"        : ""+hash
						, "timestamp"   : timestamp
						, "article"     : article
						, "alink"       : alink
						, "votesupport" : votesupport*1
						, "voteoppose"  : voteoppose*1
					});
				}
					
				votesupport=voteoppose=0;
				hash=timestamp=article=alink=null;
				if($curobj.get(0)==$(".dykentry").get(0)) break;
			}
		}
		//$curobj=($HTMLobjs=void(0));
		
		(function checkEntry(){
			if(DYKEntrys.length<=0){
				setTimeout(getCurTypes, 1000);
				return;
			}
				
			editPage({
				titles   : pgnames.WP_DYKC,
				errcount : maxErrTime*1,
				editFunc : function({content}){
					var newcontent=""+content,
					newsummary="",
					curEntry,
					i,
					newresult,
					oldresult,
					isEdit=false;
					
					var parts=newcontent.split( /\{\{\s*DYKEntry/i );
					
					L1:while( curEntry=DYKEntrys.pop() ){
						mytimelog(curEntry);
						if( !curEntry.timestamp ) continue L1;
						if( isNaN(curEntry.timestamp.getTime()) ) continue L1;
						
						newresult=oldresult='';
						isEdit=false;
						i=parts.length-1;
						L2:while(i-->0){
							if ( parts[i].indexOf( curEntry.hash ) >= 0 ) {
								if(curEntry.article!=curEntry.alink && curEntry.alink!=""){
									parts[i] = parts[i]
									.replace1st( /(\|\s*article\s*\=).*?\n/i , '$1 ' + curEntry.alink + '\n')
									.replace1st( /(\|\s*hash\s*\=).*?\n/i    , '$1 ' + "" + '\n')
									.replace1st( /(\|\s*result\s*\=).*?\n/i  , '$1 ' + "" + '\n')
									;
									
									newsummary="change article name: "+curEntry.article+"/"+"*"+curEntry.alink+"*"+"/";
									break L1;
								}else{
									if( parts[i].match( /\|\s*?result\s*?\=/i )==null ) parts[i]="\n | result = \n"+parts[i].replace1st( /^\n*/ , "");
									
									oldresult=getPaVal(parts[i], "result").split("\|");
									//oldresult=parts[i].replace1st(/(?:.|\n)*\|\s*result\s*\= *(.*?)\n(?:.|\n)*/i, "$1").split("\|");
									
									if( oldresult[0].trim()==botpassflag || !oldresult[0].trim()  ){
										if(
											oldresult[0]==botpassflag
											&& (curEntry.voteoppose>=3 || curEntry.votesupport-curEntry.voteoppose<4)
										){
											newsummary="clear /"+"*"+curEntry.article+"*"+"/";
											newresult="";
											parts[i] = parts[i].replace(/\{\{\s*DYKvote[HF]\s*(?:\|[^\}]*?)?\}\}\n*/g, "");
											
											isEdit=true;
										}else if(
											(
												(
													Date.now()-curEntry.timestamp.getTime()>(3*24)*60*60*1000
													&& Date.now()-curEntry.timestamp.getTime()<(4*24-3)*60*60*1000
												)
												||
												(
													Date.now()-curEntry.timestamp.getTime()>(6*24)*60*60*1000
													&& Date.now()-curEntry.timestamp.getTime()<(7*24-3)*60*60*1000
												)
											)
											&& curEntry.votesupport-curEntry.voteoppose>=4
											&& curEntry.voteoppose<3 && oldresult[0]==""
										){
											newsummary=botpassflag+"\|"+genhash(botpassflag+curEntry.hash+botpassflag);
											newresult=newsummary+"\|\{\{subst:#time:U\}\}";
											newsummary+=" /"+"*"+curEntry.article+"*"+"/";
											
											isEdit=true;
										}
										
										if(isEdit){
											parts[i] = parts[i].replace1st( /(\|\s*result\s*\=).*?\n/i , '$1 ' + newresult + '\n');
											break L1;
										}
									}
								}
								
								break L2;
							}
						}
						
						
					}

					
					newcontent=parts.join("\{\{ DYKEntry");
					content.value=newcontent;
					content.summary="auto vote counting: "+newsummary;
				},
				doneFunc : checkEntry,
			});
		})();
		
	}
	
	var dyktypes=[], getCurTypes=function(){
		editPage({
			titles   : pgnames.T_DYK,
			errcount : maxErrTime*1,
			editFunc : function({content}){
				var i=6-1;
				while(i-->0){
					dyktypes = dyktypes.concat( getPaVal( ""+content, "t"+i, true).split("、") );
				}
				
				setTimeout(getDYKsum, 100);
				return false;
			}
		});
	};
	
	var DYKrevs=[], getDYKsum=function(){
		getRevs({
			titles  : pgnames.T_DYK,
			rvstart : new Date(),
			rvend   : new Date(Date.now()-12*60*60*1000),
			rvprop  : 'timestamp|comment',
			tarAry  : DYKrevs,
			errcount: maxErrTime*1,
			doneFunc: function({tarAry}){
				setTimeout(function(){
					updatehash(false);
				}, 100);
			}
		});
	};
	
	var needchkinv=[];
	var updatehash=function(noPass){
		mytimelog("Start hashing");
		
		editPage({
			titles   : pgnames.WP_DYKC,
			errcount : maxErrTime*1,
			editFunc : function({content}){
				var article,
				question,
				imgfilename,
				timestamp,
				hash,
				typestr,
				result,
				dateSect,
				newcontent=(""+content).replace(/\n\={3}\s*?\d*?月\d*?日\s*?\={3}/ig, "").replace(/\n\={4}\s*?\={4}/ig, ""),
				DYKdate=new Date(0),
				parts = newcontent.split( /\{\{\s*DYKEntry/i );
				parts[parts.length-1]=parts[parts.length-1].replace(/\{\{\s*safesubst\:DYKEntry\/auto(?:.|\n)*$/i, "");
				
				var header=parts.shift().trim(),
				footer="==== ====\n\
\{\{safesubst:DYKEntry\/auto\n\
 \| 編者請注意 = 此模板為新提名插入點,請勿移除或將之移動到其它位置,以免出現錯誤,感謝配合。\n\
 \| 编者请注意 = 此模板为新提名插入点,请勿移除或将之移动到其它位置,以免出现错误,感谢配合。\n\
 \| 提交方式 = 請填妥以下參數之後,並提交編輯。/请填妥以下参数之后,并提交编辑。如果需提报多个条目请分多次提交,勿复制本表单。\n\
 \| article = \n\
 \| question = \n\
 \| image = \n\
 \| type = \n\
 \| author = \n\
 \| 理由 (不必簽名) = \n\
 \| nominator = \{\{subst:REVISIONUSER\}\}\n\
 \| timestamp = \{\{subst:#time:U\}\}\n\
\}\}\{\{safesubst:void\|請注意,請勿更動此行或者在此行後面添加內容。而附加資訊、說明文字或提名人票請添加於「理由」一行。\n\
-------------------请注意,请勿更动此行或者在此行后面添加内容。而附加资讯、说明文字或提名人票请添加于“理由”一行。 \}\}\n\
\n\
==== ====\n\
\{\{進行中的內容評選\}\}";
				
				var lastUpdateTime=new Date(0), lasth=Math.MAX_VALUE;
				var i=DYKrevs.length;
				while(i-->0){
					if( (""+DYKrevs[i].comment).indexOf("updateDYK")>=0){
						lasth=( (new Date(DYKrevs[i].timestamp)).getTime()-lastUpdateTime.getTime() ) / (1000*60*60) ;
						lastUpdateTime=new Date(DYKrevs[i].timestamp);
					}
				}
				
				var h=6, numOfPass=(newcontent.match(/[\+\^]\|/g) || nullAry).length, doPass=false;
				if(!noPass){
					if(numOfPass>=5 ) h=4;
					if(numOfPass>=10) h=3;
					if(numOfPass>=15 && lasth>2.5 ) h=2;
					if(numOfPass>=20) h=2;
					if(fixh>0) h=fixh;
					if(numOfPass>0 && Date.now()-lastUpdateTime.getTime()>=(h*60-10)*60*1000 ) doPass=true;
				}
				
				numOfPass=-1;
				var i=parts.length, j, k, r, numSameType=0, minSameType=Number.MAX_VALUE, artnames=[];
				while(i-->0){
					parts[i]="\n "+parts[i].trim();
					dateSect="";
					numSameType=0;
					
					j=DYKEntryAttrs.length;
					while(j-->0){
						eval("r="+( (/(\|\s*attributes\s*\=).*\n/).toString().replace("attributes", DYKEntryAttrs[j] ) ) );
						
						if( parts[i].match(r)==null ){
							parts[i] = '\n \| '+DYKEntryAttrs[j]+' = ' + parts[i];
						};
					};
					

					article     = artnames[i]=getPaVal(parts[i], "article", true);
					question    = "";
					imgfilename = "";
					timestamp   = getPaVal(parts[i], "timestamp", true);
					hash        = "";
					result      = getPaVal(parts[i], "result", true).split("\|");
					
					if( !result[2] || isNaN(result[2]) ) result[2]=0;
					
					if(!timestamp || Date.now()/1000-timestamp<4*60*60) timestamp=NaN;
					if(isNaN(timestamp)){
						parts[i]="==== ====\n\{\{ DYKEntry"+parts[i];
						//refillTimestamp();
						//return false;
					}else{
						article     = artnames[i]=getPaVal(parts[i], "article", true);
						question    = getPaVal(parts[i], "question", true).replace(/\?$/,"?");
						imgfilename = getPaVal(parts[i], "image", true);
						hash        = getPaVal(parts[i], "hash", true);
						
						DYKdate=new Date(timestamp*1000);
						
						if( (typestr=getPaVal(parts[i], "type", true))=="" ){
							parts[i] = parts[i].replace( /(\|\s*type\s*\=).*?\n/, '$1 ' + '\{\{subst:#if:\{\{subst:WikidataEntity|'+article+'\}\}|\{\{subst:#invoke:WikidataIB |getValue |P31 |fwd=ALL |osd=no|linked=no |noicon=yes |lang=en |qid=\{\{subst:WikidataEntity|'+article+'}}|sep="、"\}\}\}\}' + '\n');
						}
						
						parts[i] = parts[i].replace( /(\|\s*question\s*\=).*?\n/, '$1 ' + question + '\n');
						newhash=genhash([question,article,imgfilename,timestamp].join(","));
						
						if(newhash!=hash && result[0]!="-"){
							needchkinv.push(article);
							
							parts[i] = parts[i].replace( /(\|\s*hash\s*\=).*?\n/, '$1 ' + newhash + '\n');
							if(result[0]!="@") {
								parts[i] = parts[i].replace( /(\|\s*result\s*\=).*?\n/, '$1 \n').replace(/\{\{\s*DYKvote[HF]\s*(?:\|[^\}]*?)?\}\}\n*/g, "");
								result=["@","",""];
							}
						}
						
						j=i;
						while(++j<artnames.length){
							if(artnames[i]==artnames[j]){
								if( (result[0].match(/^[\@\-\:]/) || nullAry).length==0 ){
									parts[i] = parts[i].replace( /(\|\s*result\s*\=).*?\n/, '$1 \:\n').replace(/\{\{\s*DYKvote[HF]\s*(?:\|[^\}]*?)?\}\}\n*/g, "");
								}
								
								result=[":","",""];
								
								if( (getPaVal(parts[j], "result", true).match(/^[\@\-\:]/) || nullAry).length==0 ){
									parts[j] = parts[j].replace( /(\|\s*result\s*\=).*?\n/, '$1 \:\n').replace(/\{\{\s*DYKvote[HF]\s*(?:\|[^\}]*?)?\}\}\n*/g, "");
								}
							}
						}

						
						if( !doPass && result[0]=="-" && result[1].trim()==genhash(result[0].trim()+hash+result[0].trim()) && result[2]>0
							&&
							(
								(
									Date.now()/1000-result[2]>6*60*60
									&& result[2]-timestamp>=7*24*60*60
								)
								||
								(
									Date.now()/1000-result[2]>24*60*60
									&& result[2]-timestamp<7*24*60*60
								)
								||
								fixh%100000==1
							)
						){
							failDYKs.push( parts.splice(i,1)[0] );
							continue;
						}else{
							if(
								doPass
								&& result[2]>0
								&& result[1].trim()==genhash(result[0].trim()+hash+result[0].trim())
								&& (parts[i].match( /\{\{\s*DYKvoteF/ ) || nullAry).length>0
								&& (
									result[0]=="+"
									||
									(
										result[0]=="^"
										&&
										(
											(
												result[2]-timestamp>3*24*60*60
												&& result[2]-timestamp<(4*24-2)*60*60
											)
											||
											(
												result[2]-timestamp>6*24*60*60
												&& result[2]-timestamp<(7*24-2)*60*60
											)
										)
									)
								)
							){
								typestr=typestr.split("、");
								j=typestr.length;
								
								while(j-->0){
									k=dyktypes.length;
									while(k-->0){
										if(typestr[j].trim().toLowerCase()==dyktypes[k].trim().toLowerCase()){
											numSameType++;
										}
									}
								}
								
								if(numSameType<=minSameType){
									numOfPass=i;
									minSameType=numSameType;
								}
							}
							
							
							if(
								null==parts[i].match( /\{\{\s*DYKvoteF/ )
								&&
								(
									(Date.now()-DYKdate.getTime()>=7*24*60*60*1000 )
									||
									(result[0].trim()==botpassflag && Date.now()-DYKdate.getTime()>=4*24*60*60*1000 && result[2]-timestamp<4*24*60*60 && result[2]-timestamp>0 )
								)
								
							){
								parts[i]="\{\{subst\:DYKEntry/close\n "+parts[i].replace( /\s*$/ , "\n\{\{DYKvoteF\}\}");
							}else{
								parts[i]="\{\{ DYKEntry"+parts[i];
							}
							
							parts[i]="==== ====\n"+parts[i];
						}
						
					}
				}
				
				if(doPass && numOfPass>=0){
					parts[numOfPass]=parts[numOfPass].replace(/^(?:.|\n)*\{\{\s*?DYKEntry\n/, "");
					passDYKs.push(parts.splice(numOfPass,1)[0]);
				}
				
				DYKdate=null;
				for(i=0; i<parts.length; i++){
					timestamp = getPaVal(parts[i], "timestamp", true);
					
					if(!timestamp) timestamp=NaN;
					if(isNaN(timestamp)){
						
						continue;
					}else{
						if(!DYKdate){
							DYKdate=new Date(i=0);
						};
						
						if( DYKdate.getUTCDate() != (new Date(timestamp*1000)).getUTCDate() || DYKdate.getUTCMonth() != (new Date(timestamp*1000)).getUTCMonth() || DYKdate.getUTCFullYear() != (new Date(timestamp*1000)).getUTCFullYear()){
							DYKdate=new Date(timestamp*1000);
							parts[i] = "=== "+(DYKdate.getUTCMonth()*1+1)+"月"+DYKdate.getUTCDate()+"日 ===\n"+parts[i];
						}
						DYKdate=new Date(timestamp*1000);
					}
				}
				
				
				parts.push(footer);
				parts.unshift(header);
				newcontent=parts.join("\n\n");
				
				content.value = newcontent;
				content.summary = "auto update"
				
			},
			beforeRetryFunc : function(){
				passDYKs=[];
				failDYKs=[];
			},
			doneFunc : function({
				content,
				data=nullAry
			}){
				mytimelog("Finished hashing");
				
				if(passDYKs.length>0){
					passDYKarc({content, data});
				}else if(failDYKs.length>0){
					failDYKarc({content, data});
				}else{
					setTimeout(refillinv, 1000);
				}
			},
		});
	}
	
	var failDYKarc=function({content, data}){
		mytimelog("Start archive fail DYKs");
		var lastrevid=content.lastrevid;
		var i=failDYKs.length;
		
		(function savetalk(i){
			if( i>=0 ){
				var curEntry=failDYKs[i];
				
				editPage({
					titles   : "Talk:"+getPaVal(""+curEntry, "article", true),
					errcount : maxErrTime*1,
					editFunc : function({content}){
						var newcontent=""+content;
						newcontent=newcontent.replace(/\{\{\s*?DYK(?:C|N|[ _]?invite)\s*?\}\}\n?/ig, "");
						newcontent+="\n\n\n\{\{DYKEntry/archive\n \| closeframe = 1\n \| revid = "+lastrevid+"\n "+curEntry.trim().replace( /\s*\{\{\s*?DYKvoteH/ , "\{\{subst\:void");
						
						content.value=newcontent;
						content.summary="auto archive";
					},
					doneFunc : function(){
						savetalk(i-1);
					},
				});
			}else{
				mytimelog("Finished archive fail DYKs");
				setTimeout(refillinv, 1000);
			}
			
		})(failDYKs.length-1);

	}
	
	var passDYKarc=function({content, data}){
		mytimelog("Start pass");
		
		var lastrevid=content.lastrevid,
		passedEntry=passDYKs[0],
		nowdate=new Date();
		
		var article = getPaVal(passedEntry, "article", true),
		author      = getPaVal(passedEntry, "author", true) ,
		question    = getPaVal(passedEntry, "question", true),
		typestr     = getPaVal(passedEntry, "type", true),
		imgfilename = getPaVal(passedEntry, "image", true);
		
		setTimeout(function(){
			upTem({content, data});
		}, 100);
		
		var upTem=function({content, data}){
			editPage({
				titles   : pgnames.T_DYK,
				errcount : maxErrTime*5,
				editFunc : function({content}){
					var newcontent=""+content;
					
					var q=[], p=[], t=[], i=6-1;
					
					while(i-->0){
						q[i]=getPaVal(newcontent, " "+i, true);
						p[i]=getPaVal(newcontent, "p"+i, true);
						t[i]=getPaVal(newcontent, "t"+i, true);
					}
					q.unshift(question);
					p.unshift(imgfilename);
					t.unshift(typestr);
					
					newcontent=newcontent
					.replace(/(\{\{\s*?Dyk\/auto)(?:.|\n)*(\<\!\-\-\s*?BOT\: END\s*?\-\-\>)/, "$1\n\}\}$2")
					.replace(/(\{\{\s*?Dyk\/auto)/, "$1\n \| allimages \= \{\{\{allimages\|no\}\}\}")
					;
						
					i=q.length;
					while(i-->0){
						newcontent=newcontent
						.replace(/(\{\{\s*?Dyk\/auto)/, "$1\n \| t"+i+" \= "+t[i])
						.replace(/(\{\{\s*?Dyk\/auto)/, "$1\n \| p"+i+" \= "+p[i])
						.replace(/(\{\{\s*?Dyk\/auto)/, "$1\n \|  "+i+" \= "+q[i])
						;
					}
					
					
					content.value=newcontent;
					content.summary="auto updateDYK";
				},
				doneFunc : dayarc,
			});
		}
		
		var dayarc=function({content, data}){
			editPage({
				titles   : "Wikipedia:新条目推荐/供稿/"+nowdate.getUTCFullYear()+"年"+(nowdate.getUTCMonth()*1+1)+"月"+nowdate.getUTCDate()+"日",
				errcount : maxErrTime*5,
				editFunc : function({content}){
					content.summary="auto archive";
					content.value="* "+question+"\n"+content;
				},
				doneFunc : montharc,
			});
		}
		
		var montharc=function({content, data}){
			editPage({
				titles   : "Wikipedia:新条目推荐/存档/"+nowdate.getUTCFullYear()+"年"+(nowdate.getUTCMonth()*1+1)+"月",
				errcount : maxErrTime*5,
				editFunc : function({content}){
					content.summary="auto archive";
					content.value="* "+question+"\n"+content;
				},
				doneFunc : function({content, data}){
					if(content.isCreate){
						mainarc({content, data});
					}else{
						proEnc({content, data});
					}
				},
			});
		}
		
		var mainarc=function({content, data}){
			editPage({
				titles   : "Wikipedia:新条目推荐/"+nowdate.getUTCFullYear()+"年"+(nowdate.getUTCMonth()*1+1)+"月",
				errcount : maxErrTime*5,
				editFunc : function({content}){
					content.summary="";
					content.value="\{\{DYKMonthlyArchive\}\}";
				},
				doneFunc : proEnc,
			});
		}
		
		var proEnc=function({content, data}){
			if(author=="" || !!author.match(/^(?:游魂|UjuiUjuMandan|Tokisaki[_ ]Kurumi)$/i ) || !!author.match(/^\d+.\d+.\d+.\d+$/) || !!author.match(/^([0-9A-Za-z]+:){8,}[0-9A-Za-z]+$/) ){
				talkarc({content, data});
				return;
			}
			
			editPage({
				titles   : "User:"+author,
				errcount : maxErrTime*5,
				editFunc : function({content}){
					var proNum=1, newcontent=""+content;
					
					if( !newcontent.match( /\{\{\s*(?:Blocked[ _]user|BU|Indefblockeduser|indef|永久?封禁?用[户戶戸]|sockpuppeteer|Blocked[ _]sockpuppet|sockpuppetProven|sp[mp]|User[ _](?:noAwards|noServiceAwards|nobanstar|BSF))\s*(?:\}\}|\|)/i ) ){
						if( !newcontent.match(/\{\{\s*?[Pp]roduceEncouragement\s*?\|\s*?count\s*?\=\s*?\d+\s*?\}\}/) ){
							newcontent="\{\{produceEncouragement\|count\=0\}\}\n"+newcontent;
						}
						proNum=newcontent.replace(/(?:.|\n)*\{\{\s*?[Pp]roduceEncouragement\s*?\|\s*?count\s*?\=\s*?(\d+)\s*?\}\}(?:.|\n)*/ , "$1")*1+1;
						newcontent=newcontent.replace(/({\{\s*?[Pp]roduceEncouragement\s*?\|\s*?count\s*?\=\s*?)\d+/ , "$1"+proNum);
						
						if( !!newcontent.match(/\{\{\s*?[Uu]ser[_ ]DYK\s*?\|\s*?\d+\s*?\}\}/ ) ){
							newcontent=newcontent.replace(/({\{\s*?[Uu]ser[_ ]DYK\s*?\|\s*?)\d+/ , "$1"+proNum);
						}
						
						content.summary='auto \{\{produceEncouragement\|count='+proNum+'\}\}';
						content.value=newcontent;
					}
				},
				doneFunc : talkarc,
			});
		}
		
		
		var talkarc=function({content, data}){
			editPage({
				titles   : "Talk:"+getPaVal(""+passedEntry, "article", true),
				errcount : maxErrTime*1,
				editFunc : function({content}){
					var newcontent=""+content;
					newcontent="\{\{DYKtalk\|date\=\{\{subst\:#time:Y-m-d\}\}\}\}\n"+newcontent.replace(/\{\{\s*?DYK(?:C|N|[ _]?invite)\s*?\}\}\n?/ig, "");
					newcontent+="\n\n\n\{\{DYKEntry/archive\n \| closeframe = 1\n \| revid = "+lastrevid+"\n "+passedEntry.trim().replace( /\s*\{\{\s*?DYKvoteH/ , "\{\{subst\:void");
					
					content.value=newcontent;
					content.summary="auto archive";
				},
				doneFunc : function(){
					mytimelog("Finished pass")
					setTimeout(refillinv, 1000);
				},
			});
		}
	}
	
	var refillinv=function(){
		mytimelog("Start check invite");
		
		(function chkeachinv(){
		
			if( needchkinv.length>0 ){
				editPage({
					titles   : "Talk:"+needchkinv.pop(),
					errcount : maxErrTime*1,
					editFunc : function({content}){
						var newcontent=""+content;
						if( newcontent.match(/\{\{\s*?DYK(?:C|N|[ _]?invite)/ig)!=null ){
							setTimeout(chkeachinv, 1000);
							return false;
						}
						
						newcontent="\{\{DYK_Invite\}\}\n"+newcontent;
						
						content.value=newcontent;
						content.summary="auto invite";
					},
					doneFunc : function(){
						setTimeout(chkeachinv, 1000);
					},
				});
			}else{
				mytimelog("Finished check invite");
			}
			
		})();
		
	}
	
} );