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专题/成员', 15)
---
Wikipedia:云南专题
last updated page in wikiproject: ('Wikipedia:云南专题/历史任务组/古人类至青铜文明小组', 45)
---
Wikipedia:传统百科全书条目专题
last updated page in wikiproject: ('Wikipedia:传统百科全书条目专题/汉英中兽医辞典', 5)
---
Wikipedia:佛羅里達州專題
last updated page in wikiproject: ('Wikipedia:佛羅里達州專題', 48)
---
Wikipedia:加利福尼亞州專題
last updated page in wikiproject: ('Wikipedia:加利福尼亞州專題', 101)
已标记为'''半活跃'''维基专题,最新页面[[Wikipedia:加利福尼亞州專題]]于 3月11天 前编辑。
*** 
--- 
***************
*** 7,12 ****
--- 7,19 ----
  状  态  |+ 1+ =+ s+ e+ m+ i+ -  a  c  t***************
*** 14,25 ****
--- 21,36 ----
  v  e  |+ 2+ =  W  P  :  C  A  |+ 3+ =  W  P  :
Page [[Wikipedia:加利福尼亞州專題]] saved
---
Wikipedia:動畫專題
last updated page in wikiproject: ('Wikipedia talk:動畫專題/My Little Pony', 16)
---
Wikipedia:南臺灣專題
last updated page in wikiproject: ('Wikipedia:南臺灣專題', 84)
---
Wikipedia:南非专题
last updated page in wikiproject: ('Wikipedia:南非专题', 85)
---
Wikipedia:台州专题
last updated page in wikiproject: ('Wikipedia:台州专题/公告栏', 1)
---
Wikipedia:吉林专题
last updated page in wikiproject: ('Wikipedia:吉林专题', 77)
---
Wikipedia:地震专题
last updated page in wikiproject: ('Wikipedia:地震专题/地震创作奖/评审委员会', 18)
---
Wikipedia:城市軌道交通專題
last updated page in wikiproject: ('Wikipedia talk:城市軌道交通專題/評級', 11)
---
Wikipedia:大韩民国专题
last updated page in wikiproject: ('Wikipedia:大韩民国专题', 94)
已标记为'''半活跃'''维基专题,最新页面[[Wikipedia:大韩民国专题]]于 3月4天 前编辑。
*** 
--- 
***************
*** 7,12 ****
--- 7,19 ----
  状  态  |+ 1+ =+ s+ e+ m+ i+ -  a  c  t***************
*** 101,106 ****
--- 108,115 ----
  p  x  |+ 2+ =  W  P  :***************
*** 108,113 ****
--- 117,124 ----
  O  K  |+ 3+ =  W  P  :
Page [[Wikipedia:大韩民国专题]] saved
---
Wikipedia:巴士專題
last updated page in wikiproject: ('Wikipedia:巴士專題', 101)
已标记为'''半活跃'''维基专题,最新页面[[Wikipedia:巴士專題]]于 3月11天 前编辑。
*** 
--- 
***************
*** 160,165 ****
--- 160,172 ----
  状  态  |+ 1+ =+ s+ e+ m+ i+ -  a  c  t***************
*** 213,218 ****
--- 220,227 ----
  ]  ]  |+ 2+ =  W  P  :
Sleeping for 5.4 seconds, 2019-07-23 17:11:58
Page [[Wikipedia:巴士專題]] saved
---
Wikipedia:库尔德专题
last updated page in wikiproject: ('Wikipedia:库尔德专题', 1)
---
Wikipedia:康乃狄克州專題
last updated page in wikiproject: ('Wikipedia:康乃狄克州專題', 84)
---
Wikipedia:新加坡专题
last updated page in wikiproject: ('Wikipedia:新加坡专题', 3)
---
Wikipedia:朝鮮半島專題
last updated page in wikiproject: ('Wikipedia:朝鮮半島專題', 94)
已标记为'''半活跃'''维基专题,最新页面[[Wikipedia:朝鮮半島專題]]于 3月4天 前编辑。
*** 
--- 
***************
*** 7,12 ****
--- 7,19 ----
  状  态  |+ 1+ =+ s+ e+ m+ i+ -  a  c  t
