You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
201 lines
6.1 KiB
201 lines
6.1 KiB
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
#
|
|
# missingnotice.py
|
|
#
|
|
# Copyright 2018 Jonathan Golder <jonathan@golderweb.de>
|
|
#
|
|
# This program is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
# MA 02110-1301, USA.
|
|
#
|
|
#
|
|
|
|
from sqlalchemy import create_engine
|
|
from sqlalchemy.engine.url import URL
|
|
|
|
import pywikibot
|
|
|
|
import jogobot
|
|
|
|
from lib.redfam import RedFamWorker
|
|
|
|
|
|
class MissingNoticeBot(pywikibot.bot.Bot):
|
|
"""
|
|
"""
|
|
|
|
# MySQL-query to get articles with notice
|
|
cat_article_query = """
|
|
SELECT `page_title`
|
|
FROM `categorylinks`
|
|
JOIN `category`
|
|
ON `cl_to` = `cat_title`
|
|
AND `cat_title` LIKE "{cat}\_%%"
|
|
JOIN `page`
|
|
ON `cl_from` = `page_id`
|
|
""".format(cat=jogobot.config["red.missingnotice"]["article_category"])
|
|
|
|
def __init__( self, genFactory, **kwargs ):
|
|
|
|
self.categorized_articles = list()
|
|
self.page_content = list()
|
|
|
|
super(type(self), self).__init__(**kwargs)
|
|
|
|
def run( self ):
|
|
# query articles containing notice
|
|
self.categorized_articles = type(self).get_categorized_articles()
|
|
|
|
fam_counter = 0
|
|
|
|
# iterate open redfams
|
|
for redfam in RedFamWorker.gen_open():
|
|
fam_counter += 1
|
|
links = self.treat_open_redfam(redfam)
|
|
|
|
if links:
|
|
self.page_content.append( self.format_row( links ) )
|
|
|
|
if (fam_counter % 50) == 0:
|
|
jogobot.output( "Processed {n:d} open RedFams".format(
|
|
n=fam_counter))
|
|
|
|
else:
|
|
# To write "absent" states to db
|
|
RedFamWorker.flush_db_cache()
|
|
|
|
# Update page content
|
|
self.update_page()
|
|
|
|
def treat_open_redfam( self, redfam ):
|
|
"""
|
|
Works on current open redfam
|
|
|
|
@param redfam Redfam to work on
|
|
@type redfam.RedFamWorker
|
|
|
|
@returns Tuple of disclink and list of articles missing notice or None
|
|
@rtype ( str, list(str*) ) or None
|
|
"""
|
|
|
|
# Check if related disc section exist
|
|
if not redfam.disc_section_exists():
|
|
return None
|
|
|
|
# Get links for articles without notice
|
|
links = self.treat_articles( redfam.article_generator(
|
|
filter_existing=True, filter_redirects=True ) )
|
|
|
|
# No articles without notice
|
|
if not links:
|
|
return None
|
|
|
|
return ( redfam.get_disc_link(as_link=True), links )
|
|
|
|
def treat_articles(self, articles):
|
|
"""
|
|
Iterates over given articles and checks weather them are included in
|
|
self.categorized_articles (contain the notice)
|
|
|
|
@param articles Articles to check
|
|
@type articles iterable of pywikibot.page() objects
|
|
|
|
@returns Possibly empty list of wikitext links ("[[article]]")
|
|
@rtype list
|
|
"""
|
|
links = list()
|
|
|
|
for article in articles:
|
|
|
|
if article.title(underscore=True, with_section=False ) not in \
|
|
self.categorized_articles:
|
|
|
|
links.append( article.title(as_link=True, textlink=True) )
|
|
|
|
return links
|
|
|
|
def format_row( self, links ):
|
|
"""
|
|
Formats row for output on wikipage
|
|
|
|
@param links Tuple of disc link and list of articles as returned by
|
|
self.treat_open_redfam()
|
|
@type links ( str, list(str*) )
|
|
|
|
@returns Formatet row text to add to page_content
|
|
@rtype str
|
|
"""
|
|
|
|
return jogobot.config["red.missingnotice"]["row_format"].format(
|
|
disc=links[0],
|
|
links=jogobot.config["red.missingnotice"]["link_sep"].join(
|
|
links[1] ) )
|
|
|
|
def update_page( self, wikipage=None):
|
|
"""
|
|
Handles the updating process of the wikipage
|
|
|
|
@param wikipage Wikipage to put text on, otherwise use configured page
|
|
@type wikipage str
|
|
"""
|
|
|
|
# if not given get wikipage from config
|
|
if not wikipage:
|
|
wikipage = jogobot.config["red.missingnotice"]["wikipage"]
|
|
|
|
# Create page object for wikipage
|
|
page = pywikibot.Page(pywikibot.Site(), wikipage)
|
|
|
|
# Define edit summary
|
|
summary = jogobot.config["red.missingnotice"]["edit_summary"]
|
|
|
|
# Make sure summary starts with "Bot:"
|
|
if not summary[:len("Bot:")] == "Bot:":
|
|
summary = "Bot: " + summary.strip()
|
|
|
|
# Concatenate new text
|
|
new_text = "\n".join(self.page_content)
|
|
|
|
# Save new text
|
|
self.userPut( page, page.text, new_text, summary=summary )
|
|
|
|
@classmethod
|
|
def get_categorized_articles( cls ):
|
|
"""
|
|
Queries all articles containing the notice based on category set by
|
|
notice template. Category can be configured in
|
|
jogobot.config["red.missingnotice"]["article_category"]
|
|
|
|
@returns List of all articles containing notice
|
|
@rtype list
|
|
"""
|
|
|
|
# construct connection url for sqlalchemy
|
|
url = URL( "mysql+pymysql",
|
|
username=pywikibot.config.db_username,
|
|
password=pywikibot.config.db_password,
|
|
host=jogobot.config["red.missingnotice"]["wikidb_host"],
|
|
port=jogobot.config["red.missingnotice"]["wikidb_port"],
|
|
database=jogobot.config["red.missingnotice"]["wikidb_name"],
|
|
query={'charset': 'utf8'} )
|
|
|
|
# create sqlalchemy engine
|
|
engine = create_engine(url, echo=False)
|
|
|
|
# fire the query to get articles with notice
|
|
result = engine.execute(cls.cat_article_query)
|
|
|
|
# return list with articles with notice
|
|
return [ row['page_title'].decode("utf-8") for row in result ]
|
|
|