用户:Antigng-bot/translation

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <process.h>
#include <windows.h>
#include "network.h"
#include "convert.h"
#include "auth.h"
#include "struct.h"
struct problemlist
{
	char *title;
	char *revid;
	char *comment;
	char *talktitle;
	char *ftitle;
	char *frev;
	char *lang;
	struct problemlist *next;
} ;
struct editargv
{
    int count;
	char *title;
	char *newtext;
};
struct neditargv
{
    int count;
	char *title;
	HTTP newtext;
};
CRITICAL_SECTION cs;
CRITICAL_SECTION tcs;
const char *nsprefix[]={"","Talk:","User:","User_talk:","Wikipedia:","Wikipedia_talk:","File:","File_talk:","Mediawiki:","Mediawiki_talk:","Template:","Template_talk:","Help:","Help_talk:","Category:","Category_talk:"};
int threadnumber=0;
struct problemlist *query();
struct problemlist *localquery();
int checkcomment(char *comment,char *lang,char *frev,char *ftitle);
int converttalk(char *title,char *talk);
void show(struct problemlist *head);
int proceed(struct problemlist* p,struct problemlist **new,int depth);
int proceedchild(char *title);
int findtemp(char *title);
int smartedit(struct neditargv *p);
int update(char *title);
int showerr=0;
int safemod=1;
int main()
{
	struct problemlist *head;
	if(login("Antigng-bot","")) return 1;
	_beginthread(tokenmanage,0,0);	
	InitializeCriticalSection(&cs);
	InitializeCriticalSection(&tcs);
	head=localquery();
	show(head);
    while(head) proceed(head,&head,100);
	DeleteCriticalSection(&cs);
	DeleteCriticalSection(&tcs);
	return 0;
}