Page [[Wikipedia:朝鮮半島專題]] saved
---
Wikipedia:桥梁专题
last updated page in wikiproject: ('Wikipedia:桥梁专题/过往任务存档', 24)
---
Wikipedia:模仿专题
last updated page in wikiproject: ('Wikipedia:模仿专题', 13)
---
Wikipedia:沈阳专题
last updated page in wikiproject: ('Wikipedia:沈阳专题', 1)
---
Wikipedia:浙江专题
last updated page in wikiproject: ('Wikipedia:浙江专题', 11)
---
Wikipedia:热带气旋专题
last updated page in wikiproject: ('Wikipedia:热带气旋专题/动态', 86)
---
Wikipedia:特拉華州專題
last updated page in wikiproject: ('Wikipedia:特拉華州專題', 73)
---
Wikipedia:电子游戏专题
last updated page in wikiproject: ('Wikipedia:电子游戏专题/新进条目', 0)
---
Wikipedia:电脑和信息技术专题
last updated page in wikiproject: ('Wikipedia:电脑和信息技术专题', 26)
---
Wikipedia:科羅拉多州專題
last updated page in wikiproject: ('Wikipedia:科羅拉多州專題', 109)
已标记为'''半活跃'''维基专题,最新页面[[Wikipedia:科羅拉多州專題]]于 3月19天 前编辑。
*** 
--- 
***************
*** 7,12 ****
--- 7,19 ----
  状  态  |+ 1+ =+ s+ e+ m+ i+ -  a  c  t***************
*** 14,19 ****
--- 21,28 ----
  v  e  |+ 2+ =  W  P  :
Page [[Wikipedia:科羅拉多州專題]] saved
---
Wikipedia:維基百科幽默專題/主頁
last updated page in wikiproject: ('Wikipedia:維基百科幽默專題/主頁', 48)
---
Wikipedia:联合国开放获取文本
last updated page in wikiproject: ('Wikipedia:联合国开放获取文本', 85)
---
Wikipedia:臺灣專題
last updated page in wikiproject: ('Wikipedia:臺灣專題/狀態圖表', 72)
---
Wikipedia:船舶专题
last updated page in wikiproject: ('Wikipedia:船舶专题', 5)
已标记为'''活跃'''维基专题,最新页面[[Wikipedia:船舶专题]]于 5天 前编辑。
*** 
--- 
***************
*** 1,7 ****
--- 1,20 ----
  {  {+ 维+ 基  专  题+ 状+ 态+ |+ 1+ =+ a+ c+ t+ i+ v+ e  }  }  
Page [[Wikipedia:船舶专题]] saved
---
Wikipedia:语言专题
last updated page in wikiproject: ('Wikipedia:语言专题', 56)
---
Wikipedia:语言学专题
last updated page in wikiproject: ('Wikipedia:语言学专题', 43)
---
Wikipedia:軍事專題
last updated page in wikiproject: ('Wikipedia:軍事專題/參與者列表/名單', 110)
已标记为'''半活跃'''维基专题,最新页面[[Wikipedia:軍事專題/參與者列表/名單]]于 3月20天 前编辑。
*** 
--- 
***************
*** 6,22 ****
  题  状  态- 
  |  1  =  a  c  t  i  v  e- 
  }  }  
--- 6,25 ----
  题  状  态  |  1  =+ s+ e+ m+ i+ -  a  c  t  i  v  e  }  }  
Page [[Wikipedia:軍事專題]] saved
---
Wikipedia:鐵道專題
last updated page in wikiproject: ('Wikipedia talk:鐵道專題', 48)
---
Wikipedia:钱币学专题
last updated page in wikiproject: ('Wikipedia:钱币学专题/优良条目', 46)
---
Wikipedia:電子遊戲專題/世嘉
last updated page in wikiproject: ('Wikipedia:電子遊戲專題/世嘉/左面版', 7)
---
Wikipedia:首页的缺失条目专题
last updated page in wikiproject: ('Wikipedia:首页的缺失条目专题', 78)

Checked page 38