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

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright 2018 Jonathan Golder <>
# 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
# 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(
# 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`
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(
# To write "absent" states to db
# Update page content
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 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 \
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
@type links ( str, list(str*) )
@returns Formatet row text to add to page_content
@rtype str
return jogobot.config["red.missingnotice"]["row_format"].format(
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 )
def get_categorized_articles( cls ):
Queries all articles containing the notice based on category set by
notice template. Category can be configured in
@returns List of all articles containing notice
@rtype list
# construct connection url for sqlalchemy
url = URL( "mysql+pymysql",
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 ]