struct problemlist *query()
{
    HTTP h;
	struct problemlist *pre,*head,*temp;
	int flag=0;
	int status=0;
	char url[3000]={0};
	char buffer[102400]={0};
	char offset[200]={0};
	char title[2000]={0};
	char talktitle[2000]={0};
	char revid[1000]={0};
	char timestamp[1000]={0};
	char comment[10000]={0};
	char lang[10]={0};
	char frev[100]={0};
	char ftitle[2000]={0};
	char *ctn[]={"arvcontinue"};
	char *ctnres[1];
	char *tta[]={"title"};
	char *ttares[1];
	char *rev[]={"revid","timestamp","comment"};
	char *revres[3];
	int bufferpos=0;
	int next=0;
	int vl=0;
	struct hashlist *hsh;
	ctnres[0]=offset;
	ttares[0]=title;
	revres[0]=revid;
	revres[1]=timestamp;
	revres[2]=comment;
	head=0;
    hsh=hashini();
	do
	{
	h=hopen();
	
	strcpy(url,"https://zh.wikipedia.org/w/api.php?action=query&format=xml&list=allrevisions&arvprop=ids|timestamp|comment&arvdir=older&arvlimit=5000");
	if(next)
	{
		strcat(url,"&arvcontinue=");
		strcat(url,offset);
	}
	if(get(url,1,h))
	{
	   hclose(h);
	   return NULL;
	 }
	if(skipresponseheader(h))
	{
		hclose(h);
		return NULL;
	}
	next=0;
	 while(!heof(h))
	 {
		vl=xmlparsetag(h,buffer);
		if(!next&&!strcmp(buffer,"continue"))
		{
			vl=xmlparsearg(h,1,ctn,ctnres);
			next=1;
			printf("continue=%s\n",offset);
			continue;
		}
		if(vl==0&&!strcmp(buffer,"page"))
		{
			vl=xmlparsearg(h,1,tta,ttares);
			status=1;
			continue;
		}
		if(!strcmp(buffer,"rev"))
		{
			vl=xmlparsearg(h,3,rev,revres);
			status=0;
			if(!hashquery(hsh,title)&&checkcomment(comment,lang,frev,ftitle))
			{
				   status=0;
				   hashadd(hsh,title);
			       temp=(struct problemlist *)calloc(sizeof(struct problemlist),1);
			       temp->comment=(char *)calloc(strlen(comment)+5,1);
			       strcpy(temp->comment,comment);
			       temp->revid=(char *)calloc(strlen(revid)+5,1);
			       strcpy(temp->revid,revid);
			       temp->title=(char *)calloc(strlen(title)+5,1);
			       strcpy(temp->title,title);
				   temp->frev=(char *)calloc(strlen(frev)+5,1);
			      strcpy(temp->frev,frev);
				   temp->lang=(char *)calloc(strlen(lang)+5,1);
			       strcpy(temp->lang,lang);
				   temp->ftitle=(char *)calloc(strlen(ftitle)+5,1);
			      strcpy(temp->ftitle,ftitle);
				  converttalk(title,talktitle);
				  temp->talktitle=(char *)calloc(strlen(talktitle)+5,1);
			      strcpy(temp->talktitle,talktitle);
			       if(!head)
				   {
				           pre=head=temp;
				   }
			       else
				   {
				           pre->next=temp;
				           pre=temp;
				   }
			       temp->next=0;
			}
		}
	 }
	 hclose(h);
	 if(strcmp(timestamp,"2016-04-01T00:00:00Z")<0) break;
	}while(next);
	hashdestroy(hsh);
	 return head;
}
int converttalk(char *title,char *talk)
{
	int i=0;
	while(title[i]!=':'&&title[i]) i++;
	if(title[i]==':')
	{
		strncpy(talk,title,i);
		talk[i]=0;
		strcat(talk,"_talk");
		strcat(talk,&title[i]);
		return 1;
	}
	else
	{
		strcpy(talk,"Talk:");
		strcat(talk,title);
		return 0;
	}
}
struct problemlist *localquery()
{
	struct problemlist *pre=0,*temp=0,*head=0;
	FILE *f;
	char buffer[20000];
	char daemon[100];
	char revid[1000]={0};
	char comment[5000]={0};
	char ns[100]={0};
	int number=0;
	char title[1000]={0};
	char lang[10];
	char ftitle[1000];
	char frev[100];
	int i=0,j=0;
	struct hashlist *hsh;
	f=fopen("quarry.txt","r+");
	if(f==0) return NULL;
	while(!feof(f))
	{
		fgets(buffer,19990,f);
		for(i=0;buffer[i]&&buffer[i]!='\t';i++)
		{
			daemon[i]=buffer[i];
		}
		daemon[i]=0;
		i+=1;
		for(j=0;buffer[i+j]&&buffer[i+j]!='\t';j++)
		{
			revid[j]=buffer[i+j];
		}
		revid[j]=0;
		i=i+j+1;
		j=0;
		for(j=0;buffer[i+j]&&buffer[i+j]!='\t';j++)
		{
			comment[j]=buffer[i+j];
		}
		comment[j]=0;
		i=i+j+1;
		j=0;
		for(j=0;buffer[i+j]&&buffer[i+j]!='\t';j++)
		{
			title[j]=buffer[i+j];
		}
		title[j]=0;
		i=i+j+1;
		j=0;
		for(j=0;buffer[i+j]&&buffer[i+j]!='\n';j++)
		{
			ns[j]=buffer[i+j];
		}
		ns[j]=0;
		sscanf(ns,"%d",&number);
		checkcomment(comment,lang,frev,ftitle);
		if(number<20)
		{
		     temp=(struct problemlist *)calloc(sizeof(struct problemlist),1);
		     temp->comment=(char *)calloc(strlen(comment)+5,1);
		     strcpy(temp->comment,comment);
		     temp->revid=(char *)calloc(strlen(revid)+5,1);
		     strcpy(temp->revid,revid);
		     if(number>0)
			 {
			      temp->title=(char *)calloc(strlen(title)+20,1);
			      strcpy(temp->title,nsprefix[number]);
			      strcat(temp->title,title);
			 }
		     else
			 {
			     temp->title=(char *)calloc(strlen(title)+5,1);
			     strcpy(temp->title,title);
			 }

		
		     temp->talktitle=(char *)calloc(strlen(title)+strlen(nsprefix[number+1])+5,1);
		     strcpy(temp->talktitle,nsprefix[number+1]);
		     strcat(temp->talktitle,title);
		     temp->frev=(char *)calloc(strlen(frev)+5,1);
		     strcpy(temp->frev,frev);
		     temp->lang=(char *)calloc(strlen(lang)+5,1);
		     strcpy(temp->lang,lang);
		     temp->ftitle=(char *)calloc(strlen(ftitle)+5,1);
		     strcpy(temp->ftitle,ftitle);
		     temp->next=pre;
		     head=pre=temp;
		}

		
	}
	fclose(f);
	hsh=hashini();
	pre=temp=head;
	while(temp)
	{
		if(!hashquery(hsh,temp->title))
		{
        		hashadd(hsh,temp->title);
				pre=temp;
				temp=temp->next;
		}
		else
		{
			pre->next=temp->next;
			free(temp);
			temp=pre->next;
		}
	}
	return head;
}

