import pywikibot
import sys
from difflib import context_diff
from pywikibot import pagegenerators, Timestamp, textlib
from pywikibot.logging import stdout, warning, error, log, debug, error
import datetime

site = pywikibot.Site('zh', 'wikipedia')
ensite = pywikibot.Site('en', 'wikipedia')
repo = site.data_repository()

#generator config.
cat = pywikibot.Category(site,'Category:活跃维基专题')
gen = pagegenerators.CategorizedPageGenerator(cat)

#config conversion english to zh
status2zh = {
    "semi-active": "半活跃",
    "defunct": "废弃",
    "inactive": "不活跃",
    "active": "活跃"
}
    
#reset count to zero
pagelimit = 10 #max to update
update=True #should update page

#util: conversion from days to natural duration.
def natural_interval(daysAgo):
        yearsAgo = daysAgo // 365
        monthsAgo = (daysAgo - yearsAgo*365) // 30
        daysRemain= daysAgo-monthsAgo*30-yearsAgo*365
        rez = ""
        if(yearsAgo>0):
            rez += f"{yearsAgo}年"
        if(monthsAgo>0):
            rez += f"{monthsAgo}月"
        if(daysRemain>0):
            rez += f"{daysRemain}天"
        if(rez==""):
            return "0天"
        return rez
    
#config: edit days ago to status.
def determine_status(daysAgo):
    status = "active"
    if(daysAgo > 90):
        status = "semi-active"
    if(daysAgo > 200):
        status = "inactive"
    if(daysAgo > 700):
        status = "defunct"
    return status

#util: conditionals if the revision should be ignored
def is_bot_edit(revision):
    return not revision.user or site.isBot(revision.user)

def is_blacklisted_edit(revision):
    return revision.user=="Vizbot"

def is_revision_revert(revision):
    comment = revision.comment
    return "撤销" in comment or "回退" in comment

def acceptable_revision(revision):
#     print(is_bot_edit(revision), is_revision_revert(revision), is_blacklisted_edit(revision))
    return not is_bot_edit(revision) and not is_revision_revert(revision) and not is_blacklisted_edit(revision)

def last_acceptable_revision(page):
    for entry in page.revisions():
        if acceptable_revision(entry):
            return entry
#end util conditionals
    
#latest acceptable revision time.
def last_revision_ago(page):
    try:
        title = page.title()
        nowtimestamp = pywikibot.site.APISite.server_time(site)
        timestamp = last_acceptable_revision(page).timestamp
        timediff = nowtimestamp - timestamp
#         stdout(f"find {page.title()} last updated {timediff.days} days ago")
        return (title, timediff.days)
    except:
        return None

#combined latest revision time of a page
def all_subpages_revision_ago(page):
    stdout("---")
    stdout(page.title())
    
    subpages = pagegenerators.PrefixingPageGenerator(prefix = page.title())
    withTalkpages = pagegenerators.PageWithTalkPageGenerator(subpages)
    
    latest_revisions_ago = (t for t in map(last_revision_ago, withTalkpages) if t is not None)
    result = min(list(latest_revisions_ago), key = lambda t: t[1])
    stdout(f"last updated page in wikiproject: {result}")
    return result
 
#replace status according to func.
def replace_status(page, status):
    nextstr = page.text
    templates = textlib.extract_templates_and_params(nextstr, strip=True)
    builder = textlib._MultiTemplateMatchBuilder(site)
    template_regexes = [builder.pattern(i) for i in ("专题", "專題", "WikiProject status", "维基专题状态")]

    for template in templates:
        (tname, tpars) = template
#         log(f"found {template}")
        if tname in ("WikiProject status", "专题", "專題"):
            tname = "维基专题状态"
#         stdout(f"found template {tname}")
        if tname == "维基专题状态":
            if '1' not in tpars or tpars['1'] != status:
                tpars['1'] = status
                tpars.move_to_end('1', last=False)
                glued = textlib.glue_template_and_params((tname, tpars))
                glued = ''.join(glued.split('\n'))
                for template_regex in template_regexes:
                    nextstr = textlib.replaceExcept(nextstr, template_regex, glued, [], count=1)
            break
    return nextstr

def update_page(page, nextstr, saveMessage):
    diff = list(context_diff(page.text, nextstr))
    if (len(diff)>0):
        stdout(saveMessage)
        for line in diff:
            sys.stdout.write(line)
        if(update==True):
            page.text=nextstr
            page.save(saveMessage)
        else:
            print("test mode, change not saved.")
        return True
    return False

def update_page_status(page):
    (latestPage, daysAgo) = all_subpages_revision_ago(page)
    status=determine_status(daysAgo)
    nextstr = replace_status(page, status)
    a = "\'"
    saveMessage=f"已标记为\'\'\'{status2zh[status]}\'\'\'维基专题,最新页面[[{latestPage}]]于 {natural_interval(daysAgo)} 前编辑。"
    result = update_page(page, nextstr, saveMessage)
 
#main to iterate pages.
def main():
    count=0
    checked_page = 0
    for page in gen:
        checked_page+=1
        if (count >= pagelimit):
            stdout(f"已更新{count}页,现在退出...")
            break
        result=update_page_status(page)
        if(result):
            count +=1
    print(f"\nChecked page {checked_page}")
    
main()
---
Wikipedia:ACG专题
last updated page in wikiproject: ('Wikipedia:ACG专题', 46)
---
Wikipedia:云南专题
last updated page in wikiproject: ('Wikipedia:云南专题/历史任务组/古人类至青铜文明小组', 5)
---
Wikipedia:传统百科全书条目专题
 
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-5-acb40142f1ca> in <module>
      1 
----> 2 fxxx = f"维基专题状态已标记为{a}"
      3 print(fxxx)

NameError: name 'a' is not defined