Szerkesztő:BinBot/piroskat-userallap.py

A Wikipédiából, a szabad enciklopédiából

A nem létező kategóriákat a szerkesztői allapokról eltávolító bot. Lásd még itt.

#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
Ez a script a piroskat.py függeléke
Piros kategóriákat keres a Speciális:Keresett kategóriák lapon, amelyek
szerkesztői allapra vannak beillesztve. Nowikibe teszi őket, és értesíti a tulajdonost.

Megoldás:
1. Beolvasás a speclapról
2. Ellenőrzés, hogy tényleg piros-e még
3. A benn levő lapok végignézése: csak 2. névtér, és csak allap
   (Feltételezzük, hogy itt alapvetően készülő cikkek vannak.)
   Nem nyúlunk a userlapokhoz és a szerkesztővita-névtérhez, ott nincs is tömeges gond.
4. nowiki
5. Értesítés (a botMayEdit() figyelembe vételével!) -- ha még nem kapott egy másiknál
6. A Wikipédia:Nem létező kategóriák lap módosítása
A kategória listázásának magyarázata a piroskat.py-ban van.

(C)(D)(E)(F)(G)(A)(H)(C) Bináris. Licenc: használd egészséggel.
"""
import wikipedia as pywikibot
import catlib, re
import binbotutils #naplózás

#Globális változók:
allapok=set() #Itt gyűjtjük a javítottakat. Egy user egy allapról csak egy értesítést kap.
teszt=False #True esetén "dry" üzemmód, csak a képernyőre ír.
site=pywikibot.getSite()
BinBotEdit=0 #naplózáshoz

def CikketKeres(kat):
    lista = catlib.categoryAllElementsAPI(kat)
    for cim in lista[0]:
       if cim['ns'] == 2:
          if '/' in cim['title']:
             yield cim
          else:
             pass #Ez userlap, egyelőre kihagyjuk.

def redCategories(number = 500, repeat = False): #number mindegy, a lenti limit számít
        """Yield Pages from Special:WantedCategories.
        Félig elloptam a wikipedia.py-ból, félig átírtam, sok kísérlettel. 
        Hogy ez miért nincs ott megírva..."""
        path='/w/index.php?title=Special:WantedCategories&limit=2500&useskin=monobook'
        seen = set()
        while True:
            html = site.getUrl(path)
            entryR = re.compile(
                '<li><a href=".+?" title="(?P<title>.+?)">.+?</a>.+?</li>')
            for m in entryR.finditer(html):
                title = m.group('title')

                if title not in seen:
                    seen.add(title)
                    try:
                       hol=title.index(u'(megíratlan szócikk)') #Még piros
                       title=title.replace(u'(megíratlan szócikk)','')
                       #page = pywikibot.Page(site, title)
                       page = catlib.Category(site, title) #Ez való a kategóriákhoz
                       yield page
                    except ValueError:
                       pass #Ez a kategória már elkékült
            if not repeat:
                break
        """
         Így néz ki sima printtel:
         [[Kategória:Neurotoxins (megíratlan szócikk)]] (piros)
         [[Kategória:Kvantummechanika]]                 (kék)
         [[Kategória:Finn nyelv (megíratlan szócikk)]]
        """

def NowikibeTesz(allapcim,kategoriacim):
          global allapok, BinBotEdit #A hívások között maradjon meg
          pywikibot.output(u'Allap: %s, %s' %(allapcim,kategoriacim))
          keres=u'[[%s]]' % kategoriacim
          KatCimNevterNelkul=kategoriacim[kategoriacim.find(':')+1:]
          rekeres=re.compile(ur'(\[\[(Kategória|Category):%s(\|.*)?\]\])' % re.escape(KatCimNevterNelkul))
          csere=r'<nowiki>\1</nowiki>'
          #Műszaki kocsmafal, 2010. szept. 7.
          allap=pywikibot.Page(site,allapcim)
          try:
             oldtext=allap.get()
          except:
             print u'Hát ilyen nincs, eltűnt a lap!'
             oldtext=''
          newtext=pywikibot.replaceExcept(oldtext,rekeres,csere,['nowiki'],caseInsensitive=True)
          pywikibot.showDiff(oldtext, newtext)
          #Tesztelve: Kategória/Category, és van/nincs |... a ]] előtt.
          success=False #A mentés sikerét jelzi
          if oldtext == newtext:
             pywikibot.output(u'Nem találom a kategóriát! Vagy sablon csinálta, vagy rossz a keresőkifejezés!')
             RemoveFromList(allapcim,kategoriacim, sablon=True) #Megpróbálunk megjegyzést írni a listába
          elif not teszt:
             try:
                allap.put(newtext,u"Piros kategória nowikizése bottal")
                success=True
             except:
                pywikibot.output(u'Nem sikerült a mentés: %s.' % allapcim)
          else:
                pywikibot.output(u'\03{lightred}Tesztüzem, az allapot nem mentettem: %s.\03{default}\n' % allapcim)
                success=True #A további szimulációhoz
          if success:
                BinBotEdit+=1
                if allapcim not in allapok:
                   UsernekUzen(allapcim,kategoriacim)
                else:
                   pywikibot.output(u'Erről az alapról már küldtünk értesítést egy másik kategória kapcsán.')
                allapok.add(allapcim) #Egy allapról csak egy értesítést küldünk
                RemoveFromList(allapcim,kategoriacim)

def UzenetSzovege(allapneve):
    s=u'\n\n== Allap módosítása ==\n'
    s+=u'Szia! A [[%s]] allapodon a bot egy vagy több nem létező kategóriát talált. ' % allapneve
    s+=u'Utólagos engedelmeddel nowikibe tettem, hogy ne zavarja a kategóriarendszer '
    s+=u'karbantartását. (Lásd még ['
    s+=u'http://hu.wikipedia.org/w/index.php?title=Wikip%C3%A9dia:Kocsmafal_'
    s+=u'%28egy%C3%A9b%29&oldid=8395515#Piros_kateg.C3.B3ri.C3.A1k_nowikiz.C3.A9se_szerkeszt.C5.91i_allapon'
    s+=u' itt].) ~~~~\n'
    return(s)

def UsernekUzen(allapcim,kategoriacim):
          global BinBotEdit
          userlap=allapcim
          while '/' in userlap:
             userlap=userlap[:userlap.find('/')]
          print userlap
          vitalap=pywikibot.Page(site,userlap)
          vitalap=vitalap.toggleTalkPage()
          print vitalap.aslink()
          #Na és ha átirányította?
          if vitalap.isRedirectPage():
             ujvitalap=vitalap.getRedirectTarget()
             if ujvitalap.namespace()==3 and not ujvitalap.isRedirectPage():
                vitalap=ujvitalap
                print vitalap.aslink()
             else: #Hibás átirányítás
                pywikibot.output(u'\03{lightpurple}Hibásan átirányított vitalap, nem tudok üzenni.\03{default}')
                return
          if vitalap.botMayEdit('user:BinBott'):
             comment=u'Értesítés bottal végzett allapszerkesztésről'
             try:
                text=vitalap.get()
             except:
                text=''
                print u"\a\a\aNem sikerült betölteni a vitalapot, ellenőrizd!"
             #TODO: rendesen megkivételezni, néha előfordul betöltési hiba
             #létező lapnál. Addig figyelni kell, hogy ne töröljön véletlenül vitalapot.
             text+=UzenetSzovege(allapcim)
             #pywikibot.output(text) #Teljes vitalap képernyőre, csak debug, lassít.
             if not teszt:
                try:
                   vitalap.put(text,comment,minorEdit=False)
                   BinBotEdit+=1
                except:
                   pywikibot.output(u'Nem sikerült a mentés: %s.' % vitalap.title())
             else:
                pywikibot.output(u'\03{lightred}Tesztüzem, a vitalapot nem mentettem: %s.\03{default}\n' % vitalap.title())
                BinBotEdit+=1 #Szimuláció
          else:
             pywikibot.output(u'A felhasználó kizárta a botot a vitalapról, nem kap értesítést.')

def RemoveFromList(allapcim,kategoriacim,sablon=False):
    #sablon jelentése: True, ha nem találtuk a lapon a kategóriát, talán sablon csinálta.
    global BinBotEdit
    hely=u'Wikipédia:Nem létező kategóriák'
    oldal=pywikibot.Page(site,hely)
    if sablon:
       comment=u'A [[%s]] lapon nem találtam a [[%s]] kategóriát. Kategorizáló sablon tán?' % (allapcim,kategoriacim)
    else:
       comment=u'[[%s]] kihúzása [[%s]] alól bottal (ellenőrizendő)' % (allapcim,kategoriacim)
    try:
       oldtext=oldal.get()
    except:
       pywikibot.output(u'A Wikipédia:Nem létező kategóriák betöltése sikertelen, nem tudom kihúzni\n az allapot.')
       return
    newtext=''
    keres=False #Igaz lesz, ha megtaláltuk a kategóriát, és keressük az allap címét.
    oldtextsorai=oldtext.splitlines(1)
    for sor in oldtextsorai:
       s='*[[:'+kategoriacim
       #Itt van egy kis bug, ha "xyz" a kat. neve, és van egy "xyzzz" is, akkor kétszer írja fel.
       if s in sor:
          keres=True
          pywikibot.output(sor)
       elif sor.startswith(u'*[[:Kategória')==1: 
          keres=False
       if keres: #Most vagyunk a kategória alatt, listázva van-e a szerk. allap?
          mitkeres='**[[%s]]' % allapcim
          if mitkeres in sor:
             pywikibot.output(u'Régi szöveg: '+sor) #%s helyettesítésre kódolási hibát ad
             mitkeres=mitkeres[2:] #Már nem kell a csillag.
             if sablon:
                csere=mitkeres+u' (Bot: nincs meg a kategória, lehet, hogy egy sablon illesztette be.)'
             else:
                csere='<s>'+mitkeres+'</s>'
             #debug only
             #print mitkeres
             #print csere
             #sor.replace(mitkeres,csere) #Ez valamiért nem cseréli ki! :-((
             holvan=sor.find(mitkeres)
             sor=sor[:holvan]+csere+sor[holvan+len(mitkeres):]
             #pywikibot.output(u'Új szöveg: '+sor) #debug only
       newtext+=sor
    pywikibot.showDiff(oldtext,newtext)
    pywikibot.output(comment)
    success=False #A mentés sikerét jelzi
    if oldtext == newtext:
             pywikibot.output(u'A tételt nem találtam a %s lapon.' % hely)
    elif not teszt:
             try:
                oldal.put(newtext,comment)
                success=True
             except:
                pywikibot.output(u'Nem sikerült a mentés: %s.' % hely)
    else:
                pywikibot.output(u'\03{lightred}Tesztüzem, a %s lapot nem mentettem.\03{default}\n' % hely)
                success=True #A további szimulációhoz
    if success:
                BinBotEdit+=1
    #TODO: rendesen megkivételezni, szerkesztési ütközést vizsgálni

def naplozas():
   s=u'Wikipédia:Kocsmafal (egyéb)' #Majd archívot ide!
   s+=u'#Piros kategóriák nowikizése szerkesztői allapon'
   stat = {'fix':'','modm':0,'moda':BinBotEdit,'not':0,'skip':0,'err': 0,}
   naplo=binbotutils.munkanaplo()
   naplo.run(u'Nem létező kategóriák nowikizése',s,None,u'Szerkesztő:BinBot/piroskat-userallap.py', stat, teszt)
   #A teszt megfelel a munkanapló screen paraméterének, csak a képernyőre ír.

if __name__ == '__main__':
   if teszt:
      s=u'Tesztüzem, semmit nem mentünk. Kikapcsolás a script elején.'
   else:
      s=u'Éles üzem,mindent menteni fogunk!'
   pywikibot.output(u'\03{lightred}%s\03{default}' % s)
   try:
      for piros in redCategories():
         for allapneve in CikketKeres(piros.title()):
             NowikibeTesz(allapneve['title'], piros.title())
   finally:
      naplozas() #Ctrl C vagy más gond esetére