int checkcomment(char *comment,char *lang,char *frev,char *ftitle)
{
	char *match1=G2U("通过翻译页面“[[:");
	char *match2=G2U(":Special:Redirect/revision/");
	unsigned int length1=strlen(match1);
	unsigned int length2=strlen(match2);
    unsigned	int i=0,j=0;
	lang[0]=frev[0]=ftitle[0]=0;
	if(strlen(comment)<length1+length2+10)
	{
		free(match1);
		return 0;
	}
	for(i=0;i<length1&&comment[i];i++)
	{
		if(comment[i]!=match1[i]) break;
	}
	if(i!=length1)
	{
		free(match1);
		return 0;
	}
	j=0;
	while(comment[i+j]!=':'&&comment[i+j])
	{
		lang[j]=comment[i+j];
		j++;
	}
	lang[j]=0;
	i=i+j;
	j=0;
	if(comment[i]!=':')
	{
		free(match1);
		return 0;
	}
	for(j=0;j<length2&&comment[i];j++)
	{
		if(comment[i+j]!=match2[j]) break;
	}
	if(j!=length2)
	{
		free(match1);
		return 0;
	}
	i=i+j;
	j=0;
	while(comment[i+j]!='|'&&comment[i+j])
	{
		frev[j]=comment[i+j];
		j++;
	}
	frev[j]=0;
	i=i+j;
	j=0;
	if(comment[i]!='|')
	{
		free(match1);
		return 0;
	}
	i++;
	while(comment[i+j]!=']'&&comment[i+j])
	{
		ftitle[j]=comment[i+j];
		j++;
	}
	ftitle[j]=0;
	i=i+j;
	j=0;
	if(comment[i]!=']')
	{
		free(match1);
		return 0;
	}
	return 1;
}


void show(struct problemlist *head)
{
   FILE *f;
   f=fopen("b.txt","w+");
   while(head)
   {
     fprintf(f,"[[%s]] %s %s %s %s %s %s\r\n",head->title,head->talktitle,head->revid,head->comment,head->lang,head->ftitle,head->frev);
	 fflush(f);
	 head=head->next;
   } 
   fclose(f);
}

