User:Kotbot/Source
# Source code (Python) for Kotbot------------
def doros(sta,sto):
C=F('tclog')[sta:sto+1]; TY=F('tylog'); global g_logcon
for L in C:
cy=row(TY,L[1],2)[1]; g_logcon=L[0]; n=nam(L[0])
tx=wpraw('en',L[0]); iib=iibox(L,cy)
if 'nfobox' in tx:
log('settlement' if 'nfobox settlement'\
in tx else envirs(tx,'nfobox',2,25))
elif 'ategory:Communes in '+cy not in tx or 'Romania' not in tx:
log('*wrong page? '+iib)
elif '{{bot' in tx or '{{nob' in tx or '{{Bot' in tx or '{{Nob' in tx:
log('*bot exclusion '+iib)
else:
x=sf(tx,"'''"+n)
if x<0 or x>100 or "'''"+n in tx[x+3:]:
log('*no place for infobox: '+iib)
else:
ty=tx[:x]+iibox(L,cy)+'\n'+tx[x:]
if '<ref>' in ty and '{{reflist}}' not in ty and \
'<references' not in ty and '{{Reflist}}' not in ty:
if 'eferenc' in ty or 'xternal' in ty or 'Notes' in ty:
log('*cant place reflist')
else:
xx=sf(ty,('\n{{Communes','\n{{communes',
'\n{{DEFAULT','\n[[Category'))
if xx<0:
log('*cant put ref section')
else:
ty=ty[:xx]+'\n==References==\n{{reflist}}\n\n'+\
ty[xx:]
log('*put ref section')
edit('en',L[0],'Force',ty,
'bot adding infobox')
return sta,sto
def iibox(L,cou):
t=('{{Infobox settlement\n|name='+nam(L[0])+
'\n|settlement_type='+
('[[Municipiu|City]]' if I(L,5)=='M' else (u9('[[Orasx|Town]]'+
'') if I(L,5)=='O' else '[[Communes of Romania|Commune]]'))+
'\n|total_type= \n|image_map=\n|map_caption='+
'\n|subdivision_type=Country\n|subdivision_name'+
'={{flag|Romania}}\n|subdivision_type1=[[Counties of Romania|County]]'+
'\n|subdivision_name1=[['+cou+']]\n|population_total='+L[2])
if L[2]!='' and L[3]!='':
t=(t+'\n|population_as_of=2002\n|population_footnotes=<ref>'+
'[http://recensamant.referinte.transindex.ro/?pg=3&id='+
L[3]+' Romanian census data, 2002]; retrieved on March 1, 2010</ref>')
y=a2l(L[4],'|')
if len(y)==6 and y[0]!='':
t=(t+'\n|latd='+y[0]+'|latm='+y[1]+'|lats='+y[2]+'|latNS=N'+
'|longd='+y[3]+'|longm='+y[4]+'|longs='+y[5]+'|longEW=E'+
'\n|pushpin_map=Romania')
t=(t+'\n|timezone=[[Eastern European Time|EET]]|utc_offset=+2'+
'\n|timezone_DST=[[Eastern European Summer Time|EEST]]'+
'|utc_offset_DST=+3\n}}')
return t
def absss():
"""Coords"""
T=F('ttlog')
for L in T:
tx=wpraw('en',L[0])
if 'nfobox' in tx:
ac=''
else:
acm=mgp(r'\{\{(?:C|c)oord(.*)\}',tx); ac=ascoo(acm)
if len(L)==6:
log(L[0],L[1],L[4],L[5],ac,L[2])
else:
log(L+[ac,'**'])
return 9
def oldddoioi():
TY=col(F('tylog'),2)
for L in T:
if len(L)==6:
if '*' in L[0] or L[1] not in TY \
or not isnin(L[4],200,1000000) or not isnin(L[5],1,2951) or \
S[eval(L[5])-1][3:5]!=[L[1],L[4]]:
log('*',L[0])
else:
if len(L)!=4 or L[1] not in TY or L[3]!='*0':
log('*',L[0])
return 9
def abcrc(sta,sto):
"""Get"""
S=F('sulog'); SV=F('svlog'); T=F('tclog'); TY=F('tylog')
for L in T[sta:sto+1]:
na=nam(L[0]); cy=row(TY,L[1],1)[2]
A=rows(S,na,1)
B=rows(A,cy,3)
if len(B)==0:
A=rows(SV,J2j(rom(na)).replace('-',' '),1)
B=rows(A,cy,3)
if len(B)==0:
A=rows(SV,J2j(rom(na)).replace('-',' ').replace('a',''),1)
B=rows(A,cy,3)
if len(B)==1:
log(L[0],cy,'C',B[0][2],B[0][4],B[0][0])
else:
log(L[0],cy,'C','*'+str(len(B)))
return 9
def achch():
ty=F('tylog'); c=F('tclog'); s=F('sulog'); R=['']*len(ty)
for L in c:
i=lf(ty,L[1],1)
if R[i]=='':
M=row(s,L[0],2)
R[i]=I(M,4)
for j in range(len(ty)):
log(ty[j][1],R[j])
return 9
def an2():
g=catcont('en','Communes and villages in Romania')[0]; L=[]
for k in g:
if starts(k,'Communes in ') and ends(k,' County'):
kk=k[12:]
elif starts(k,'Localities in ') and ends(k,' County'):
kk=k[14:]
else:
kk=k
log(kk)
h=catcont('en',k)[1]
for y in h:
L=L+[[y,kk]]
a2fi(L,'blog')
return 9
#Localities in Ilfov County (incl. 9 towns)
def an1():
K=F('sourcelog')
for L in K:
t=L[2]; c='**'
if starts(t,'Municipiul '):
t=t[11:]; c='m'
elif ends(t,' municipiul'):
t=t[:-11]; c='m'
elif starts(t,'Comuna '):
t=t[7:]; c='c'
elif ends(t,' comuna'):
t=t[:-7]; c='c'
elif ends(t,' c.'):
t=t[:-3]; c='c'
elif ends(t,' o.'):
t=t[:-3]; c='o'
elif ends(t,' ora\xc5\x9f'):
t=t[:-6]; c='o'
elif ends(t,' ora\xc5\x9ful'):
t=t[:-8]; c='o'
elif starts(t,'Ora\xc5\x9e '):
t=t[6:]; c='o'
elif starts(t,'Ora\xc5\x9eul '):
t=t[8:]; c='o'
elif starts(t,'Ora\xc5\x9ful '):
t=t[8:]; c='o'
elif ' '!=t:
c='x'
log(L[1],noex(t.replace(' ',' ')),c,L[3],L[4])
return 9
def romget(sta,sto):
for n in range(sta,sto+1):
u='http://recensamant.referinte.transindex.ro/?pg=3&id='+str(n)
t=urlread(u)
nl=mgps('margin-top.+>(.+?)<',t)
pl=mgps('<th>Total.+\n.+>(\d+)<',t)
if len(nl)!=1 or len(pl)!=1 or '>' in nl[0]+pl[0]:
log(str(n)+'>**>'+str(nl+pl))
else:
nj=noex(upto(nam(nl[0]),'/')); ta=tag(nl[0])
na=replaces(nj,[('\xe2','\xc3\xa2'),
('\xe3','\xc4\x83'),
('\xba','\xc5\x9f'),
('\xfe','\xc5\xa3'),
('\xce','\xc3\x8e'),
('\xaa','\xc5\x9e'),
('\xde','\xc5\xa2')])
log(str(n),na,ta,pl[0])
return sta,sto
#****************
global g_uni, g_coo, g_lang, g_logfile, g_logcon
global g_user, g_pass, g_jar, g_loggedon
#Unicode characters: lowercase, uppercase, keyboard, (reduction)
g_uni=(('pl',(('\xC4\x85','\xC4\x84','a'),('\xC4\x87','\xC4\x86','c'),
('\xC4\x99','\xC4\x98','e'),('\xC5\x82','\xC5\x81','l'),
('\xC5\x84','\xC5\x83','n'),('\xC3\xB3','\xC3\x93','o'),
('\xC5\x9B','\xC5\x9A','s'),('\xC5\xBA','\xC5\xB9','x','z'),
('\xC5\xBC','\xC5\xBB','z'))),
('cs',(('\xc3\xa1','\xc3\x81','a'),('\xc4\x8d','\xc4\x8c','c'),
('\xc4\x8f','\xc4\x8e','d'),('\xc3\xa9','\xc3\x89','e'),
('\xc4\x9b','\xc4\x9a','f','e'),('\xc3\xad','\xc3\x8d','i'),
('\xc5\x88','\xc5\x87','n'),('\xc3\xb3','\xc3\x93','o'),
('\xc5\x99','\xc5\x98','r'),('\xc5\xa1','\xc5\xa0','s'),
('\xc5\xa5','\xc5\xa4','t'),('\xc3\xba','\xc3\x9a','u'),
('\xc5\xaf','\xc5\xae','v','u'),('\xc3\xbd','\xc3\x9d','y'),
('\xc5\xbe','\xc5\xbd','z'))),
('ro',(('\xc3\xa2','\xc3\x82','a'),('\xc4\x83','\xc4\xa3','b','a'),
('\xc3\xae','\xc3\x8e','i'),
('\xc5\x9f','\xc5\x9e','s'),
('\xc5\xa3','\xc5\xa2','t'))))
#Max and min degree
g_coo=(('pl',(49,54,14,24)),('cs',(48,51,12,18)),('ro',(43,48,20,29)))
g_lang='ro'
g_logfile='blog.txt'
g_logcon=''
g_jar=0
g_loggedon=[]
def I(x,n,df=''):
"""x[n] if exists else default"""
try:
return x[n]
except:
return df
def lty(a):
"""Returns 2 if a t/list containing t/list(s), 1 if other t/l, else 0"""
if type(a) not in (tuple,list):
return 0
for b in a:
if type(b) in (tuple,list):
return 2
return 1
def l2s(L,sep='>'):
"""Converts list to string, > default separator"""
os=''
for x in L[:-1]:
os=os+str(x)+sep
os=os+str(I(L,-1))
return os
def a2s(a,sep='>'):
"""Converts any to string, > and \n default seps"""
if lty(a)<2:
return str(a) if lty(a)==0 else l2s(a,sep)
s=''
for b in a:
s=s+(str(b) if lty(b)==0 else l2s(b,sep))+'\n'
return s
def a2p(a):
"""If list or tuple, returns tuple. Else returns 1-tuple."""
return tuple(a) if lty(a)>0 else (a,)
def a2pp(a):
"""Makes tuple of tuples"""
if lty(a)<2:
return (a2p(a),)
pp=()
for b in a:
pp=pp+(a2p(b),)
return pp
def a2l(a,seps='>'):
"""Converts any to list, > default sep (can be alternative seps)"""
if lty(a)>0:
return list(a)
s=str(a)
if I(s,-1)=='\n' and '\n' in seps:
s=s[:-1]
if s=='' and '>' not in seps:
return []
l=[]; t=''
for ch in s:
if ch in seps:
l.append(t); t=''
else:
t=t+ch
l.append(t)
return l
def a2ll(a,seps='>'):
"""Converts to list of lists, > and \n default separators"""
if lty(a)>1:
return list(a)
LL=[]
for k in a2l(a,'\n'):
LL.append(a2l(k,seps))
return LL
def reesc(st):
"""Escapes string to regex or removes initial !R"""
import re; s=str(st)
return s[2:] if re.match('!R',s) else re.escape(s)
def a2re(a,get=0):
"""String/tuple to regex: init. !R for no escape, get=1 for ()"""
os='(' if get else '(?:'; p=a2p(a)
if len(p)==1:
return '('+reesc(p[0])+')' if get else reesc(p[0])
for x in p:
os=os+reesc(x)+'|'
return os[:-1]+')'
def mgps(r,s):
"""Returns all matched groups from regex matched to s, or []"""
ol=[]; import re
l=re.search(r,s)
if not l:
return []
for x in l.groups():
if type(x)==str:
ol.append(x)
return ol
def mgp(r,s):
"""First of matched groups, or '' """
return I(mgps(r,s),0)
def newunifile(finame,intro=''):
"""Creates unicode file with intro as first line, if file nonexistent"""
"""Returns 1 if created, else -1"""
full=finame if '.' in finame else finame+'.txt'
try:
fi=open(full)
except:
try:
nf=open(full,'w')
except:
return -1
nf.write('\xef\xbb\xbf'+(intro if intro!='' else finame+' file')+'\n')
nf.close()
return 1
fi.close()
return -1
def fi2l(finame):
"""Gets list of lines; returns -1 if no such file"""
L=[]; fo=finame if 'log' in finame or '/' in finame or\
'.' in finame else 'jdata/'+finame
full=fo if '.' in fo else fo+'.txt'
try:
fi=open(full)
except:
return -1
for line in fi:
L.append(line[:-1] if I(line,-1)=='\n' else line)
fi.close()
return L[1:]
def fi2ll(finame,seps='>'):
"""File with >-sep. lines to list of lists. -1 if no such file"""
a=fi2l(finame)
return -1 if a==-1 else a2ll(a,seps)
def F(*fis):
"""Multiple fi2ll"""
j=()
for fi in fis:
j=j+(fi2ll(fi),)
return j[0] if len(j)==1 else j
def fi2s(finame):
"""Converts file to single string with \n's. -1 if no such file"""
a=fi2l(finame)
return -1 if a==-1 else l2s(a,'\n')+'\n'
def a2fi(A,finame):
"""Writes anything to file"""
if A=='':
return
full=finame if '.' in finame else finame+'.txt'
fi=open(full,'a')
for L in a2pp(A):
fi.write(l2s(L)+'\n')
fi.close()
return 0
def log(*f):
"""Logs g_logcon plus series of items, to g_logfile"""
op=(g_logcon,) if g_logcon else ()
for a in f:
op=op+(a2s(a),)
return a2fi(op,g_logfile)
def allin(a,b):
"""?Are all chars/els of a in b"""
for x in a:
if x not in b:
return False
return True
def reps(L,M=0):
"""List of repetitions in L / things in L also in M"""
OL=[]
for i in range(len(L)):
if L[i] in (M if M!=0 else L[:i]):
OL.append(L[i])
return OL
def replaces(st,L):
"""Does non-reiterated replaces acc. to list of pairs"""
for ab in L:
st=st.replace(ab[0],ab[1])
return st
def subs(st,L):
"""Applies list of regex substitution pairs (triples)"""
import re
for l in L:
st=re.sub(l[0],l[1],st,I(l,2,0))
return st
def has(S,st,wh=0,se=''):
"""?Does S contain a(any of) st (can be !R+regex) (se for start/end)"""
"""If wh>0: +which(2=last non-overlap.)+start+stop(3=how many)"""
import re; of=0; s=str(S); r=a2re(st,1)
if wh>1:
M=re.split(r,s)
if len(M)>1:
of=len(s)-len(M[-1])-len(M[-2]); s=s[of:]
m=re.search(('^' if 's' in se else '')+r+('$' if 'e' in se else ''),s)
if wh==0:
return True if m else False
if m:
return True, m.group(), m.start()+of, m.end()+of if wh<3 else len(M)/2
return False,'',-1,0
def starts(S,st,wh=0):
"""?Does S start with (any of) st (wh=1 also returns which)"""
return has(S,st,wh,'s')
def ends(S,st,wh=0):
"""?Does S end with (any of) st (wh=1 also returns which)"""
return has(S,st,wh,'e')
def isas(S,st,wh=0):
"""?Is S (any of) st (wh=1 also returns which)"""
return has(S,st,wh,'se')
def spl(S,st):
"""Split: if st in S, returns triple, else S,'',''"""
h=has(S,st,1)
return (S[:h[2]],h[1],S[h[3]:]) if h[0] else (S,'','')
def mspl(sl,r,ch):
"""Splits 1st of strings; codes the result (code is !;(ch)(n); )"""
import re
m=re.split('('+r+')',sl[0]); os=''
for n in range(len(m)):
if n%2==0:
os=os+m[n]
else:
sl.append(m[n]); os=os+'!;'+ch+str(len(sl)-1)+';'
return [os]+sl[1:]
def subslist(sl):
"""List for subs use based on sl"""
L=[]
for n in range(1,len(sl)):
L.append([r'!;[^0-9]*'+str(n)+';',sl[n]])
return L
def sf(S,m,st='',fl=''):
"""Finds st in S (or rel. index m), fl=j,l,1. -1 if m=-1 or not found"""
if type(m)!=int:
fl=st; st=m; m=0
if m<0:
return (-1,'') if '1' in fl else -1
K=has(S[m:],st,(2 if 'l' in fl else 1))
if not K[0]:
return (-1,'') if '1' in fl else -1
i=K[3] if 'j' in fl else K[2]
return (i+m,K[1]) if '1' in fl else i+m
def nin(S,st):
"""How many of (non-overlapping) (any of) st in S"""
N=0
if type(S)!=str:
for s in S:
if isas(s,st):
N=N+1
return N
return has(S,st,3)[3]
def compare(a,b):
"""If a, b not identical, returns index and differing items"""
for n in range(max(len(a),len(b))):
if I(a,n)!=I(b,n):
return n,I(a,n),I(b,n)
return -1,'',''
def envirs(S,st,back,forth):
"""Returns all environments (back and forth define how big) of st in S"""
L=[]
for i in range(len(S)):
si,wh=starts(S[i:],st,1)[:2]
if si:
L.append(S[max(0,i-back):i+len(wh)+forth])
return a2s(L).replace('\n','&')
def per(ST,PARM,THIS):
"""Applies st (column of THIS, -1 gives PARM; or eval string)"""
if ST==-1:
return PARM
if ST==-2:
return THIS
if type(ST)==int:
return I(a2p(THIS),ST)
return eval(ST.replace('!!','THIS').replace('!%','PARM'))
def rows(L,st,col=0,rcols=-2,ret=-1):
"""Gets rcols (-2=all, -1=ind.) of ret (-1=all,0=NOT) rows: st match col"""
"""col can be eval string. Single rcol will debracket"""
OL=[]; n=0
while n<len(L) and (ret<1 or len(OL)<ret):
K=L[n]
if isas(per(col,n,K),st)==(ret!=0):
O=[]
for c in a2p(rcols):
O=O+(list(a2p(K)) if c==-2 else [per(c,n,K)])
OL.append(O[0] if type(rcols)==int and rcols>-2 or
type(L[n]) not in (list,tuple) and rcols==-2 else O)
n=n+1
return OL
def row(L,st,col=0,rcols=-2):
"""First of rows, or []"""
return I(rows(L,st,col,rcols,1),0,[])
def lf(L,st,col=0):
"""Index of first of rows, or -1"""
return I(rows(L,st,col,-1,1),0,-1)
def col(L,col):
"""Column(s) from L"""
return rows(L,'a','"a"',col)
def j2J(st,no=0):
"""All to uppercase; no=1 means only initial"""
inil=1
L=[('a','A'),('b','B'),('c','C'),('d','D'),('e','E'),('f','F'),('g','G'),
('h','H'),('i','I'),('j','J'),('k','K'),('l','L'),('m','M'),('n','N'),
('o','O'),('p','P'),('q','Q'),('r','R'),('s','S'),('t','T'),('u','U'),
('v','V'),('w','W'),('x','X'),('y','Y'),('z','Z')]
for k in g_uni:
for a in k[1]:
L.append((a[0],a[1]))
inil=len(a[0]) if st[:len(a[0])]==a[0] else inil
if no==1:
return replaces(st[:inil],L)+st[inil:]
return replaces(st,L)
def st2St(st):
"""Capitalises first character of string"""
return j2J(st,1)
def J2j(st,no=0):
"""All to lower case; no=1 means only initial"""
inil=1
L=[('A','a'),('B','b'),('C','c'),('D','d'),('E','e'),('F','f'),('G','g'),
('H','h'),('I','i'),('J','j'),('K','k'),('L','l'),('M','m'),('N','n'),
('O','o'),('P','p'),('Q','q'),('R','r'),('S','s'),('T','t'),('U','u'),
('V','v'),('W','w'),('X','x'),('Y','y'),('Z','z')]
for k in g_uni:
for a in k[1]:
L.append((a[1],a[0]))
inil=len(a[1]) if st[:len(a[1])]==a[1] else inil
if no==1:
return replaces(st[:inil],L)+st[inil:]
return replaces(st,L)
def St2st(st):
"""Makes first char. lower case"""
return J2j(st,1)
def U(st,la=''):
"""From x+ format to Unicode"""
la=la if la!='' else g_lang; d=row(g_uni,la,0,1)
for a in d:
st=st.replace(a[2]+'+',a[0]).replace(j2J(a[2])+'+',a[1])
return st
def rom(st,la=''):
"""Unicode to reduced format"""
la=la if la!='' else g_lang; d=row(g_uni,la,0,1)
for a in d:
r=I(a,3,a[2])
st=st.replace(a[0],r).replace(a[1],j2J(r))
return st
def rplus(st,la=''):
"""Unicode to x+ format"""
la=la if la!='' else g_lang; d=row(g_uni,la,0,1)
for a in d:
st=st.replace(a[0],a[2]+'+').replace(a[1],j2J(a[2])+'+')
return st
def notrail(s,a):
"""Removes (any of) a from end of string, iteratively"""
t=''; import re
while ends(s,a) and t!=s:
t=s; s=re.sub(a2re(a)+'$','',s)
return s
def noinit(s,a):
"""Removes (any of) a from start of string, iteratively"""
t=''; import re
while starts(s,a) and t!=s:
t=s; s=re.sub('^'+a2re(a),'',s)
return s
def noex(st):
"""Removes spaces and newlines from start and end"""
return notrail(noinit(st,(' ','\n')),(' ','\n'))
def repblank(t):
"""Removes double blank lines from t"""
while '\n\n\n' in t:
t=t.replace('\n\n\n','\n\n')
return t
def upto(s,a):
"""If s contains (any of) a, returns noex of what goes before (else s)"""
return noex(spl(s,a)[0])
def after(s,a):
"""If s contains a, returns what comes after (else '')"""
return spl(s,a)[2]
def insbef(s,a,t,T0='',T2=''):
"""puts t before a in s, T0/T2 logged if not found/found twice"""
K=has(s,a,1)
if not K[0]:
log(T0) if T0!='' else ''; return s
if has(s[K[3]:],a):
log(T2) if T2!='' else ''
return s[:K[2]]+t+s[K[2]:]
def insaft(s,a,t,T0='',T2=''):
"""puts t after a in s, T0/T2 logged if not found/found twice"""
K=has(s,a,1)
if not K[0]:
log(T0) if T0!='' else ''; return s
if has(s[K[3]:],a):
log(T2) if T2!='' else ''
return s[:K[3]]+t+s[K[3]:]
def l2txt(L,sep=', ',lsep=', and ',osep=' and ',do=0):
"""Makes a text list. Normal separator, last, only, operation on items"""
os=''; k=len(L)
for n in range(k):
os=os+per(do,n,L[n])+\
(osep if n==0 and k==2 else (lsep if n==k-2 else (sep if
n<k-1 else '')))
return os
def isn(st):
"""Is st a pure integer?"""
return isas(st,r'!R0|\-?[1-9][0-9]*')
def isnin(st,a,b):
"""Is st a pure int in the range a to b?"""
return isn(st) and eval(st)>=a and eval(st)<=b
def isx(st):
"""Is st a pure English int or decimal?"""
return isas(st,r'!R\-?(0|[1-9][0-9]*)(\.[0-9]+)?')
def no0(s):
"""Removes redundant initial zero from number"""
return s[1:] if I(s,0)=='0' and I(s,1,'X') in '0123456789' else s
def nco(s):
"""Puts commmas into English number string"""
z=spl(s,'.'); import re
return re.sub(r'(?<=[0-9])([0-9]{3})(?=([0-9]{3})*$)',r',\1',
z[0])+z[1]+z[2]
def sround(xs,n=0):
"""Rounds a string number to n dec places, 0 gives an int"""
z=spl(xs,'.')
if not isx(xs) or len(z[2])<=n:
return xs
if z[2][n] in '01234':
az='0' if z[0]=='-0' and z[2][:n]=='0'*n else z[0]
return az+('.' +z[2][:n] if n>0 else '')
zz=str(eval('1'+z[2][:n])+1)
if zz[0]=='1':
return z[0]+('.'+zz[1:] if n>0 else '')
return str(eval(z[0])+(-1 if z[0][0]=='-' else 1))+\
('.'+zz[1:] if n>0 else '')
def nword(nn):
"""Converts to a word if integer 1-9, else just to a string"""
n=eval(nn) if type(nn)==str and isn(nn) else nn
if n in range(1,10):
return ['one','two','three','four','five','six','seven','eight',
'nine'][n-1]
return str(n)
def ifpl(n,plst='s',sst=''):
"""returns s or other pl if n not 1, else empty or other sing"""
return sst if n==1 else plst
def less(x,y):
"""?Is x less than y (nos. by value then strings wo diacritics)"""
x=eval(x) if type(x)==str and isx(x) else x
y=eval(y) if type(y)==str and isx(y) else y
if type(y)==str and type(x)!=str:
return True
if type(x)==str and type(y)!=str:
return False
if type(y)!=str:
return x<y
a=rom(x); b=rom(y); c=J2j(a); d=J2j(b)
if a==b:
return x<y
if c==d:
return a<b
return c<d
def lless(p,q):
"""?Is list p less than q"""
p=a2p(p); q=a2p(q)
for n in range(max(len(p),len(q))):
if n==len(p):
return True
if n==len(q):
return False
if less(p[n],q[n]):
return True
if less(q[n],p[n]):
return False
return False
def rless(p,q,col=-2,m=0,n=0):
"""?Is p less than q by col (m and n: params if col an eval str"""
return lless(per(col,m,p),per(col,n,q))
def ins(L,p,col=-2,cp=-2):
"""Inserts p (changed per cp) in list, in order defined by col"""
m=0; n=len(L); p=per(cp,0,p)
while m!=n:
h=(m+n)/2
if rless(p,L[h],col):
n=h
else:
m=h+1
return L[:n]+[p]+L[n:]
def sort(L,col=-2,cp=-2,topn=0):
"""Returns cp-ed list of lists/tuples sorted by columns cs (top n only)"""
OL=[]; n=len(L) if topn==0 else topn
for p in L:
OL=ins(OL,p,col)[:n]
return OL
def getnos(s,decpts='.,'): #must be some decpts
"""Returns normed nos; number blocks; intervening blocks (ie 1 more)"""
import re
t=re.split(r'((?:[0-9]|['+reesc(decpts)+'](?=[0-9]))+)',s)
p=rows(t,'1','str(!%%2)'); q=rows(t,'0','str(!%%2)'); k=[]
for x in p:
x=no0(x.replace(',','.'))
if isx(x):
k.append(x)
return k,p,q
def normno(st,u,v,U,V,tolog=''):
"""norms a number string (or ''), w warning + error limits"""
s=replaces(st,[(' ',' '),("'",' '),(' ,',' ;'),(' ','')])
k=sf(s,('(','<','{','['))
if k>0:
s=noex(s[:k]); log('*'+tolog+' from '+st+' to: '+s)
if s=='':
return ''
k=sf(s,',')
if k>0:
if '.' in s:
s=s[:k].replace('.','')+'.'+s[k+1:]
log('*'+tolog+' from '+st+' to: '+s)
else:
s=s[:k]+'.'+s[k+1:]
if not isx(s):
log('**'+tolog+' NOT NUMERICAL: '+st); return ''
d=eval(s)
if d<U or d>V:
log('**'+tolog+' OUT OF RANGE: '+s+' ('+str(U)+','+str(V)+')')
return ''
if d<u or d>v:
log('*'+tolog+' outside range?: '+s+' ('+str(u)+','+str(v)+')')
if str(d)!=s:
log('*'+tolog+' from: '+st+' got '+s)
return s
def ascoo(s):
"""Converts string/list to six-coo string, or err/warn"""
p=getnos(a2s(upto(s,('E|','source'))))[0]; g=row(g_coo,g_lang,0,1)
if len(p)==2 and '.' in p[0] and '.' in p[1]:
x=eval(p[0]); m=int(x); mm=int((x-m)*60.0+0.5)
y=eval(p[1]); n=int(y); nn=int((y-n)*60.0+0.5)
r=[str(m),str(mm),'',str(n),str(nn),'']
elif len(p)==4 and '.' not in p[0]+p[2]:
r=[str(p[0]),sround(str(p[1])),'',str(p[2]),sround(str(p[3])),'']
elif len(p)==6 and '.' not in p[0]+p[1]+p[3]+p[4]:
r=[str(p[0]),str(p[1]),sround(str(p[2])),
str(p[3]),str(p[4]),sround(str(p[5]))]
else:
#log('**no coords from: '+s)
return '|||||'
for i in (2,5,1,4):
if r[i]=='60':
#log('*60 in coords: '+s)
r[i]='0'; r[i-1]=str(eval(r[i-1])+1)
if eval(r[0]) not in range(g[0],g[1]+1) or \
eval(r[3]) not in range(g[2],g[3]+1) or \
eval(r[1]) not in range(0,60) or eval(r[4]) not in range(0,60) or \
r[2]!='' and eval(r[2]) not in range(0,60) or \
r[5]!='' and eval(r[5]) not in range(0,60):
log('**strange coords from: '+s)
return '|||||'
return a2s(r,'|')
def coo2xy(c):
"""Pipe-sep coor string to decimals or 0,0"""
d=[]
for k in a2l(c,'|'):
d.append(0 if k=='' else eval(k))
return d[0]+d[1]/60.0+d[2]/3600.0,d[3]+d[4]/60.0+d[5]/3600.0
def kmdir(x,y,X,Y):
"""Returns distance and direction of (x,y) from (X,Y) (within Poland)"""
import math
vx=(x-X)*110.946
vy=(y-Y)*111.319*math.cos(math.radians((x+X)/2))
d=int(math.sqrt(vx*vx+vy*vy))+1
if vx>2.42*abs(vy):
pt='north'
elif -vx>2.42*abs(vy):
pt='south'
elif vy>2.42*abs(vx):
pt='east'
elif -vy>2.42*abs(vx):
pt='west'
else:
pta='north' if vx>0 else 'south'
ptb='east' if vy>0 else 'west'
pt=pta+'-'+ptb
return d,pt
def km(c,d):
"""Distance between coord | strings"""
x,y=coo2xy(c); X,Y=coo2xy(d)
return kmdir(x,y,X,Y)[0]
def kmtxt(dc,dcb,u,v,U,V,abbr,tolog):
"""Makes text e.g. 8 km north, of dc from dcb (warning/error limits)"""
x,y=coo2xy(dc); X,Y=coo2xy(dcb)
d,pt=kmdir(x,y,X,Y)
if d<U or d>V:
log('**'+tolog+' DIST REJECTED: '+str(d)+' ('+str(U)+','+str(V)+')')
return ''
if d<u or d>v:
log('*'+tolog+' distance wrong?: '+str(d)+' ('+str(u)+','+str(v)+')')
return '{{convert|'+str(d)+'|km|mi|0'+('|abbr=on' if abbr else '')+'}} '+pt
def loctxts(name,c,*p):
"""Full text: name, coords, list of coo/name/text/uvUV/pri 8s (V2 16s)"""
L=[]; M=[]; N=[]
for x in p:
if len(x)==16:
A1=km(c,x[0]); A2=km(c,x[8])
A3=km(x[0],x[8]); Ah=max(A1,A2); Ab=min(A1,A2)
X1,X2=(x[:8],x[8:]) if Ab==A1 else (x[8:],x[:8])
L=L+[X1] if 2*(Ah*Ah-Ab*Ab)>A3*A3 else L+[X1,X2]
else:
L.append(x)
for K in L:
if list(K)==sort(rows(L,K[1],1),7)[-1] and K[1]!=name:
M.append(K)
for K in M:
t=kmtxt(c,K[0],K[3],K[4],K[5],K[6],K!=M[0],K[7])
if t=='':
return ''
if not starts(t,'{{convert|1|'):
N.append(t+' of '+K[2])
else:
log('*omitted: '+t+' of '+K[2])
returnstr='approximately '+l2txt(N)
return returnstr if len(N)>0 else ''
def st2date(s):
"""Converts string to proper date"""
w=getnos(s,'@')[0]
if len(w)==1 and isn(w[0]) and eval(w[0]) in range (2000,2010):
return w[0]
if len(w)==3 and isn(w[2]) and eval(w[2]) in range (2000,2010) and\
isn(w[1]) and eval(w[1]) in range(1,13) and\
isn(w[0]) and eval(w[0]) in range(1,30 if w[1]=='2' else (31 if
w[1] in ('4','6','9','11') else 32)):
return w[0]+' '+('January','February','March','April','May','June',
'July','August','September','October','November',
'December')[eval(w[1])-1]+' '+w[2]
return ''
def urlread(url,tries=50):
"""Gets url text"""
import urllib
n=0
while n<tries:
try:
ur=urllib.urlopen(url)
r=ur.read(); ur.close()
return r
except:
n=n+1
return 0/0
def wpraw(la,Art):
return urlread('http://'+la+'.wikipedia.org/w/index.php?title='
+Art.replace(' ','_')+'&action=raw')
def wcraw(Art):
return urlread('http://commons.wikimedia.org/w/index.php?title='+
Art.replace(' ','_')+'&action=raw')
def catcont(la,cat):
"""Returns subcats, members, subckeys, membkeys, sdates, mdates (->500)"""
import re; login(la); SC=[]; M=[]; SCK=[]; MK=[]; SCD=[]; MD=[]
xm=urlread('http://'+la+'.wikipedia.org/w/api.php?cmtitle=Category:'
+cat.replace(' ','_')+'&action=query&list=categorymembers'+
'&cmlimit=500&cmprop=title|sortkey|timestamp')
rg=r'title=\"(.*?)\".*?sortkey=\"(.*?)\".*?'+\
r'timestamp=\"(.*?)\"'
for m in re.findall(rg,xm):
if starts(m[0],'Category:'):
SC.append(m[0][9:]); SCK.append(m[1]); SCD.append(m[2])
else:
M.append(m[0]); MK.append(m[1]); MD.append(m[2])
return SC,M,SCK,MK,SCD,MD
def fullcatcont(la,cat,d=5):
"""Returns all pages below a cat to a depth of d, +cats they're in"""
cs=[[cat,'0']]; ps=[]
for k in range(d+1):
for c in rows(cs,str(k),1,0):
a,b,w,x,y,z=catcont(la,c)
for p in b:
u=lf(ps,p,0)
if u<0:
ps.append([p,c])
else:
ps[u].append(c)
for s in a:
if s not in col(cs,0):
if k<d:
cs.append([s,str(k+1)])
else:
ps.append(['Category:'+s,c])
log([[cat,d]]+ps)
return
def coca():
"""Investigate unmatched categories"""
c=F('colog')[0]
for a in c:
x=catsin(wpraw('en',a)); y=catsin(wpraw('en','Category:'+a))
os=''; ns=''
for p in y:
if p not in x:
if 's ' in p+' ':
os=os+'[[Category:'+p+']]\n'
else:
ns=ns+p+','
log('\n'+a+' ('+ns+')\n'+os)
return 9
def isim(name):
"""?Is ready-trimmed name an image in commons or wp"""
if '.' not in name[1:-1] or sf(name,list('[]{}<>#|'))>-1:
return False
return wcraw('Image:'+name)!='' or wpraw('en','Image:'+name)!=''
def IFim(name):
"""Name if image (or Image: etc.), else empty"""
if isim(name):
return name
if isim(after(name,':')):
return after(name,':')
return ''
def nocomm(text):
"""Removes comments from wikipedia text"""
return subs(text,[(r'\<!--(?:.|\n)*?--\>','')])
def nam(st):
"""Main name part of string, less tag"""
return upto(st,(',','('))
def tag(st):
"""Tag after comma or in brackets"""
return mgp(r', (.*)|\((.*)\)',st)
def essnam(st):
"""Removes generic part of name"""
p=(' ','Gmina','Wojew\xC3\xB3dztwo','Powiat','Park Narodowy',
'Park Krajobrazowy','Okres')
q=(' ','County','Voivodeship','National Park','Landscape Park',
'Park Narodowy','Park Krajobrazowy','District','Region',' kraj')
return notrail(noinit(nam(st),p),q)
def wpl(st):
"""Make WP (piped) link, not displaying the tag"""
name=nam(st)
return '[['+st+']]' if name==st else '[['+st+'|'+name+']]'
def essl(st):
"""Make WP (piped) link, not displaying the tag"""
name=essnam(st)
return '[['+st+']]' if name==st else '[['+st+'|'+name+']]'
def Title(na):
"""Makes WP title, w capital and no underscores"""
return st2St(noex(na.replace('_',' ')))
def targlabel(link):
"""The _T_arget and display text of first wp link (removes extr spaces)"""
m=mgps(r'\[\[(.+?)(?:\|(.*?))?\]\]',link)
if len(m)==0:
return '',link
return Title(m[0]),I(m,1,m[0])
def targ(link):
return targdisp(link)[0]
def label(link):
return targdisp(link)[1]
def redtarg(txt):
"""redirect target in txt or empty string"""
m=mgp(r'^[ \n]*\#(?:REDIRECT|redirect|Redirect)[ ]*(\[\[.*\]\])',nocomm(txt))
return I(m,0)
def targpars(t):
"""Name and list of parameter pairs for a template call"""
import re; m=re.split('\|',subs(t,[('^\{\{',''),('\}\}$','')])); L=[]; n=1
if len(m)==0:
return '',[]
for x in m[1:]:
mm=mgps(r'^(?:[ \n]*(.+?)[ \n]*\=)?[ \n]*((?:.|\n)*?)[ \n]*$',x)
a,b=(mm[0],mm[1]) if len(mm)==2 else (str(n),I(mm,0))
n=n if len(mm)==2 else n+1
L=rows(L,a,0,-2,0)+[[a,b]]
return Title(m[0]),L
def imnam(st):
"""Returns image filename only"""
st2=noinit(st,(' ','[','Image:','image:','grafika:','Grafika:'))
st3=noex(upto(st2,('|',']')))
return st3 if '.' in st3 else ''
def esctext(tx):
"""Converts article text to string structure"""
sl=[tx]
sl=mspl(sl,r'\[\[[^\|\[\]\<\>\{\}\n]+(?:\|.*?)?\]\]','\n')
sl=mspl(sl,r'\[\[(?:Image|image|Grafika|grafika)\:[^\|\[\]\<\>\{\}\n]+'+\
r'(?:\|(?:.|(?<=!;)\n)*?)?\]\]','\n\n')
sl=mspl(sl,r'\{\{[ \n]*[^\|\[\]\<\>\{\}\n]+?[ \n]*(?:\|[^\{\}]*?)?\}\}','')
sl=mspl(sl,r'\{\{[ \n]*[^\|\[\]\<\>\{\}\n]+?[ \n]*(?:\|(?:.|\n)*?)?\}\}','')
return sl
def ansl(sl):
"""Gets lists of links/templates/f values from string structure"""
LL=[]; LT=[]; LF=[]; u=subslist(sl)
for s in sl[1:]:
if I(s,0)=='[':
Q=targlabel(s); LL.append((subs(Q[0],u),subs(Q[1],u),subs(s,u)))
else:
Q,QL=targpars(s); LT.append((Q,subs(s,u)))
for p in QL:
LF.append((Q,p[0],subs(p[1],u)))
return LL,LT,LF
def ant(t):
"""Links (targ,lab,tx), templates (targ,tx), fvals (tem,f,val,tx)"""
return ansl(esctext(t))
def catsin(tx):
"""All categories explicitly in tx"""
k=sf(tx,('[[Category:','[[category:'))
if k<0:
return []
t=tx[max(0,k-10):]; L=[]
for a in ant(t)[0]:
if starts(a[0],'Category:'):
L.append(a[0][9:])
return L
def iwto(tx,la):
"""Target(s$) of iwlink to language la in tx, else empty"""
k=sf(tx,'[['+la+':')
if k<0:
return ''
t=tx[max(0,k-10):]
return I(row(ant(t)[0],'!R'+st2St(la)+':.+',0),0)[3:]
def fv(tx,tem,*f):
"""Named field values"""
L=[]; fl=rows(ant(tx)[2],tem,0)
for x in f:
L.append(I(row(fl,x,1),2))
return L[0] if len(L)==1 else L
def IPA(st):
"""converts Polish string to IPA representation"""
import re; s=' '+rplus(st).replace('-',' ')+' '
if not re.match(r'( [A-PR-UWXZ]?[a-pr-uwxyz\+]+)+ $',s):
return ''
s=subs(J2j(s),[(' w ',' w'),(' z ',' z'),('ch','h'),(r'o\+','u'),
('ia','Ja'),('ie','Je'),('io','Jo'),('iu','Ju'),
('ai','aj'),('ei','ej'),('oi','oj'),('ui','uj'),('au','aL'),
(r'sJ|s\+|s(?=i)','S'),(r'zJ|x\+|z(?=i)','X'),(r'cJ|c\+|c(?=i)','C'),
(r'nJ|n\+','N'),(r'z\+','Z'),(r'l\+','L'),(r'a\+','o9'),(r'e\+','e9'),
('dZ','B'),('dX','D'),('dz','0'),('sz','T'),('cz','1'),('rz','R'),
('9(?=[bp])','m'),('9(?=[tcC1dBD0gk])','n'),('9l','l'),
('(?<=[aeiouy])L(?![aeouy])','U'),('(?<=[aeiouy])j(?![aeou])','I'),
('ji|ii','i')])
L=[]
for n in range(11):
L.append(('bd0BDg'[n]+'(?=[ c1CfhkpstTS4])','ptc1Ck'[n]) if n<6 else\
('wzZXR'[n-6]+'(?=[ c1CfhkpstTS4])|(?<=[c1CfhkpstTS4])'+'wzZXR'[n-6],
'fsTS4'[n-6]))
for n in range(3):
s=subs(s,[(' nad ',' na8d')]+L+[('8d','d '),('8t','t ')])
s=subs(s,[('(((?<= )[^aeiouy ]*|[^aeiouy ]?)([aeiouy][^aeiouy ]*){1,2} )',
r"'\1"),("([bdfghkpsSTtwzZX])'(?=[rR4])",r"'\1"),
("([bfghkpsSTwzZX])'(?=[lL])",r"'\1"),
("([^aeiouy ])'(?=[J])",r"'\1")])
s=s.replace("'",'') if nin(s,"'")==1 and nin(s,list('aeiouy'))<2 else s
s=subs(s,[("'nad ",",nad "),("'nat ",",nat "),('(?<=[SXCDN])e','E'),
("n(?='?[kg])",'5'),('(?<=[^kg])J','j'),('o9','A'),('e9|E9','Y')])
mhl=[(' ','-'),('A',U('a+')),('Y',U('e+')),('B',U('dz+')),('C',U('c+')),
('D',U('dx+')),('E','e' if 'e' in s else 'e1'),('L',U('l+')),
('N',U('n+')),('R',U('z+')),('S',U('s+')),('T','sz'),('X',U('x+')),
('Z',U('z+')),('0','dz'),('1','cz'),('4','sz'),('5','N')]
os='{{IPAc-pl|[]|'
for n in range(1,len(s)-1):
os=os+I(row(mhl,s[n],0),1,s[n])+'|'
if n%28==0 and n<len(s)-2:
os=os[:-1].replace(']','-')+'}}{{IPAc-pl|-]|'
return os[:-1].replace('[]|','')+'}}'
def countystub(p):
pp=p if essnam(p) in ('Opole','Lublin') else essnam(p)
return pp.replace(' ','')+'-geo-stub'
def skey(st):
"""Makes standard category sort key (returns empty if comes to defa)"""
s=rom(st); os=''; import re
for a in re.split(r'[^a-zA-Z]+',s):
os=os+j2J(I(a,0))+J2j(a[1:])+' '
return noex(os)
def expandtem(s):
"""Expands s"""
ur0='http://en.wikipedia.org/wiki/Special:ExpandTemplates'
ht=doreq(ur0,[('contexttitle',''),('input',s),
('removecomments','1'),('generate_xml','0')])
return mup(mgp(r'id\="output".*\>((?:[ .]*?)\</textarea\>',ht))
#
# BOT
#
def Ne(x,y):
return x==y or x==y+'\n' or y==x+'\n'
def formv(form,*ns):
"""Find the given value of a named input in an HTML form"""
L=[]
for nam in ns:
L.append(mgp(r'\<[^\>]*(?:name\="'+nam+r'"[^\>]*value\="(.*?)"'+\
r'|value\="(.*?)"[^\>]*name\="'+nam+r'")',form))
return L[0] if len(L)==1 else L
def mup(html):
"""Marks up &#ref and &ref; chars. in an html string without tags"""
global MuPsTr; MuPsTr=[''] #output string as 1-list
import sgmllib
pa=sgmllib.SGMLParser()
pa.handle_data=writetoMuPsTr #how to handle input
pa.feed(html) #read and handle input
pa.close()
return MuPsTr[0]
def writetoMuPsTr(s):
"""Appends a string to sole element of the global list MuPsTr"""
"""Used in mup() as the data handler"""
MuPsTr[0]=MuPsTr[0]+s
return
def doreq(url,dl=''):
"""Makes an HTTP request and sends it; supplies and extracts cookies"""
"""Returns the response html content, or 'KBerrKB on failure"""
"""dl is the optional data list (of key/value pairs) for a POST"""
"""The global cookie jar is botjar"""
import urllib, urllib2, cookielib
req=urllib2.Request(url) #make Request object
g_jar.add_cookie_header(req) #add relevant cookies
req.add_header('User-agent','Agent.Kotbot') #add User Agent header
if dl!='':
req.add_data(urllib.urlencode(dl)) #add data (changes type to POST)
n=0
while n<50:
try:
u=urllib2.urlopen(req) #send the request
g_jar.extract_cookies(u,req) #extract cookies from response
html=u.read() #get content from response
u.close()
return html
except: #if error, retry
n=n+1
return 'KBerrKB'
def php(la):
"""Returns main part of generic php access string to Wikipedia"""
return 'http://'+la+'.wikipedia.org/w/index.php?title='
def login(la):
"""Initializes global cookiejar, and logs in as the bot"""
"""Languages (las...) can include 'en' and/or 'pl'"""
import cookielib; global g_jar
if g_jar==0:
g_jar=cookielib.CookieJar() #makes global cookie jar
if la not in g_loggedon:
ur0=php(la)+'Special:Userlogin'
doreq(ur0) #get login page
ur1=ur0+'&action=submitlogin&type=login'
dl1=[('wpName',g_user),('wpPassword',g_pass),
('wpRemember','0'),('wpLoginattempt','Log+in')]
rt=doreq(ur1,dl1) #submit form
if rt=='KBerrKB':
log('*FAILEDTOLOGON: '+la)
else:
a2fi('\nLOGGEDON: '+la,'botlog'); g_loggedon.append(la)
return
def edit(la,Art,instr,*params):
"""Edits Wikipedia page according to instruction (and parameters)"""
""" la is the language code, Art is the page name"""
""" instr is the instruction (the function 'edit_'instr will be called)"""
"""Confirms if edit made (adds result to return message)"""
"""Botlogs la:Art:message, returns message and any output"""
global g_logcon; g_logcon=la+':'+Art
login(la); ur0=php(la)+Art.replace(' ','_')+'&action=edit' #edit page url
html=doreq(ur0) #get edit page
if html=='KBerrKB':
log('*NETWORKFAULT1'); return
if g_user not in html:
log('*NOTLOGGEDON'); return
m=mgps(r'name\=\"wpTextbox1\".*?\>((?:.|\n)*?)\<\/textarea\>',html)
if len(m)==0:
log('*BADEDITPAGE'); return
old=mup(m[0]) #existing text or empty string
FUNC=eval('edit_'+instr) #function to be called
#now call the function and get new text, edit summary, message and any output
newtext,summ,mess=FUNC(la,Art,old,*params)
if newtext=='': #end if no new text provided
log(mess) if mess!='' else ''; return
if Ne(newtext,old):
log('*NEWTEXTSAMEASOLD'); return
#now make data list (lp) for POST request
lp=[]; n=sf(html,'id="editform"') #find edit form
for a in ['wpSection','wpStarttime','wpEdittime','wpScrolltop',
'wpEditToken','wpAutoSummary']:
val=formv(html[n:],a) #find each named value on form
lp=lp+[(a,val)] #add key/value pair to list
lp=lp[:4]+[('wpTextbox1',newtext),('wpSummary',summ),
('wpSave','Save page')]+lp[4:]
#now submit the form
ur1=php(la)+Art.replace(' ','_')+'&action=submit' #make the url
htmr=doreq(ur1,lp) #submit the POST request, get response
if htmr=='KBerrKB':
log('*NETWORKFAULT2'); return
#check if the edit was successful
now=wpraw(la,Art) #this is the page text now
conf='[OK]' if Ne(now,newtext) else '[*NOCONFIRM]'
log(mess,conf) if '*' in mess+conf else a2fi((la,Art,mess,conf),'botlog')
return
def qedit(la,Art,instr,*params):
"""As edit, but starts by reading raw"""
global g_logcon; g_logcon=la+':'+Art
exi=wpraw(la,Art); FUNC=eval('edit_'+instr)
newtext,summ,mess=FUNC(la,Art,exi,*params)
if newtext=='': #end if no new text provided
log(mess) if mess!='' else ''; return
if Ne(newtext,exi):
log('*NEWTEXTSAMEASOLD'); return
login(la); ur0=php(la)+Art.replace(' ','_')+'&action=edit' #edit page url
html=doreq(ur0) #get edit page
if html=='KBerrKB':
log('*NETWORKFAULT1'); return
if g_user not in html:
log('*NOTLOGGEDON'); return
m=mgps(r'name\=\"wpTextbox1\".*?\>((?:.|\n)*?)\<\/textarea\>',html)
if len(m)==0:
log('*BADEDITPAGE'); return
old=mup(m[0]) #get and mark up content of text area
if not Ne(old,exi):
log('*UNSTABLEPAGE'); return
#now make data list (lp) for POST request
lp=[]; n=sf(html,'id="editform"') #find edit form
for a in ['wpSection','wpStarttime','wpEdittime','wpScrolltop',
'wpEditToken','wpAutoSummary']:
val=formv(html[n:],a) #find each named value on form
lp=lp+[(a,val)] #add key/value pair to list
lp=lp[:4]+[('wpTextbox1',newtext),('wpSummary',summ),
('wpSave','Save page')]+lp[4:]
#now submit the form
ur1=php(la)+Art.replace(' ','_')+'&action=submit' #make the url
htmr=doreq(ur1,lp) #submit the POST request, get response
if htmr=='KBerrKB':
log('*NETWORKFAULT2'); return
#check if the edit was successful
now=wpraw(la,Art) #this is the page text now
conf='[OK]' if Ne(now,newtext) else '[*NOCONFIRM]'
log(mess,conf) if '*' in mess+conf else a2fi((la,Art,mess,conf),'botlog')
return
#
# BOT EDIT FUNCTIONS
# Each edit_xx function must take as arguments:
# la (lang. code), Art (page name), old (old page text or empty), params...
# It must return:
# new page text (empty=no edit), edit summary, b(ot)log message
#
def edit_New(la,Art,old,text,summ='bot creating page',suppr='!DUMMY!'):
"""text, summary, list to suppress logging of text if art found"""
if not Ne(old,''):
if sf(old,suppr)>-1:
return '','','*ARTEXISTS('+str(len(old))+')'
else:
return '','','*ARTEXISTS('+str(len(old))+') for:\n'+text+'\n'
return text,summ,'CREATED'
def edit_Force(la,Art,old,text,summ='bot: standardizing'):
"""text, summary"""
if Ne(old,''):
log('*HADTOCREATE')
return text,summ,'HADTOCREATE' if Ne(old,'') else 'REPLACEDARTICLE'
def edit_Subst(la,Art,old,lp,summ='bot: standardizing'):
"""list of replace pairs (or 6ples, with min/max, warn min/max)"""
t=old
for p in lp:
k=nin(old,p[0])
if k<I(p,2,0) or k>I(p,3,1000):
print g_logcon, k, I(p,2,0), I(p,3,1000)
return '','','*WRONGNUMBEROF '+p[0]
if k<I(p,4,0) or k>I(p,5,1000):
log(Art+';*NOTE NUMBER OF '+p[0]+':'+str(k))
t=t.replace(p[0],p[1])
return t,summ,'REPLACED'
Content Disclaimer
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.
- The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
- There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
- It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
- Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.