int proceed(struct problemlist* p,struct problemlist **newh,int depth)
{
	struct problemlist *head;
	int count=0;
	if(!p) return -1;
	
	head=p;
	for(count=0;count< depth&&head;head=head->next,count++)
	{
	    
		while(!hastoken)
        {
              Sleep(100);
        }
		proceedchild(head);
		
		
	}
	*newh=head;
	
	return 0;
}
int proceedchild(struct problemlist *head)
{
	char newtemp[10000];
	char newtemp_e[15000];
	char tt[2000];
	char url[3000];
	char statusl[500];
	char ch=0,cht=0;
	char buffer[10240];
	int bufferpos=0;
	int i=0;
	int status=0;
	struct neditargv p;
	HTTP h,newtext;
	i=sprintf(newtemp,"Translated page|1=%s|2=%s|version=%s|insertversion=%s",head->lang,head->ftitle,head->frev,head->revid);
	URLEncode(newtemp,i,newtemp_e,14900);
    h=hopen();
    URLEncode(head->talktitle,strlen(head->talktitle),tt,1990);
	//printf("%s\n",head->talktitle);
    sprintf(url,"https://zh.wikipedia.org/w/index.php?action=raw&title=%s&redirect=no",tt);
	//printf("%s\n",url);
	if(get(url,1,h))
	{
		hclose(h);
		return -1;
	}
	hgets(statusl,490,h);
	if(strstr(statusl," 50")||strstr(statusl," 30"))
	{
		hclose(h);
		return -2;
	}
	skipresponseheader(h);
	newtext=hopen();
	hputs("&text=",strlen("&text="),newtext);
	smartURLEncode('{',newtext);
	smartURLEncode('{',newtext);
	hputs(newtemp_e,strlen(newtemp_e),newtext);
	smartURLEncode('}',newtext);
	smartURLEncode('}',newtext);
	smartURLEncode('\n',newtext);
	while(!heof(h))
	{
		cht=ch;
		ch=hgetc(h);
		switch(status)
		{
		case 0:
			if(ch=='{')
			{
				status=1;
				buffer[0]='{';
				bufferpos=1;
				buffer[bufferpos]=0;
			}
			else
			{
				smartURLEncode(ch,newtext);
			}
			break;
		case 1:
			if(ch!='{')
			{
				if(bufferpos!=2)
				{
					hclose(h);
					hclose(newtext);
					return -3;
				}
				status=2;
				
			}
			buffer[bufferpos]=ch;
			bufferpos++;
			buffer[bufferpos]=0;
			break;
		case 2:
			buffer[bufferpos]=ch;
			bufferpos++;
			buffer[bufferpos]=0;
			if(ch=='}')
			{
				for(i=0;i<bufferpos;i++)
				{
					smartURLEncode(buffer[i],newtext);
				}
				bufferpos=0;
				status=0;
			}
			else if(ch=='|')
			{
				if(findtemp(buffer))
				{
					status=3;
					bufferpos=0;
				}
				else
				{
					for(i=0;i<bufferpos;i++)
					{
					    smartURLEncode(buffer[i],newtext);
					}
				    bufferpos=0;
				    status=0;
				}
			}
			break;
		case 3:
			if(ch!='}'&&cht=='}')
			{
				status=0;
				if(ch!='\n') smartURLEncode(ch,newtext);
			}
			break;
		}
	}
	hclose(h);
	if(status==1||status==2)
	{
		hclose(newtext);
		return -3;
	}
    p.newtext=newtext;
	p.title=tt;
	smartedit(&p);
	hclose(newtext);
	return 0;
}
int findtemp(char *title)
{
	char prep[5000];
	int i,j;
	char *match1=G2U("已翻譯的頁面"),*MATCH1=G2U("已翻译页面");
    char *match2=G2U("翻譯自"),*MATCH2=G2U("翻译自");
	for(i=0,j=0;title[i]&&i<4900;i++)
	{
		if(title[i]!=' '&&title[i]!='{'&&title[i]!='|'&&title[i]!='_')
		{
			prep[j]=(title[i]>='A'&&title[i]<='Z')?(title[i]+'a'-'A'):title[i];
			j++;
			prep[j]=0;
		}
	}
	if(title[i]) return 0;
	if(!strcmp(prep,"translatedpage")||!strcmp(prep,match1)||!strcmp(prep,match2)||!strcmp(prep,MATCH1)||!strcmp(prep,MATCH2)) return 1;
	return 0;
}
int smartedit(struct neditargv *p)
{
   HTTP f;
  
	const char *invalid1="notoken",*invalid2="badtoken";
	const int length1=strlen(invalid1),length2=strlen(invalid2);
	char line[1050],url[10240],aft[1000];

	int resultlength=0,i=0,j=0,error=0,count=0,find;
     
	strcpy(url,"https://zh.wikipedia.org/w/api.php?action=edit&title=");
	strcat(url,p->title);
	strcpy(aft,"&summary=add_translate_template([[User:Antigng-bot/1]])&minor=1&bot=1&format=xml&token=");
	find=strlen(aft);
    do
	{
		f=hopen();
		error=0;count++;
	while(!hastoken)
    {
		Sleep(100);
	}
	EnterCriticalSection(&cs);
	aft[find]=0;
	strcat(aft,token);
	LeaveCriticalSection(&cs);
	hrewind(p->newtext);
	smartpost(url,p->newtext,aft,1,f);
	resultlength=0;error=0;
	
	while(!heof(f))
	{
	    hgets(line,1000,f);
		i=0;j=0;
		while(line[j])
		{
		if(line[j]==invalid1[0])
		{
			for(i=0;i<length1;i++)
			{
				if(line[j+i]!=invalid1[i]) break;
			}
			if(i==length1) {error=1;break;}
		}
		if(line[j]==invalid2[0])
		{
			for(i=0;i<length2;i++)
			{
				if(line[j+i]!=invalid2[i]) break;
			}
			if(i==length2) {error=1;break;}
		}
		j++;
		
		}
	}

	
	
	
	hclose(f);

	if(error) 
	{
		EnterCriticalSection(&cs);
		i=0;
		while(token[i])
		{
			if(aft[find+i]!=token[i]) break;
			i++;
		}
		if(token[i]==0) hastoken=0;
		LeaveCriticalSection(&cs);
	}
    }while(error&&count<3);
	return 0;
}