Пример #1
0
    def display_references(self):
        """
        Display pages which links the current page, sorted per namespace.

        Number of pages to display per namespace is provided by:
        - self.getOption('isorphan')
        """
        refs = self.current_page.ref_table
        if refs:
            total = sum(len(v) for v in refs.values())
            pywikibot.warning('There are %d pages who link to %s.'
                              % (total, self.current_page))
        else:
            return

        show_n_pages = self.getOption('isorphan')
        width = len(max((ns.canonical_prefix() for ns in refs), key=len))
        for ns in sorted(refs):
            n_pages_in_ns = len(refs[ns])
            plural = '' if n_pages_in_ns == 1 else 's'
            ns_name = ns.canonical_prefix() if ns != ns.MAIN else 'Main:'
            ns_id = '[{0}]'.format(ns.id)
            pywikibot.output(
                '    {0!s:<{width}} {1:>6} {2:>10} page{pl}'.format(
                    ns_name, ns_id, n_pages_in_ns, width=width, pl=plural))
            if show_n_pages:  # do not show marker if 0 pages are requested.
                for page in islice_with_ellipsis(refs[ns], show_n_pages):
                    pywikibot.output('      {0!s}'.format(page.title()))
Пример #2
0
 def run(self):
     for page in self.generator:
         if self.getOption('purge'):
             pywikibot.output(u'Page %s%s purged'
                              % (page.title(asLink=True),
                                 "" if page.purge() else " not"))
             continue
         try:
             # get the page, and save it using the unmodified text.
             # whether or not getting a redirect throws an exception
             # depends on the variable self.touch_redirects.
             page.get(get_redirect=self.getOption('redir'))
             page.save("Pywikibot touch script")
         except pywikibot.NoPage:
             pywikibot.error(u"Page %s does not exist."
                             % page.title(asLink=True))
         except pywikibot.IsRedirectPage:
             pywikibot.warning(u"Page %s is a redirect; skipping."
                               % page.title(asLink=True))
         except pywikibot.LockedPage:
             pywikibot.error(u"Page %s is locked."
                             % page.title(asLink=True))
         except pywikibot.PageNotSaved:
             pywikibot.error(u"Page %s not saved."
                             % page.title(asLink=True))
    def load_values(self, replacements):
        """
        Load the dataset specific replacements into self.variables.

        Does not accept variables other than those in self.variables.
        Automatically handles lat_int and lon_int.

        @param replacements: Dictionary with target variable as key and
            replacement SQL a value. e.g. {"adm0": "'ad'", "lat": "`lat`"}
        """
        required_fields = ('country', 'lang')
        if not all(required in replacements for required in required_fields):
            raise ValueError(
                "All of the required fields '{}' must be replaced".format(
                    "','".join(required_fields)))

        if 'lat' not in replacements:
            self.variables['lat_int'] = None
        if 'lon' not in replacements:
            self.variables['lon_int'] = None

        for variable in self.variables:
            if variable in replacements:
                value = replacements[variable]
                if not isinstance(value, VariableType):
                    raise ValueError(
                        "All variables must be encoded through VariableType, "
                        "'{}' was not".format(variable))
                self.variables[variable] = value.format()

        for target in replacements:
            if target not in self.variables:
                pywikibot.warning(
                    "Unrecognized variable in {table}: {variable}".format(
                        table=self.table, variable=target))
Пример #4
0
    def treat_page(self):
        page = self.current_page
        text = page.text
        done_replacements = []
        quickly = self.getOption('quick') is True
        start = time.clock()
        if self.own_generator:
            text = self.currentrule.apply(page.text, done_replacements)
            if page.text == text:
                if quickly:
                    pywikibot.output('Typo not found, not fixing another typos '
                                     'in quick mode')
                    return
            else:
                self.replaced += 1

        for rule in self.typoRules:
            if self.own_generator and rule == self.currentrule: # __eq__
                continue
            if rule.matches(page.title()):
                continue
            if quickly and rule.needsDecision():
                continue

            text = rule.apply(text, done_replacements)
            stop = time.clock()
            if quickly and stop - start > 15:
                pywikibot.warning('Other typos exceeded 15s, skipping')
                break

        self.put_current(
            text, summary='oprava překlepů: %s' % ', '.join(done_replacements))
Пример #5
0
def main(*args):
    """
    Process command line arguments and invoke bot.

    If args is an empty list, sys.argv is used.

    @param args: command line arguments
    @type args: list of unicode
    """
    local_args = pywikibot.handle_args(args)
    start = None
    force = False

    # Parse command line arguments
    for arg in local_args:
        if arg.startswith('-start:'):
            start = arg[7:]
        elif arg == '-force':
            force = True
        else:
            pywikibot.warning(
                u'argument "%s" not understood; ignoring.' % arg)

    bot = StatesRedirectBot(start, force)
    bot.run()
def group_missing_commonscat_by_source(commonscats, withoutCommonscat,
                                       countryconfig):
    """Identify all unused images and group them by source page and id."""
    missing_commonscat = {}

    for catSortKey in sorted(commonscats.keys()):
        try:
            monumentId = common.get_id_from_sort_key(
                catSortKey, withoutCommonscat)
        except ValueError:
            pywikibot.warning(u'Got value error for {0}'.format(catSortKey))
            continue

        if monumentId in withoutCommonscat:
            try:
                source_link = common.get_source_link(
                    withoutCommonscat.get(monumentId),
                    countryconfig.get('type'))
                if source_link not in missing_commonscat:
                    missing_commonscat[source_link] = []
            except ValueError:
                pywikibot.warning(
                    u'Could not find source page for {0} ({1})'.format(
                        monumentId, withoutCommonscat.get(monumentId)))
                continue

            missing_commonscat[source_link].append(
                (commonscats.get(catSortKey), monumentId))

    return missing_commonscat
    def testApiMethods(self):
        """Test generic ApiSite methods"""

        self.assertType(mysite.logged_in(), bool)
        self.assertType(mysite.logged_in(True), bool)
        self.assertType(mysite.userinfo, dict)
        self.assertType(mysite.is_blocked(), bool)
        self.assertType(mysite.messages(), bool)
        self.assertType(mysite.has_right("edit"), bool)
        self.assertFalse(mysite.has_right("nonexistent_right"))
        self.assertType(mysite.has_group("bots"), bool)
        self.assertFalse(mysite.has_group("nonexistent_group"))
        try:
            self.assertType(mysite.is_blocked(True), bool)
            self.assertType(mysite.has_right("edit", True), bool)
            self.assertFalse(mysite.has_right("nonexistent_right", True))
            self.assertType(mysite.has_group("bots", True), bool)
            self.assertFalse(mysite.has_group("nonexistent_group", True))
        except pywikibot.NoUsername:
            pywikibot.warning(
             "Cannot test Site methods for sysop; no sysop account configured.")
        for msg in ("1movedto2", "about", "aboutpage", "aboutsite",
                    "accesskey-n-portal"):
            self.assertTrue(mysite.has_mediawiki_message(msg))
            self.assertType(mysite.mediawiki_message(msg), basestring)
        self.assertFalse(mysite.has_mediawiki_message("nosuchmessage"))
        self.assertRaises(KeyError, mysite.mediawiki_message, "nosuchmessage")
        self.assertType(mysite.getcurrenttimestamp(), basestring)
        self.assertType(mysite.siteinfo, dict)
        self.assertType(mysite.case(), basestring)
        ver = mysite.live_version()
        self.assertType(ver, tuple)
        self.assertTrue(all(isinstance(ver[i], int) for i in (0, 1)))
        self.assertType(ver[2], basestring)
Пример #8
0
    def saveToCache(self, q, data):
        """
        Save data from a query to a cache file, if enabled.

        No return value.
        """

        if self.cacheMaxAge <= 0:
            return

        # we have to use our own query string, as otherwise we may
        # be able to find the cache file again if there are e.g.
        # whitespace differences
        cacheFile = self.getCacheFilename(q)

        if os.path.exists(cacheFile) and not os.path.isfile(cacheFile):
            return

        if not os.path.exists(self.cacheDir):
            os.makedirs(self.cacheDir)

        with open(cacheFile, 'wb') as f:
            try:
                pickle.dump(data, f)
            except IOError:
                pywikibot.warning(u"Failed to write cache file %s" % cacheFile)
Пример #9
0
    def readFromCache(self, queryStr):
        """
        Load the query result from the cache, if possible.

        Returns None if the data is not there or if it is too old.
        """

        if self.cacheMaxAge <= 0:
            return None

        cacheFile = self.getCacheFilename(queryStr)

        if os.path.isfile(cacheFile):
            mtime = os.path.getmtime(cacheFile)
            now = time.time()

            if ((now - mtime) / 60) < self.cacheMaxAge:
                with open(cacheFile, 'rb') as f:
                    try:
                        data = pickle.load(f)
                    except pickle.UnpicklingError:
                        pywikibot.warning(u"Couldn't read cached data from %s"
                                            % cacheFile)
                        data = None

                return data

        return None
Пример #10
0
def main(*args):
    """
    Process command line arguments and invoke bot.

    If args is an empty list, sys.argv is used.

    @param args: command line arguments
    @type args: list of unicode
    """
    options = {}

    for arg in pywikibot.handle_args(args):
        if arg == '-replacealways':
            options['replace'] = True
            options['replacealways'] = True
        elif arg == '-hash':
            options['use_hash'] = True
        elif arg == '-autonomous':
            pywikibot.warning(u"The '-autonomous' argument is DEPRECATED,"
                              u" use '-always' instead.")
            options['always'] = True
        elif arg.startswith('-'):
            if arg[1:] in ('always', 'replace', 'replaceloose', 'replaceonly'):
                options[arg[1:]] = True

    bot = NowCommonsDeleteBot(**options)
    bot.run()
Пример #11
0
def getOpenStreetMap(latitude, longitude):
    """
    Get the result from https://nominatim.openstreetmap.org/reverse .

    @rtype: list of tuples
    """
    result = []
    gotInfo = False
    parameters = urlencode({'lat': latitude, 'lon': longitude, 'accept-language': 'en'})
    while not gotInfo:
        try:
            page = fetch('https://nominatim.openstreetmap.org/reverse?format=xml&%s' % parameters)
            et = xml.etree.ElementTree.fromstring(page.content)
            gotInfo = True
        except IOError:
            pywikibot.output(u'Got an IOError, let\'s try again')
            time.sleep(30)
        except socket.timeout:
            pywikibot.output(u'Got a timeout, let\'s try again')
            time.sleep(30)
    validParts = [u'hamlet', u'village', u'city', u'county', u'country']
    invalidParts = [u'path', u'road', u'suburb', u'state', u'country_code']
    addressparts = et.find('addressparts')

    for addresspart in addressparts.getchildren():
        if addresspart.tag in validParts:
            result.append(addresspart.text)
        elif addresspart.tag in invalidParts:
            pywikibot.output(u'Dropping %s, %s' % (addresspart.tag, addresspart.text))
        else:
            pywikibot.warning('%s, %s is not in addressparts lists'
                              % (addresspart.tag, addresspart.text))
    return result
Пример #12
0
def site_rc_listener(site, total=None):
    """Yield changes received from EventStream.

    @param site: the Pywikibot.Site object to yield live recent changes for
    @type site: Pywikibot.BaseSite
    @param total: the maximum number of changes to return
    @type total: int

    @return: pywikibot.comms.eventstream.rc_listener configured for given site
    """
    if isinstance(EventSource, Exception):
        warning('sseclient is required for EventStreams;\n'
                'install it with "pip install sseclient"\n')
        # fallback to old rcstream method
        # NOTE: this will be deprecated soon
        from pywikibot.comms.rcstream import rc_listener
        return rc_listener(
            wikihost=site.hostname(),
            rchost=site.rcstream_host(),
            rcport=site.rcstream_port(),
            rcpath=site.rcstream_path(),
            total=total,
        )

    stream = EventStreams(stream='recentchange', site=site)
    stream.set_maximum_items(total)
    stream.register_filter(server_name=site.hostname())
    return stream
Пример #13
0
 def setLinkDead(self, url, error, page, day):
     """Add the fact that the link was found dead to the .dat file."""
     self.semaphore.acquire()
     now = time.time()
     if url in self.historyDict:
         timeSinceFirstFound = now - self.historyDict[url][0][1]
         timeSinceLastFound = now - self.historyDict[url][-1][1]
         # if the last time we found this dead link is less than an hour
         # ago, we won't save it in the history this time.
         if timeSinceLastFound > 60 * 60:
             self.historyDict[url].append((page.title(), now, error))
         # if the first time we found this link longer than x day ago
         # (default is a week), it should probably be fixed or removed.
         # We'll list it in a file so that it can be removed manually.
         if timeSinceFirstFound > 60 * 60 * 24 * day:
             # search for archived page
             try:
                 archiveURL = get_archive_url(url)
             except Exception as e:
                 pywikibot.warning(
                     'get_closest_memento_url({0}) failed: {1}'.format(
                         url, e))
                 archiveURL = None
             if archiveURL is None:
                 archiveURL = weblib.getInternetArchiveURL(url)
             if archiveURL is None:
                 archiveURL = weblib.getWebCitationURL(url)
             self.log(url, error, page, archiveURL)
     else:
         self.historyDict[url] = [(page.title(), now, error)]
     self.semaphore.release()
Пример #14
0
    def read_file_content(self, file_url=None):
        """Return name of temp file in which remote file is saved."""
        if not file_url:
            file_url = self.url
            pywikibot.warning("file_url is not given. "
                              "Set to self.url by default.")
        pywikibot.output(u'Reading file %s' % file_url)
        resume = False
        rlen = 0
        _contents = None
        dt = 15
        uo = URLopener()
        retrieved = False

        while not retrieved:
            if resume:
                pywikibot.output(u"Resume download...")
                uo.addheader('Range', 'bytes=%s-' % rlen)

            infile = uo.open(file_url)

            if 'text/html' in infile.info().getheader('Content-Type'):
                pywikibot.output(u"Couldn't download the image: "
                                 "the requested URL was not found on server.")
                return

            content_len = infile.info().getheader('Content-Length')
            accept_ranges = infile.info().getheader('Accept-Ranges') == 'bytes'

            if resume:
                _contents += infile.read()
            else:
                _contents = infile.read()

            infile.close()
            retrieved = True

            if content_len:
                rlen = len(_contents)
                content_len = int(content_len)
                if rlen < content_len:
                    retrieved = False
                    pywikibot.output(
                        u"Connection closed at byte %s (%s left)"
                        % (rlen, content_len))
                    if accept_ranges and rlen > 0:
                        resume = True
                    pywikibot.output(u"Sleeping for %d seconds..." % dt)
                    time.sleep(dt)
                    if dt <= 60:
                        dt += 15
                    elif dt < 360:
                        dt += 60
            else:
                pywikibot.log(
                    u"WARNING: length check of retrieved data not possible.")
        handle, tempname = tempfile.mkstemp()
        with os.fdopen(handle, "wb") as t:
            t.write(_contents)
        return tempname
Пример #15
0
def modeletodic(modele):
    """ Transforme un chaine "modèle" en tableau
    convention : r[0] est le nom du modèle
    """
    r = {}
    m = RE_Modele.search(modele)
    if m:
        chaine = m.group(1).replace('\n', '')
        chaine = RE_Comment.sub(r'', chaine)
        chaine = RE_Pipe.sub(r'[[\2]]', chaine) #pour le split après
        pos = 0
        for l in chaine.split("|"):
            if pos == 0:
                r[0] = l.strip()
                pos += 1
            else:
                a = l.split("=")
                b = a[0].strip()
                if len(a) > 1:
                    r[b] = a[1].strip()
                else:
                    r[pos] = b
                    pos +=1
    else:
        pywikibot.warning("BeBot.modeletodic() ; il a été impossible de lire le modèle suivant\n%s" % modele)
    return r
Пример #16
0
    def readFromCache(self, queryStr):
        """
        Check if we have cached this data recently enough, read it
        if we have. Returns None if the data is not there or if it is
        too old
        """

        if self.cacheMaxAge <= 0:
            return None

        cacheFile = self.getCacheFilename(queryStr)

        if os.path.isfile(cacheFile):
            mtime = os.path.getmtime(cacheFile)
            now = time.time()

            if ((now - mtime) / 60) < self.cacheMaxAge:

                try:
                    data = pickle.load(open(cacheFile, 'r'))
                except pickle.UnpicklingError:
                    pywikibot.warning(u"Couldn't read cached data from %s"
                                        % cacheFile)
                    data = None

                return data

        return None
Пример #17
0
    def loadTypos(self):
        pywikibot.output('Loading typo rules')
        self.typoRules = []

        if self.typos_page_name is None:
            self.typos_page_name = 'Wikipedie:WPCleaner/Typo'
        typos_page = pywikibot.Page(self.site, self.typos_page_name)
        if not typos_page.exists():
            # todo: feedback
            return

        content = typos_page.get()
        load_all = self.load_all is True
        for template, fielddict in textlib.extract_templates_and_params(
            content, remove_disabled_parts=False, strip=False):
            if template.lower() == 'typo':
                try:
                    rule = TypoRule.newFromParameters(fielddict, self.site)
                except IncompleteTypoRuleException as exc:
                    pywikibot.warning(exc.message) # pwb.exception?
                except InvalidExpressionException as exc:
                    if 'fixed-width' not in exc.message:
                        pywikibot.warning('Invalid %s %s: %s' % (
                            exc.aspect, fielddict['1'], exc.message))
                else:
                    rule.id = self.top_id
                    self.top_id += 1
                    if load_all or not rule.needsDecision():
                        self.typoRules.append(rule)

        pywikibot.output('%s typo rules loaded' % len(self.typoRules))
        return self.typoRules
Пример #18
0
    def __init__(self, url, urlEncoding=None, description=u'',
                 useFilename=None, keepFilename=False,
                 verifyDescription=True, ignoreWarning=False,
                 targetSite=None, uploadByUrl=False, aborts=[], chunk_size=0):
        """
        Constructor.

        @param url: path to url or local file (deprecated), or list of urls or
            paths to local files.
        @type url: string (deprecated) or list
        @param description: Description of file for its page. If multiple files
            are uploading the same description is used for every file.
        @type description: string
        @param useFilename: Specify title of the file's page. If multiple
            files are uploading it asks to change the name for second, third,
            etc. files, otherwise the last file will overwrite the other.
        @type useFilename: string
        @param keepFilename: Set to True to keep original names of urls and
            files, otherwise it will ask to enter a name for each file.
        @type keepFilename: bool
        @param verifyDescription: Set to False to not proofread the description.
        @type verifyDescription: bool
        @param ignoreWarning: Set this to True to upload even if another file
            would be overwritten or another mistake would be risked. Set it to
            an array of warning codes to selectively ignore specific warnings.
        @type ignoreWarning: bool or list
        @param targetSite: Set the site to upload to. If target site is not
            given it's taken from user-config.py.
        @type targetSite: object
        @param aborts: List of the warning types to abort upload on. Set to True
            to abort on any warning.
        @type aborts: bool or list
        @param chunk_size: Upload the file in chunks (more overhead, but
            restartable) specified in bytes. If no value is specified the file
            will be uploaded as whole.
        @type chunk_size: integer

        @deprecated: Using upload_image() is deprecated, use upload_file() with
            file_url param instead

        """
        self.url = url
        if isinstance(self.url, basestring):
            pywikibot.warning("url as string is deprecated. "
                              "Use an iterable instead.")
        self.urlEncoding = urlEncoding
        self.description = description
        self.useFilename = useFilename
        self.keepFilename = keepFilename
        self.verifyDescription = verifyDescription
        self.ignoreWarning = ignoreWarning
        self.aborts = aborts
        self.chunk_size = chunk_size
        if config.upload_to_commons:
            self.targetSite = targetSite or pywikibot.Site('commons',
                                                           'commons')
        else:
            self.targetSite = targetSite or pywikibot.Site()
        self.targetSite.login()
        self.uploadByUrl = uploadByUrl
Пример #19
0
    def get_sd_template(self):
        """Look for speedy deletion template and return it.

        @return: A valid speedy deletion template.
        @rtype: str or None
        """
        if self.getOption('delete') and not self.site.logged_in(sysop=True):
            sd = self.getOption('sdtemplate')
            if not sd and i18n.twhas_key(self.site,
                                         'redirect-broken-redirect-template'):
                sd = i18n.twtranslate(self.site,
                                      'redirect-broken-redirect-template')
            # TODO: Add bot's signature if needed (Bug: T131517)

            # check whether template exists for this site
            title = None
            if sd:
                template = extract_templates_and_params_regex_simple(sd)
                if template:
                    title = template[0][0]
                    page = pywikibot.Page(self.site, title, ns=10)
                    if page.exists():
                        return sd
            pywikibot.warning(
                'No speedy deletion template {0}available.'
                ''.format('"{0}" '.format(title) if title else ''))
        return None
Пример #20
0
def main():
    always = False

    for arg in pywikibot.handleArgs():
        if arg == '-always':
            always = True

    mysite = pywikibot.Site()
    # If anything needs to be prepared, you can do it here
    template_image = i18n.translate(pywikibot.Site(),
                                    template_to_the_image)
    template_user = i18n.translate(pywikibot.Site(),
                                   template_to_the_user)
    except_text_translated = i18n.translate(pywikibot.Site(), except_text)
    if not(template_image and template_user and except_text_translated):
        pywikibot.warning(u'This script is not localized for %s site.' % mysite)
        return
    generator = pagegenerators.UnusedFilesGenerator()
    generator = pagegenerators.PreloadingGenerator(generator)
    for image in generator:
        if (except_text_translated.encode('utf-8')
                not in image.getImagePageHtml() and
                u'http://' not in image.text):
            pywikibot.output(u"\n\n>>> \03{lightpurple}%s\03{default} <<<"
                             % image.title())
            if template_image in image.text:
                pywikibot.output(u"%s done already"
                                 % image.title(asLink=True))
                continue
            appendtext(image, u"\n\n" + template_image, always)
            uploader = image.getFileVersionHistory().pop(0)['user']
            user = pywikibot.User(mysite, uploader)
            usertalkpage = user.getUserTalkPage()
            msg2uploader = template_user % {'title': image.title()}
            appendtext(usertalkpage, msg2uploader, always)
Пример #21
0
    def add_mbid_claim_to_item(self, item, mbid):
        """
        Adds a claim with pid `pid` with value `mbid` to `item` and call `donefunc`
        with `mbid` to signal the completion.

        :type pid: str
        :type mbid: str
        :type item: pywikibot.ItemPage
        """
        claim = wp.Claim(const.WIKIDATA_DATASITE, self.property_id)
        claim.setTarget(mbid)
        wp.debug(u"Adding property {pid}, value {mbid} to {title}".format
                 (pid=self.property_id, mbid=mbid, title=item.title()),
                 layer="")
        if wp.config.simulate:
            wp.output("Simulation, no property has been added")
            return
        try:
            item.addClaim(claim, True)
        except wp.UserBlocked as e:
            wp.error("I have been blocked")
            exit(1)
        except wp.Error as e:
            wp.warning(e)
            return
        else:
            wp.debug("Adding the source Claim", layer="")
            claim.addSources([const.MUSICBRAINZ_CLAIM, const.RETRIEVED_CLAIM], bot=True)
            self.donefunc(mbid)
 def treat_page(self):
     """Process one page."""
     page = self.current_page
     text = page.get()
     for url in weblinksIn(text):
         ignoreUrl = False
         for ignoreR in ignorelist:
             if ignoreR.match(url):
                 ignoreUrl = True
         if not ignoreUrl:
             # Limit the number of threads started at the same time. Each
             # thread will check one page, then die.
             while threading.activeCount() >= config.max_external_links:
                 time.sleep(config.retry_wait)
             thread = LinkCheckThread(page, url, self.history,
                                      self.HTTPignore, self.day)
             # thread dies when program terminates
             thread.setDaemon(True)
             try:
                 thread.start()
             except threading.ThreadError:
                 pywikibot.warning(
                     "Can't start a new thread.\nPlease decrease "
                     "max_external_links in your user-config.py or use\n"
                     "'-max_external_links:' option with a smaller value. "
                     "Default is 50.")
                 raise
Пример #23
0
def main(*args):
    generator = None
    local_args = pywikibot.handle_args(args)
    site = pywikibot.Site()
    if str(site) != "commons:commons":
        pywikibot.warning("The script has not been tested on sites other that "
                          "commons:commons.")

    gen_factory = pagegenerators.GeneratorFactory(site)
    for local_arg in local_args:
        if gen_factory.handleArg(local_arg):
            continue
        arg, sep, value = local_arg.partition(':')
        if arg in ('-showcats',):
            options[arg[1:]] = True
        else:
            raise ValueError('Unknown argument: ' + local_arg)

    generator = gen_factory.getCombinedGenerator(gen=generator)
    if not generator:
        pywikibot.bot.suggest_help(missing_generator=True)
    else:
        pregenerator = pagegenerators.PreloadingGenerator(generator)
        for i, page in enumerate(pregenerator):
            if page.exists():
                log = handle_page(page)
                pywikibot.output('\n'.join(log))
                pywikibot.output("")
Пример #24
0
 def treat_page(self):
     commons = pywikibot.Site(code = u'commons', fam = u'commons')
     today = datetime.date.today()
     # fileTemplate = pywikibot.Page(commons, u'Template:Potd filename')
     # captionTemplate = pywikibot.Page(commons, u'Template:Potd description') # (Potd page, POTD description)
     filePage = pywikibot.Page(commons, u'Template:Potd/%s' % today.isoformat())
     file = get_template_parameter_value(filePage, u'Potd filename', u'1')
     # TODO: use languages instead of lang
     captionPage = pywikibot.Page(commons, u'Template:Potd/%s (%s)'
         % (today.isoformat(), self.current_page.site.lang))
     if self.current_page.site.lang != u'en' and not captionPage.exists():
         pywikibot.warning(u'%s does not exist' % captionPage.title(asLink=True))
         # try en instead
         captionPage = pywikibot.Page(commons, u'Template:Potd/%s (en)' % today.isoformat())
     caption = get_template_parameter_value(captionPage, u'Potd description', u'1')
     # TODO: Complete caption parsing to fix links (if not an interwiki then make it an interwiki to Commons)
     caption = re.sub(r"\[\[([^:])", r"[[:\1", caption, flags=re.UNICODE) # Force links to start with ':'
     caption = re.sub(r"\[\[(:Category:)", r"[[:c\1", caption, flags=re.UNICODE | re.IGNORECASE) # Make category links interwiki links
     # TODO: Use [[d:Q4608595]] to get the local {{Documentation}}
     doc = u'Documentation'
     if file != u'':
         summary = u'Updating Commons picture of the day'
         if caption != u'':
             summary = summary + u', [[:c:%s|caption attribution]]' % captionPage.title()
         else:
             summary = summary + u', failed to parse caption'
             pywikibot.error(u'Failed to parse parameter 1 from {{Potd description}} on %s'
                 % captionPage.title(asLink=True))
         self.put_current(u'<includeonly>{{#switch:{{{1|}}}|caption=%s|#default=%s}}</includeonly><noinclude>\n{{%s}}</noinclude>'
             % (caption, file, doc), summary=summary, minor=False)
     else:
         pywikibot.error(u'Failed to parse parameter 1 from {{Potd filename}} on %s'
             % filePage.title(asLink=True))
Пример #25
0
    def __init__(self, site, name, parameters, aliases=None, subst=False):
        self._name = name
        if not aliases:
            aliases = []
        elif not subst:
            aliases = list(aliases) + [name]
        else:
            name = 'subst:' + name
        if parameters:
            name += '|' + parameters
        self.template = '{{' + name + '}}'
        self._names = frozenset(aliases)

        template_ns = site.namespaces[10]
        # TODO: Add redirects to self.names too
        if not pywikibot.Page(site, self._name, template_ns.id).exists():
            raise ValueError('Orphan template "{0}" does not exist on '
                             '"{1}".'.format(self._name, site))
        for name in self._names:
            if not pywikibot.Page(site, name, template_ns.id).exists():
                pywikibot.warning('Orphan template alias "{0}" does not exist '
                                  'on "{1}"'.format(name, site))
        self.regex = re.compile(
            r'\{\{(?:' + ':|'.join(template_ns) + '|)(' +
            '|'.join(re.escape(name) for name in self._names) +
            r')[\|\}]', re.I)
Пример #26
0
    def check_user_exists(self):
        """
        Check that the username exists on the site.

        @see: U{https://www.mediawiki.org/wiki/API:Users}

        @raises NoUsername: Username doesn't exist in user list.
        """
        # convert any Special:BotPassword usernames to main account equivalent
        main_username = self.username
        if '@' in self.username:
            warn(
                'When using BotPasswords it is recommended that you store '
                'your login credentials in a password_file instead. See '
                '{}/BotPasswords for instructions and more information.'
                .format(__url__))
            main_username = self.username.partition('@')[0]

        try:
            data = self.site.allusers(start=main_username, total=1)
            user = next(iter(data))
        except pywikibot.data.api.APIError as e:
            if e.code == 'readapidenied':
                pywikibot.warning('Could not check user %s exists on %s'
                                  % (main_username, self.site))
                return
            else:
                raise

        if user['name'] != main_username:
            # Report the same error as server error code NotExists
            raise NoUsername("Username '%s' does not exist on %s"
                             % (main_username, self.site))
Пример #27
0
 def testTkdialog(self):
     """Test Tk dialog."""
     try:
         box = Tkdialog('foo', 'tests/data/MP_sounds.png', 'MP_sounds.png')
         box.show_dialog()
     except ImportError as e:
         pywikibot.warning(e)
Пример #28
0
 def load(self, page):
     """
     Loads the given page, does some changes, and saves it.
     """
     try:
         # Load the page
         text = page.get()
     except pywikibot.NoPage:
         if self.create:
             pywikibot.output(u"Page %s doesn't exist yet; creating."
                              % (page.title(asLink=True)))
             text = ''
         else:
             pywikibot.output(u"Page %s does not exist; skipping."
                              % page.title(asLink=True))
     except pywikibot.IsRedirectPage as arg:
         redirTarget = pywikibot.Page(self.site, arg.args[0])
         if self.follow_redirects:
             text = redirTarget.get()
         else:
             pywikibot.warning(u"Page %s is a redirect to %s; skipping."
                               % (page.title(asLink=True),
                                  redirTarget.title(asLink=True)))
     else:
         return text
Пример #29
0
 def status(self):
     """Return Proofread Page status."""
     try:
         return self.site.proofread_levels[self.ql]
     except KeyError:
         pywikibot.warning('Not valid status set for {0!s}: quality level = {1!s}'.format(self.title(asLink=True), self.ql))
         return None
Пример #30
0
    def treat(self, page):
        """
        Load the given page, make the required changes, and save it.

        @param page: the page to treat
        @type page: pywikibot.Page
        """
        self.current_page = page
        page.get()
        wikicode = mwparserfromhell.parse(page.text)
        for el in wikicode.ifilter_tags():
            if el.tag in self.getOption('tags'):
                try:
                    result = self.process_lines(el.contents)
                except PoemError as e:
                    pywikibot.warning(e)
                    continue
                if result:
                    lines, numbering, lines_count = result
                    if lines != el.contents:
                        scheme = self.detect_numbering(numbering, lines_count)
                        if scheme:
                            el.contents = lines
                            for attr, val in scheme.items():
                                el.add(attr, val)
                            if self.getOption('preferred'):
                                # change the tag name to the preferred form
                                el.tag = self.getOption('preferred')
                        else:
                            pywikibot.warning(u'a reliable line numbering scheme could not be obtained')
        newtext = unicode(wikicode)
        summary = self.getOption('summary')
        if not summary:
            summary = i18n.translate(page.site, self.summary, fallback=True)
        self.userPut(page, page.text, newtext, comment=summary)
Пример #31
0
def main(*args):
    """Process command line arguments and perform task."""
#     imagerecat.initLists()

    photoset = u''  # public (popular photos), full (all photos), user ID number
    start_id = u''
    end_id = u''
    addCategory = u''
    autonomous = False
    totalPhotos = 0
    uploadedPhotos = 0

    # Do we mark the images as reviewed right away?
    if config.panoramio['review']:
        panoramioreview = config.panoramio['review']
    else:
        panoramioreview = False

    # Set the Panoramio reviewer
    if config.panoramio['reviewer']:
        reviewer = config.panoramio['reviewer']
    elif 'commons' in config.sysopnames['commons']:
        reviewer = config.sysopnames['commons']['commons']
    elif 'commons' in config.usernames['commons']:
        reviewer = config.usernames['commons']['commons']
    else:
        reviewer = u''

    # Should be renamed to overrideLicense or something like that
    override = u''
    local_args = pywikibot.handle_args(args)
    for arg in local_args:
        if arg.startswith('-set'):
            if len(arg) == 4:
                photoset = pywikibot.input(u'What is the set?')
            else:
                photoset = arg[5:]
        elif arg.startswith('-start_id'):
            if len(arg) == 9:
                start_id = pywikibot.input(
                    u'What is the id of the photo you want to start at?')
            else:
                start_id = arg[10:]
        elif arg.startswith('-end_id'):
            if len(arg) == 7:
                end_id = pywikibot.input(
                    u'What is the id of the photo you want to end at?')
            else:
                end_id = arg[8:]
        elif arg == '-panoramioreview':
            panoramioreview = True
        elif arg.startswith('-reviewer'):
            if len(arg) == 9:
                reviewer = pywikibot.input(u'Who is the reviewer?')
            else:
                reviewer = arg[10:]
        elif arg.startswith('-override'):
            if len(arg) == 9:
                override = pywikibot.input(u'What is the override text?')
            else:
                override = arg[10:]
        elif arg.startswith('-addcategory'):
            if len(arg) == 12:
                addCategory = pywikibot.input(
                    u'What category do you want to add?')
            else:
                addCategory = arg[13:]
        elif arg == '-autonomous':
            autonomous = True

    if photoset:
        site = pywikibot.Site()
        if site != pywikibot.Site('commons', 'commons'):
            pywikibot.warning(
                'Using {0} instead of Wikimedia Commons'.format(site))

        for photoInfo in getPhotos(photoset, start_id, end_id):
            photoInfo = getLicense(photoInfo)
            # time.sleep(10)
            uploadedPhotos += processPhoto(photoInfo, panoramioreview,
                                           reviewer, override, addCategory,
                                           autonomous, site=site)
            totalPhotos += 1
    else:
        usage()
    pywikibot.output(u'Finished running')
    pywikibot.output(u'Total photos: ' + str(totalPhotos))
    pywikibot.output(u'Uploaded photos: ' + str(uploadedPhotos))
Пример #32
0
    def replace_links(self, text, linkedPage, targetPage):
        """Replace all source links by target."""
        mysite = pywikibot.Site()
        linktrail = mysite.linktrail()

        # make a backup of the original text so we can show the changes later
        linkR = re.compile(
            r'\[\[(?P<title>[^\]\|#]*)(?P<section>#[^\]\|]*)?'
            r'(\|(?P<label>[^\]]*))?\]\](?P<linktrail>' + linktrail + ')')
        curpos = 0
        # This loop will run until we have finished the current page
        while True:
            m = linkR.search(text, pos=curpos)
            if not m:
                break
            # Make sure that next time around we will not find this same hit.
            curpos = m.start() + 1
            # T283403
            try:
                is_interwikilink = mysite.isInterwikiLink(m.group('title'))
            except ValueError:
                pywikibot.exception()
                continue
            # ignore interwiki links, links in the disabled area
            # and links to sections of the same page
            if (m.group('title').strip() == ''
                    or is_interwikilink
                    or isDisabled(text, m.start())):
                continue
            actualLinkPage = pywikibot.Page(targetPage.site, m.group('title'))
            # Check whether the link found is to page.
            try:
                actualLinkPage.title()
            except InvalidTitleError:
                pywikibot.exception()
                continue
            if actualLinkPage != linkedPage:
                continue

            # The link looks like this:
            # [[page_title|link_text]]trailing_chars
            page_title = m.group('title')
            link_text = m.group('label')

            if not link_text:
                # or like this: [[page_title]]trailing_chars
                link_text = page_title
            if m.group('section') is None:
                section = ''
            else:
                section = m.group('section')
            if section and targetPage.section():
                pywikibot.warning(
                    'Source section {} and target section {} found. '
                    'Skipping.'.format(section, targetPage))
                continue
            trailing_chars = m.group('linktrail')
            if trailing_chars:
                link_text += trailing_chars

            # remove preleading ":"
            if link_text[0] == ':':
                link_text = link_text[1:]
            if link_text[0].isupper() or link_text[0].isdigit():
                new_page_title = targetPage.title()
            else:
                new_page_title = first_lower(targetPage.title())

            # remove preleading ":"
            if new_page_title[0] == ':':
                new_page_title = new_page_title[1:]

            if ((new_page_title == link_text and not section)
                    or self.opt.overwrite):
                newlink = '[[{}]]'.format(new_page_title)
            # check if we can create a link with trailing characters instead of
            # a pipelink
            elif (len(new_page_title) <= len(link_text)
                  and (firstcap(link_text[:len(new_page_title)])
                       == firstcap(new_page_title))
                  and re.sub(re.compile(linktrail), '',
                             link_text[len(new_page_title):]) == ''
                  and not section):
                newlink = '[[{}]]{}'.format(link_text[:len(new_page_title)],
                                            link_text[len(new_page_title):])
            else:
                newlink = '[[{}{}|{}]]'.format(new_page_title,
                                               section, link_text)
            text = text[:m.start()] + newlink + text[m.end():]
            continue
        return text
Пример #33
0
 def fix_1_double_redirect(self):
     """Treat one double redirect."""
     newRedir = redir = self.current_page
     redirList = []  # bookkeeping to detect loops
     while True:
         redirList.append('{0}:{1}'
                          .format(newRedir.site.lang,
                                  newRedir.title(with_section=False)))
         try:
             targetPage = newRedir.getRedirectTarget()
         except pywikibot.IsNotRedirectPage:
             if len(redirList) == 2:
                 pywikibot.output(
                     'Skipping: Redirect target {0} is not a redirect.'
                     .format(newRedir.title(as_link=True)))
                 break  # do nothing
         except pywikibot.SectionError:
             pywikibot.warning(
                 "Redirect target section {0} doesn't exist."
                 .format(newRedir.title(as_link=True)))
         except (pywikibot.CircularRedirect,
                 pywikibot.InterwikiRedirectPage,
                 pywikibot.UnsupportedPage,
                 RuntimeError):
             pywikibot.exception()
             pywikibot.output('Skipping {0}.'.format(newRedir))
             break
         except pywikibot.BadTitle as e:
             # str(e) is in the format 'BadTitle: [[Foo]]'
             pywikibot.warning(
                 'Redirect target {0} is not a valid page title.'
                 .format(str(e)[10:]))
             break
         except pywikibot.NoPage:
             if self.getOption('always'):
                 pywikibot.output(
                     "Skipping: Redirect target {} doesn't exist."
                     .format(newRedir.title(as_link=True)))
                 break  # skip if automatic
             else:
                 pywikibot.warning(
                     "Redirect target {} doesn't exist."
                     .format(newRedir.title(as_link=True)))
         except pywikibot.ServerError:
             pywikibot.output('Skipping due to server error: '
                              'No textarea found')
             break
         else:
             pywikibot.output(
                 '   Links to: {0}.'
                 .format(targetPage.title(as_link=True)))
             try:
                 mw_msg = targetPage.site.mediawiki_message(
                     'wikieditor-toolbar-tool-redirect-example')
             except KeyError:
                 pass
             else:
                 if targetPage.title() == mw_msg:
                     pywikibot.output(
                         'Skipping toolbar example: Redirect source is '
                         'potentially vandalized.')
                     break
             # watch out for redirect loops
             if redirList.count('{0}:{1}'.format(
                 targetPage.site.lang,
                     targetPage.title(with_section=False))):
                 pywikibot.warning(
                     'Redirect target {0} forms a redirect loop.'
                     .format(targetPage.title(as_link=True)))
                 break  # FIXME: doesn't work. edits twice!
                 if self.getOption('delete'):
                     # Delete the two redirects
                     # TODO: Check whether pages aren't vandalized
                     # and (maybe) do not have a version history
                     self.delete_redirect(targetPage,
                                          'redirect-remove-loop')
                     self.delete_redirect(redir, 'redirect-remove-loop')
                 break
             else:  # redirect target found
                 if targetPage.isStaticRedirect():
                     pywikibot.output(
                         '   Redirect target is STATICREDIRECT.')
                 else:
                     newRedir = targetPage
                     continue
         try:
             oldText = redir.get(get_redirect=True)
         except pywikibot.BadTitle:
             pywikibot.output('Bad Title Error')
             break
         if self.is_repo and redir.namespace() == self.repo.item_namespace:
             redir = pywikibot.ItemPage(self.repo, redir.title())
             targetPage = pywikibot.ItemPage(self.repo, targetPage.title())
             pywikibot.output('Fixing double item redirect')
             redir.set_redirect_target(targetPage)
             break
         redir.set_redirect_target(targetPage, keep_section=True,
                                   save=False)
         summary = i18n.twtranslate(self.site, 'redirect-fix-double',
                                    {'to': targetPage.title(as_link=True)}
                                    )
         self.userPut(redir, oldText, redir.text, summary=summary,
                      ignore_save_related_errors=True,
                      ignore_server_errors=True)
         break
Пример #34
0
def main(*args):
    """Process command line arguments and invoke PatrolBot."""
    # This factory is responsible for processing command line arguments
    # that are also used by other scripts and that determine on which pages
    # to work on.
    usercontribs = None
    gen = None
    recentchanges = False
    newpages = False
    repeat = False
    gen_factory = pagegenerators.GeneratorFactory()
    options = {}

    # Parse command line arguments
    for arg in pywikibot.handle_args(args):
        if arg.startswith('-ask'):
            options['ask'] = True
        elif arg.startswith('-autopatroluserns'):
            options['autopatroluserns'] = True
        elif arg.startswith('-repeat'):
            repeat = True
        elif arg.startswith('-newpages'):
            newpages = True
        elif arg.startswith('-recentchanges'):
            recentchanges = True
        elif arg.startswith('-usercontribs:'):
            usercontribs = arg[14:]
        elif arg.startswith('-versionchecktime:'):
            versionchecktime = arg[len('-versionchecktime:'):]
            options['versionchecktime'] = int(versionchecktime)
        elif arg.startswith("-whitelist:"):
            options['whitelist'] = arg[len('-whitelist:'):]
        else:
            generator = gen_factory.handleArg(arg)
            if not generator:
                if ':' in arg:
                    m = arg.split(':')
                    options[m[0]] = m[1]

    site = pywikibot.Site()
    site.login()

    if usercontribs:
        user = pywikibot.User(site, usercontribs)
        if user.isAnonymous() or user.isRegistered():
            pywikibot.output('Processing user: {}'.format(usercontribs))
        else:
            pywikibot.warning('User {} does not exist on site {}.'.format(
                usercontribs, site))

    # default behaviour
    if not any((newpages, recentchanges, usercontribs)):
        if site.family.name == 'wikipedia':
            newpages = True
        else:
            recentchanges = True

    bot = PatrolBot(**options)

    if newpages or usercontribs:
        pywikibot.output(u'Newpages:')
        gen = site.newpages
        feed = api_feed_repeater(gen,
                                 delay=60,
                                 repeat=repeat,
                                 user=usercontribs,
                                 namespaces=gen_factory.namespaces,
                                 recent_new_gen=False)
        bot.run(feed)

    if recentchanges or usercontribs:
        pywikibot.output(u'Recentchanges:')
        gen = site.recentchanges
        feed = api_feed_repeater(gen,
                                 delay=60,
                                 repeat=repeat,
                                 namespaces=gen_factory.namespaces,
                                 user=usercontribs)
        bot.run(feed)

    pywikibot.output(u'%d/%d patrolled' %
                     (bot.patrol_counter, bot.rc_item_counter))
Пример #35
0
def main(*args):
    """
    Process command line arguments and invoke bot.

    If args is an empty list, sys.argv is used.

    @param args: command line arguments
    @type args: list of unicode
    """
    gen = None
    notitle = False
    fmt = '1'
    outputlang = None
    page_get = False
    base_dir = None
    encoding = config.textfile_encoding

    # Process global args and prepare generator args parser
    local_args = pywikibot.handle_args(args)
    genFactory = GeneratorFactory()

    for arg in local_args:
        if arg == '-notitle':
            notitle = True
        elif arg.startswith('-format:'):
            fmt = arg[len('-format:'):]
            fmt = fmt.replace(u'\\03{{', u'\03{{')
        elif arg.startswith('-outputlang:'):
            outputlang = arg[len('-outputlang:'):]
        elif arg == '-get':
            page_get = True
        elif arg.startswith('-save'):
            base_dir = arg.partition(':')[2] or '.'
        elif arg.startswith('-encode:'):
            encoding = arg.partition(':')[2]
        else:
            genFactory.handleArg(arg)

    if base_dir:
        base_dir = os.path.expanduser(base_dir)
        if not os.path.isabs(base_dir):
            base_dir = os.path.normpath(os.path.join(os.getcwd(), base_dir))

        if not os.path.exists(base_dir):
            pywikibot.output(u'Directory "%s" does not exist.' % base_dir)
            choice = pywikibot.input_yn(
                u'Do you want to create it ("No" to continue without saving)?')
            if choice:
                os.makedirs(base_dir, mode=0o744)
            else:
                base_dir = None
        elif not os.path.isdir(base_dir):
            # base_dir is a file.
            pywikibot.warning(u'Not a directory: "%s"\n'
                              u'Skipping saving ...'
                              % base_dir)
            base_dir = None

    gen = genFactory.getCombinedGenerator()
    if gen:
        i = 0
        for i, page in enumerate(gen, start=1):
            if not notitle:
                page_fmt = Formatter(page, outputlang)
                pywikibot.stdout(page_fmt.output(num=i, fmt=fmt))
            if page_get:
                try:
                    pywikibot.output(page.text, toStdout=True)
                except pywikibot.Error as err:
                    pywikibot.output(err)
            if base_dir:
                filename = os.path.join(base_dir, page.title(as_filename=True))
                pywikibot.output(u'Saving %s to %s' % (page.title(), filename))
                with open(filename, mode='wb') as f:
                    f.write(page.text.encode(encoding))
        pywikibot.output(u"%i page(s) found" % i)
    else:
        pywikibot.showHelp()
Пример #36
0
def main(*args) -> None:
    """
    Process command line arguments and invoke bot.

    If args is an empty list, sys.argv is used.

    @param args: command line arguments
    @type args: str
    """
    password = None
    logall = False
    logout = False
    oauth = False
    autocreate = False
    unknown_args = []
    for arg in pywikibot.handle_args(args):
        if arg.startswith('-pass'):
            if len(arg) == 5:
                password = pywikibot.input(
                    'Password for all accounts (no characters will be shown):',
                    password=True)
            else:
                password = arg[6:]
        elif arg == '-all':
            logall = True
        elif arg == '-force':
            pywikibot.output('To force a re-login, please delete the '
                             "revelant lines from '{0}' (or the entire file) "
                             'and try again.'.format(
                                 join(config.base_dir, 'pywikibot.lwp')))
        elif arg == '-logout':
            logout = True
        elif arg == '-oauth':
            oauth = True
        elif arg == '-autocreate':
            autocreate = True
        else:
            unknown_args += [arg]

    if pywikibot.bot.suggest_help(unknown_parameters=unknown_args):
        return

    if password is not None:
        pywikibot.warning('The -pass argument is not implemented yet. See: '
                          'https://phabricator.wikimedia.org/T102477')

    if logall:
        namedict = config.usernames
    else:
        site = pywikibot.Site()
        namedict = {site.family.name: {site.code: None}}
    for family_name in namedict:
        for lang in namedict[family_name]:
            try:
                site = pywikibot.Site(code=lang, fam=family_name)
                if oauth:
                    _oauth_login(site)
                    continue
                if logout:
                    site.logout()
                else:
                    site.login(autocreate=autocreate)
                user = site.user()
                if user:
                    pywikibot.output('Logged in on {0} as {1}.'.format(
                        site, user))
                else:
                    if logout:
                        pywikibot.output('Logged out of {0}.'.format(site))
                    else:
                        pywikibot.output('Not logged in on {0}.'.format(site))
            except SiteDefinitionError:
                pywikibot.output('{0}.{1} is not a valid site, '
                                 'please remove it from your config'.format(
                                     lang, family_name))
Пример #37
0
    def __init__(self, generator, templates, **kwargs):
        """
        Initializer.

        @param generator: the pages to work on
        @type generator: iterable
        @param templates: a dictionary which maps old template names to
            their replacements. If remove or subst is True, it maps the
            names of the templates that should be removed/resolved to None.
        @type templates: dict
        """
        self.availableOptions.update({
            'subst': False,
            'remove': False,
            'summary': None,
            'addedCat': None,
        })

        Bot.__init__(self, generator=generator, **kwargs)

        self.templates = templates

        # get edit summary message if it's empty
        if not self.getOption('summary'):
            comma = self.site.mediawiki_message('comma-separator')
            params = {'list': comma.join(self.templates.keys()),
                      'num': len(self.templates)}

            if self.getOption('remove'):
                self.options['summary'] = i18n.twtranslate(
                    self.site, 'template-removing', params)
            elif self.getOption('subst'):
                self.options['summary'] = i18n.twtranslate(
                    self.site, 'template-substituting', params)
            else:
                self.options['summary'] = i18n.twtranslate(
                    self.site, 'template-changing', params)

        replacements = []
        exceptions = {}
        builder = textlib._MultiTemplateMatchBuilder(self.site)
        for old, new in self.templates.items():
            template_regex = builder.pattern(old)

            if self.getOption('subst') and self.getOption('remove'):
                replacements.append((template_regex,
                                     r'{{subst:%s\g<parameters>}}' % new))
                exceptions['inside-tags'] = ['ref', 'gallery', 'poem',
                                             'pagelist', ]
            elif self.getOption('subst'):
                replacements.append((template_regex,
                                     r'{{subst:%s\g<parameters>}}' % old))
                exceptions['inside-tags'] = ['ref', 'gallery', 'poem',
                                             'pagelist', ]
            elif self.getOption('remove'):
                separate_line_regex = re.compile(
                    r'^[*#:]* *{0} *\n'.format(template_regex.pattern),
                    re.DOTALL | re.MULTILINE)
                replacements.append((separate_line_regex, ''))

                spaced_regex = re.compile(
                    r' +{0} +'.format(template_regex.pattern),
                    re.DOTALL)
                replacements.append((spaced_regex, ' '))

                replacements.append((template_regex, ''))
            else:
                template = pywikibot.Page(self.site, new, ns=10)
                if not template.exists():
                    pywikibot.warning('Template "{0}" does not exist.'
                                      .format(new))
                    if not pywikibot.input_yn('Do you want to proceed anyway?',
                                              default=False,
                                              automatic_quit=False):
                        continue
                replacements.append((template_regex,
                                     r'{{%s\g<parameters>}}' % new))

        super(TemplateRobot, self).__init__(
            generator, replacements, exceptions,
            always=self.getOption('always'),
            addedCat=self.getOption('addedCat'),
            summary=self.getOption('summary'))
Пример #38
0
def handle_args(args):
    """Process command line arguments.

    If args is an empty list, sys.argv is used.

    @param args: command line arguments
    @type args: str
    """
    mapping = {
        # option: (attribute, value),
        '-break': ('recursive', False),
        '-nlog': ('makeWelcomeLog', False),
        '-ask': ('confirm', True),
        '-filter': ('filtBadName', True),
        '-savedata': ('saveSignIndex', True),
        '-random': ('randomSign', True),
        '-sul': ('welcomeAuto', True),
        '-quiet': ('quiet', True),
    }

    for arg in pywikibot.handle_args(args):
        arg, _, val = arg.partition(':')
        if arg == '-edit':
            globalvar.attachEditCount = int(
                val if val.isdigit() else pywikibot.input(
                    'After how many edits would you like to welcome new users?'
                    ' (0 is allowed)'))
        elif arg == '-timeoffset':
            globalvar.timeoffset = int(
                val if val.isdigit() else pywikibot.
                input('Which time offset (in minutes) for new users would you '
                      'like to use?'))
        elif arg == '-time':
            globalvar.timeRecur = int(
                val if val.isdigit() else pywikibot.
                input('For how many seconds would you like to bot to sleep '
                      'before checking again?'))
        elif arg == '-offset':
            _handle_offset(val)
        elif arg == '-file':
            globalvar.randomSign = True
            globalvar.signFileName = val or pywikibot.input(
                'Where have you saved your signatures?')
        elif arg == '-sign':
            globalvar.defaultSign = val or pywikibot.input(
                'Which signature to use?')
            globalvar.defaultSign += timeselected
        elif arg == '-limit':
            globalvar.queryLimit = int(
                val if val.isdigit() else pywikibot.
                input('How many of the latest new users would you like to '
                      'load?'))
        elif arg == '-numberlog':
            globalvar.dumpToLog = int(
                val if val.isdigit() else pywikibot.
                input('After how many welcomed users would you like to update '
                      'the welcome log?'))
        elif arg in mapping:
            setattr(globalvar, *mapping[arg])
        else:
            pywikibot.warning('Unknown option "{}"'.format(arg))
Пример #39
0
 def run(self):
     """Run the bot."""
     for page in self.generator:
         self.current_page = page
         try:
             text = page.text
         except pywikibot.NoPage:
             pywikibot.warning('Page %s does not exist?!' %
                               page.title(asLink=True))
             continue
         except pywikibot.IsRedirectPage:
             pywikibot.output(u"Page %s is a redirect; skipping." %
                              page.title(asLink=True))
             continue
         except pywikibot.LockedPage:
             pywikibot.warning('Page %s is locked?!' %
                               page.title(asLink=True))
             continue
         if page.isDisambig():
             pywikibot.output(u"Page %s is a disambig; skipping." %
                              page.title(asLink=True))
             continue
         if self.site.sitename == 'wikipedia:en' and page.isIpEdit():
             pywikibot.warning(
                 u"Page %s is edited by IP. Possible vandalized" %
                 page.title(asLink=True))
             continue
         if self.lacksReferences(text):
             newText = self.addReferences(text)
             try:
                 self.userPut(page,
                              page.text,
                              newText,
                              summary=self.comment)
             except pywikibot.EditConflict:
                 pywikibot.warning('Skipping %s because of edit conflict' %
                                   page.title(asLink=True))
             except pywikibot.SpamfilterError as e:
                 pywikibot.warning(
                     u'Cannot change %s because of blacklist entry %s' %
                     (page.title(asLink=True), e.url))
             except pywikibot.LockedPage:
                 pywikibot.warning('Skipping %s (locked page)' %
                                   page.title(asLink=True))
Пример #40
0
 def test_warning(self):
     pywikibot.warning('warning')
     self.assertEqual(newstdout.getvalue(), '')
     self.assertEqual(newstderr.getvalue(), 'WARNING: warning\n')
Пример #41
0
    def process_filename(self, file_url=None):
        """Return base filename portion of file_url."""
        if not file_url:
            file_url = self.url
            pywikibot.warning("file_url is not given. "
                              "Set to self.url by default.")

        always = self.getOption('always')
        # Isolate the pure name
        filename = file_url
        # Filename may be either a URL or a local file path
        if "://" in filename:
            # extract the path portion of the URL
            filename = urlparse(filename).path
        filename = os.path.basename(filename)
        if self.useFilename:
            filename = self.useFilename
        if not self.keepFilename:
            pywikibot.output(
                u"The filename on the target wiki will default to: %s" %
                filename)
            assert not always
            newfn = pywikibot.input(
                u'Enter a better name, or press enter to accept:')
            if newfn != "":
                filename = newfn
        # FIXME: these 2 belong somewhere else, presumably in family
        # forbidden characters are handled by pywikibot/page.py
        forbidden = ':*?/\\'  # to be extended
        try:
            allowed_formats = self.targetSite.siteinfo.get('fileextensions',
                                                           get_default=False)
        except KeyError:
            allowed_formats = []
        else:
            allowed_formats = [item['ext'] for item in allowed_formats]

        # ask until it's valid
        first_check = True
        while True:
            if not first_check:
                if always:
                    filename = None
                else:
                    filename = pywikibot.input('Enter a better name, or press '
                                               'enter to skip the file:')
                if not filename:
                    return None
            first_check = False
            ext = os.path.splitext(filename)[1].lower().strip('.')
            # are any chars in forbidden also in filename?
            invalid = set(forbidden) & set(filename)
            if invalid:
                c = "".join(invalid)
                pywikibot.output('Invalid character(s): %s. Please try again' %
                                 c)
                continue
            if allowed_formats and ext not in allowed_formats:
                if always:
                    pywikibot.output('File format is not one of '
                                     '[{0}]'.format(' '.join(allowed_formats)))
                    continue
                elif not pywikibot.input_yn(
                        u"File format is not one of [%s], but %s. Continue?" %
                    (u' '.join(allowed_formats), ext),
                        default=False,
                        automatic_quit=False):
                    continue
            potential_file_page = pywikibot.FilePage(self.targetSite, filename)
            if potential_file_page.exists():
                overwrite = self._handle_warning('exists')
                if overwrite is False:
                    pywikibot.output(
                        "File exists and you asked to abort. Skipping.")
                    return None
                if potential_file_page.canBeEdited():
                    if overwrite is None:
                        overwrite = not pywikibot.input_yn(
                            "File with name %s already exists. "
                            "Would you like to change the name? "
                            "(Otherwise file will be overwritten.)" % filename,
                            default=True,
                            automatic_quit=False)
                    if not overwrite:
                        continue
                    else:
                        break
                else:
                    pywikibot.output(u"File with name %s already exists and "
                                     "cannot be overwritten." % filename)
                    continue
            else:
                try:
                    if potential_file_page.fileIsShared():
                        pywikibot.output(
                            u"File with name %s already exists in shared "
                            "repository and cannot be overwritten." % filename)
                        continue
                    else:
                        break
                except pywikibot.NoPage:
                    break

        # A proper description for the submission.
        # Empty descriptions are not accepted.
        pywikibot.output(u'The suggested description is:\n%s' %
                         self.description)

        # Description must be set and verified
        if not self.description:
            self.verifyDescription = True

        while not self.description or self.verifyDescription:
            if not self.description:
                pywikibot.output(
                    u'\03{lightred}It is not possible to upload a file '
                    'without a summary/description.\03{default}')

            assert not always
            # if no description, default is 'yes'
            if pywikibot.input_yn(u'Do you want to change this description?',
                                  default=not self.description):
                from pywikibot import editor as editarticle
                editor = editarticle.TextEditor()
                try:
                    newDescription = editor.edit(self.description)
                except Exception as e:
                    pywikibot.error(e)
                    continue
                # if user saved / didn't press Cancel
                if newDescription:
                    self.description = newDescription
            self.verifyDescription = False

        return filename
Пример #42
0
    def __init__(self,
                 url,
                 urlEncoding=None,
                 description=u'',
                 useFilename=None,
                 keepFilename=False,
                 verifyDescription=True,
                 ignoreWarning=False,
                 targetSite=None,
                 uploadByUrl=False,
                 aborts=[],
                 chunk_size=0,
                 **kwargs):
        """
        Constructor.

        @param url: path to url or local file (deprecated), or list of urls or
            paths to local files.
        @type url: string (deprecated) or list
        @param description: Description of file for its page. If multiple files
            are uploading the same description is used for every file.
        @type description: string
        @param useFilename: Specify title of the file's page. If multiple
            files are uploading it asks to change the name for second, third,
            etc. files, otherwise the last file will overwrite the other.
        @type useFilename: string
        @param keepFilename: Set to True to keep original names of urls and
            files, otherwise it will ask to enter a name for each file.
        @type keepFilename: bool
        @param verifyDescription: Set to False to not proofread the description.
        @type verifyDescription: bool
        @param ignoreWarning: Set this to True to upload even if another file
            would be overwritten or another mistake would be risked. Set it to
            an array of warning codes to selectively ignore specific warnings.
        @type ignoreWarning: bool or list
        @param targetSite: Set the site to upload to. If target site is not
            given it's taken from user-config.py.
        @type targetSite: object
        @param aborts: List of the warning types to abort upload on. Set to True
            to abort on any warning.
        @type aborts: bool or list
        @param chunk_size: Upload the file in chunks (more overhead, but
            restartable) specified in bytes. If no value is specified the file
            will be uploaded as whole.
        @type chunk_size: integer
        @param always: Disables any input, requires that either ignoreWarning or
            aborts are set to True and that the description is also set. It will
            overwrite verifyDescription to False and keepFilename to True.
        @type always: bool

        @deprecated: Using upload_image() is deprecated, use upload_file() with
            file_url param instead

        """
        super(UploadRobot, self).__init__(**kwargs)
        always = self.getOption('always')
        if (always and ignoreWarning is not True and aborts is not True):
            raise ValueError(
                'When always is set to True, either ignoreWarning '
                'or aborts must be set to True.')
        if always and not description:
            raise ValueError('When always is set to True the description must '
                             'be set.')
        self.url = url
        if isinstance(self.url, basestring):
            pywikibot.warning("url as string is deprecated. "
                              "Use an iterable instead.")
        self.urlEncoding = urlEncoding
        self.description = description
        self.useFilename = useFilename
        self.keepFilename = keepFilename or always
        self.verifyDescription = verifyDescription and not always
        self.ignoreWarning = ignoreWarning
        self.aborts = aborts
        self.chunk_size = chunk_size
        if config.upload_to_commons:
            self.targetSite = targetSite or pywikibot.Site(
                'commons', 'commons')
        else:
            self.targetSite = targetSite or pywikibot.Site()
        self.targetSite.login()
        self.uploadByUrl = uploadByUrl
Пример #43
0
 def delete_1_broken_redirect(self, redir_name):
     redir_page = pywikibot.Page(self.site, redir_name)
     # Show the title of the page we're working on.
     # Highlight the title in purple.
     pywikibot.output(u"\n\n>>> \03{lightpurple}%s\03{default} <<<"
                      % redir_page.title())
     try:
         targetPage = redir_page.getRedirectTarget()
     except pywikibot.IsNotRedirectPage:
         pywikibot.output(u'%s is not a redirect.' % redir_page.title())
     except pywikibot.NoPage:
         pywikibot.output(u'%s doesn\'t exist.' % redir_page.title())
     else:
         try:
             targetPage.get()
         except pywikibot.BadTitle as e:
             pywikibot.warning(
                 u'Redirect target %s is not a valid page title.'
                 % str(e)[10:])
             pass
         except pywikibot.NoPage:
             movedTarget = self.moved_page(targetPage)
             if movedTarget:
                 if not movedTarget.exists():
                     # FIXME: Test to another move
                     pywikibot.output(u'Target page %s does not exist'
                                      % (movedTarget))
                 elif redir_name == movedTarget.title():
                     pywikibot.output(u'Target page forms a redirect loop')
                 else:
                     pywikibot.output(u'%s has been moved to %s'
                                      % (redir_page, movedTarget))
                     reason = i18n.twtranslate(self.site,
                                               'redirect-fix-broken-moved',
                                               {'to': movedTarget.title(
                                                   asLink=True)})
                     content = redir_page.get(get_redirect=True)
                     text = self.site.redirectRegex().sub(
                         '#%s %s' % (self.site.redirect(),
                                     movedTarget.title(asLink=True,
                                                       textlink=True)),
                         content)
                     pywikibot.showDiff(content, text)
                     pywikibot.output(u'Summary - %s' % reason)
                     if self.user_confirm(
                             u'Redirect target %s has been moved to %s.\n'
                             u'Do you want to fix %s?'
                             % (targetPage, movedTarget, redir_page)):
                         try:
                             redir_page.text = text
                             redir_page.save(reason)
                         except pywikibot.NoUsername:
                             pywikibot.output(u"Page [[%s]] not saved; "
                                              u"sysop privileges required."
                                              % redir_page.title())
                             pass
                         except pywikibot.LockedPage:
                             pywikibot.output(u'%s is locked.'
                                              % redir_page.title())
                             pass
             elif self.getOption('delete') and self.user_confirm(
                     u'Redirect target %s does not exist.\n'
                     u'Do you want to delete %s?'
                     % (targetPage.title(asLink=True),
                        redir_page.title(asLink=True))):
                 reason = i18n.twtranslate(self.site,
                                           'redirect-remove-broken')
                 if self.site.logged_in(sysop=True):
                     redir_page.delete(reason, prompt=False)
                 else:
                     assert targetPage.site == self.site, (
                         u'target page is on different site %s'
                         % targetPage.site)
                     if (self.has_valid_template(
                         'redirect-broken-redirect-template') and
                         i18n.twhas_key(targetPage.site,
                                        'redirect-remove-broken')):
                         pywikibot.output(u"No sysop in user-config.py, "
                                          u"put page to speedy deletion.")
                         content = redir_page.get(get_redirect=True)
                         # TODO: Add bot's signature if needed
                         #       Not supported via TW yet
                         content = i18n.twtranslate(
                             targetPage.site,
                             'redirect-broken-redirect-template'
                         ) + "\n" + content
                         redir_page.put(content, reason)
                     else:
                         pywikibot.output(
                             u'No speedy deletion template available')
         except pywikibot.IsRedirectPage:
             pywikibot.output(u"Redirect target %s is also a redirect! "
                              u"Won't delete anything."
                              % targetPage.title(asLink=True))
         else:
             # we successfully get the target page, meaning that
             # it exists and is not a redirect: no reason to touch it.
             pywikibot.output(
                 u'Redirect target %s does exist! Won\'t delete anything.'
                 % targetPage.title(asLink=True))
     pywikibot.output(u'')
Пример #44
0
    def fix_1_double_redirect(self,  redir_name):
        redir = pywikibot.Page(self.site, redir_name)
        # Show the title of the page we're working on.
        # Highlight the title in purple.
        pywikibot.output(u"\n\n>>> \03{lightpurple}%s\03{default} <<<"
                         % redir.title())
        newRedir = redir
        redirList = []  # bookkeeping to detect loops
        while True:
            redirList.append(u'%s:%s' % (newRedir.site.lang,
                                         newRedir.title(withSection=False)))
            try:
                targetPage = newRedir.getRedirectTarget()
            except pywikibot.IsNotRedirectPage:
                if len(redirList) == 1:
                    pywikibot.output(u'Skipping: Page %s is not a redirect.'
                                     % redir.title(asLink=True))
                    break  # do nothing
                elif len(redirList) == 2:
                    pywikibot.output(
                        u'Skipping: Redirect target %s is not a redirect.'
                        % newRedir.title(asLink=True))
                    break  # do nothing
                else:
                    pass  # target found
            except pywikibot.SectionError:
                pywikibot.warning(
                    u"Redirect target section %s doesn't exist."
                    % newRedir.title(asLink=True))
            except (pywikibot.CircularRedirect,
                    pywikibot.InterwikiRedirectPage) as e:
                pywikibot.exception(e)
                pywikibot.output(u"Skipping %s." % newRedir)
                break
            except pywikibot.BadTitle as e:
                # str(e) is in the format 'BadTitle: [[Foo]]'
                pywikibot.warning(
                    u'Redirect target %s is not a valid page title.'
                    % str(e)[10:])
                break
            except pywikibot.NoPage:
                if len(redirList) == 1:
                    pywikibot.output(u'Skipping: Page %s does not exist.'
                                     % redir.title(asLink=True))
                    break
                else:
                    if self.getOption('always'):
                        pywikibot.output(
                            u"Skipping: Redirect target %s doesn't exist."
                            % newRedir.title(asLink=True))
                        break  # skip if automatic
                    else:
                        pywikibot.warning(
                            u"Redirect target %s doesn't exist."
                            % newRedir.title(asLink=True))
            except pywikibot.ServerError:
                pywikibot.output(u'Skipping due to server error: '
                                 u'No textarea found')
                break
            else:
                pywikibot.output(
                    u'   Links to: %s.'
                    % targetPage.title(asLink=True))
                try:
                    mw_msg = targetPage.site.mediawiki_message(
                        'wikieditor-toolbar-tool-redirect-example')
                except KeyError:
                    pass
                else:
                    if targetPage.title() == mw_msg:
                        pywikibot.output(
                            u"Skipping toolbar example: Redirect source is "
                            u"potentially vandalized.")
                        break
                # watch out for redirect loops
                if redirList.count(u'%s:%s'
                                   % (targetPage.site.lang,
                                      targetPage.title(withSection=False))):
                    pywikibot.warning(
                        u'Redirect target %s forms a redirect loop.'
                        % targetPage.title(asLink=True))
                    break  # FIXME: doesn't work. edits twice!
                    try:
                        content = targetPage.get(get_redirect=True)
                    except pywikibot.SectionError:
                        content_page = pywikibot.Page(
                            targetPage.site,
                            targetPage.title(withSection=False))
                        content = content_page.get(get_redirect=True)
                    if i18n.twhas_key(
                        targetPage.site.lang,
                        'redirect-broken-redirect-template') and \
                        i18n.twhas_key(targetPage.site.lang,
                                       'redirect-remove-loop'):
                        pywikibot.output(u"Tagging redirect for deletion")
                        # Delete the two redirects
                        content = i18n.twtranslate(
                            targetPage.site.lang,
                            'redirect-broken-redirect-template'
                        ) + "\n" + content
                        summ = i18n.twtranslate(targetPage.site.lang,
                                                'redirect-remove-loop')
                        targetPage.put(content, summ)
                        redir.put(content, summ)
                    break
                else:  # redirect target found
                    if targetPage.isStaticRedirect():
                        pywikibot.output(
                            u"   Redirect target is STATICREDIRECT.")
                        pass
                    else:
                        newRedir = targetPage
                        continue
            try:
                oldText = redir.get(get_redirect=True)
            except pywikibot.BadTitle:
                pywikibot.output(u"Bad Title Error")
                break
            oldlink = self.site.redirectRegex().search(oldText).group(1)
            if "#" in oldlink and targetPage.section() is None:
                sectionlink = oldlink[oldlink.index("#"):]
                targetlink = pywikibot.Page(
                    self.site,
                    targetPage.title() + sectionlink
                ).title(asLink=True, allow_interwiki=False, textlink=True)
            else:
                targetlink = targetPage.title(asLink=True, allow_interwiki=False, textlink=True)

            text = self.site.redirectRegex().sub(
                '#%s %s' % (self.site.redirect(),
                            targetlink),
                oldText, 1)
            if redir.title() == targetPage.title() or text == oldText:
                pywikibot.output(u"Note: Nothing left to do on %s"
                                 % redir.title(asLink=True))
                break
            summary = i18n.twtranslate(self.site, 'redirect-fix-double',
                                       {'to': targetPage.title(asLink=True, allow_interwiki=False)}
                                       )
            pywikibot.showDiff(oldText, text)
            if self.user_confirm(u'Do you want to accept the changes?'):
                try:
                    redir.put(text, summary)
                except pywikibot.LockedPage:
                    pywikibot.output(u'%s is locked.' % redir.title())
                except pywikibot.SpamfilterError as error:
                    pywikibot.output(
                        u"Saving page [[%s]] prevented by spam filter: %s"
                        % (redir.title(), error.url))
                except pywikibot.PageNotSaved as error:
                    pywikibot.output(u"Saving page [[%s]] failed: %s"
                                     % (redir.title(), error))
                except pywikibot.NoUsername:
                    pywikibot.output(
                        u"Page [[%s]] not saved; sysop privileges required."
                        % redir.title())
                except pywikibot.Error as error:
                    pywikibot.output(
                        u"Unexpected error occurred trying to save [[%s]]: %s"
                        % (redir.title(), error))
            break
Пример #45
0
    def run(self):
        """Run bot."""
        def convert_from_bytes(total_bytes):
            for unit in ['B', 'K', 'M', 'G', 'T']:
                if abs(total_bytes) < 1024:
                    return str(total_bytes) + unit
                total_bytes = float(format(total_bytes / 1024.0, '.2f'))
            return str(total_bytes) + 'P'

        pywikibot.output('Downloading dump from ' + self.opt.wikiname)

        download_filename = '{wikiname}-{dumpdate}-{filename}'.format_map(
            self.opt)
        temp_filename = download_filename + '-' \
            + binascii.b2a_hex(urandom(8)).decode('ascii') + '.part'

        file_final_storepath = os.path.join(self.opt.storepath,
                                            download_filename)
        file_current_storepath = os.path.join(self.opt.storepath,
                                              temp_filename)

        # https://wikitech.wikimedia.org/wiki/Help:Toolforge#Dumps
        toolforge_dump_filepath = self.get_dump_name(self.opt.wikiname,
                                                     self.opt.filename,
                                                     self.opt.dumpdate)

        # First iteration for atomic download with temporary file
        # Second iteration for fallback non-atomic download
        for non_atomic in range(2):
            try:
                if toolforge_dump_filepath:
                    pywikibot.output('Symlinking file from ' +
                                     toolforge_dump_filepath)
                    if non_atomic:
                        if os.path.exists(file_final_storepath):
                            remove(file_final_storepath)
                    symlink(toolforge_dump_filepath, file_current_storepath)
                else:
                    url = 'https://dumps.wikimedia.org/{}/{}/{}'.format(
                        self.opt.wikiname, self.opt.dumpdate,
                        download_filename)
                    pywikibot.output('Downloading file from ' + url)
                    response = fetch(url, stream=True)

                    if response.status_code != HTTPStatus.OK:
                        if response.status_code == HTTPStatus.NOT_FOUND:
                            pywikibot.output(
                                'File with name {filename!r}, from dumpdate '
                                '{dumpdate!r}, and wiki {wikiname!r} ({url}) '
                                "isn't available in the Wikimedia Dumps".
                                format(url=url, **self.opt))
                        else:
                            pywikibot.output(
                                HTTPStatus(response.status_code).description)
                        return

                    with open(file_current_storepath, 'wb') as result_file:
                        total = int(response.headers['content-length'])
                        if total == -1:
                            pywikibot.warning("'content-length' missing in "
                                              'response headers')
                        downloaded = 0
                        parts = 50
                        display_string = ''

                        pywikibot.output('')
                        for data in response.iter_content(100 * 1024):
                            result_file.write(data)

                            if total <= 0:
                                continue

                            downloaded += len(data)
                            done = int(parts * downloaded / total)
                            display = map(convert_from_bytes,
                                          (downloaded, total))
                            prior_display = display_string
                            display_string = '\r|{}{}|{}{}/{}'.format(
                                '=' * done, '-' * (parts - done), ' ' * 5,
                                *display)
                            # Add whitespace to cover up prior bar
                            display_string += ' ' * (
                                len(prior_display.rstrip()) -
                                len(display_string.rstrip()))

                            pywikibot.output(display_string, newline=False)
                        pywikibot.output('')

                # Rename the temporary file to the target file
                # if the download completes successfully
                if not non_atomic:
                    replace(file_current_storepath, file_final_storepath)
                    break

            except OSError:
                pywikibot.exception()

                try:
                    remove(file_current_storepath)
                except OSError:
                    pywikibot.exception()

                # If the atomic download fails, try without a temporary file
                # If the non-atomic download also fails, exit the script
                if non_atomic:
                    return

                pywikibot.output('Cannot make temporary file, '
                                 'falling back to non-atomic download')
                file_current_storepath = file_final_storepath

        pywikibot.output('Done! File stored as ' + file_final_storepath)
Пример #46
0
    def run(self):
        """Run the bot."""
        # validate L10N
        try:
            self.template_list = self.site.family.category_redirect_templates[
                self.site.code]
        except KeyError:
            pywikibot.warning(u"No redirect templates defined for %s" %
                              self.site)
            return
        if not self.get_cat_title():
            pywikibot.warning(u"No redirect category found for %s" % self.site)
            return

        user = self.site.user()  # invokes login()
        newredirs = []

        l = time.localtime()
        today = "%04d-%02d-%02d" % l[:3]
        edit_request_page = pywikibot.Page(
            self.site, u"User:%s/category edit requests" % user)
        datafile = pywikibot.config.datafilepath("%s-catmovebot-data" %
                                                 self.site.dbName())
        try:
            with open(datafile, "rb") as inp:
                record = cPickle.load(inp)
        except IOError:
            record = {}
        if record:
            with open(datafile + ".bak", "wb") as f:
                cPickle.dump(record, f, protocol=config.pickle_protocol)
        # regex to match soft category redirects
        # TODO: enhance and use textlib._MultiTemplateMatchBuilder
        #  note that any templates containing optional "category:" are
        #  incorrect and will be fixed by the bot
        template_regex = re.compile(
            r"""{{\s*(?:%(prefix)s\s*:\s*)?  # optional "template:"
                     (?:%(template)s)\s*\|   # catredir template name
                     (\s*%(catns)s\s*:\s*)?  # optional "category:"
                     ([^|}]+)                # redirect target cat
                     (?:\|[^|}]*)*}}         # optional arguments 2+, ignored
             """ % {
                'prefix':
                self.site.namespace(10).lower(),
                'template':
                "|".join(
                    item.replace(" ", "[ _]+") for item in self.template_list),
                'catns':
                self.site.namespace(14)
            }, re.I | re.X)

        self.check_hard_redirect()

        comment = i18n.twtranslate(self.site, self.move_comment)
        counts = {}
        nonemptypages = []
        redircat = pywikibot.Category(pywikibot.Link(self.cat_title,
                                                     self.site))

        pywikibot.output(u"\nChecking %d category redirect pages" %
                         redircat.categoryinfo['subcats'])
        catpages = set()
        for cat in redircat.subcategories():
            catpages.add(cat)
            cat_title = cat.title(withNamespace=False)
            if "category redirect" in cat_title:
                self.log_text.append(u"* Ignoring %s" %
                                     cat.title(asLink=True, textlink=True))
                continue
            if hasattr(cat, "_catinfo"):
                # skip empty categories that don't return a "categoryinfo" key
                catdata = cat.categoryinfo
                if "size" in catdata and int(catdata['size']):
                    # save those categories that have contents
                    nonemptypages.append(cat)
            if cat_title not in record:
                # make sure every redirect has a record entry
                record[cat_title] = {today: None}
                try:
                    newredirs.append("*# %s -> %s" %
                                     (cat.title(asLink=True, textlink=True),
                                      cat.getCategoryRedirectTarget().title(
                                          asLink=True, textlink=True)))
                except pywikibot.Error:
                    pass
                # do a null edit on cat
                try:
                    cat.save()
                except:
                    pass

        # delete record entries for non-existent categories
        for cat_name in record.keys():
            if pywikibot.Category(self.site,
                                  self.catprefix + cat_name) not in catpages:
                del record[cat_name]

        pywikibot.output(u"\nMoving pages out of %s redirected categories." %
                         len(nonemptypages))

        for cat in pagegenerators.PreloadingGenerator(nonemptypages):
            try:
                if not cat.isCategoryRedirect():
                    self.log_text.append(u"* False positive: %s" %
                                         cat.title(asLink=True, textlink=True))
                    continue
            except pywikibot.Error:
                self.log_text.append(u"* Could not load %s; ignoring" %
                                     cat.title(asLink=True, textlink=True))
                continue
            cat_title = cat.title(withNamespace=False)
            if not self.readyToEdit(cat):
                counts[cat_title] = None
                self.log_text.append(u"* Skipping %s; in cooldown period." %
                                     cat.title(asLink=True, textlink=True))
                continue
            dest = cat.getCategoryRedirectTarget()
            if not dest.exists():
                self.problems.append("# %s redirects to %s" %
                                     (cat.title(asLink=True, textlink=True),
                                      dest.title(asLink=True, textlink=True)))
                # do a null edit on cat to update any special redirect
                # categories this wiki might maintain
                try:
                    cat.save()
                except:
                    pass
                continue
            if dest.isCategoryRedirect():
                double = dest.getCategoryRedirectTarget()
                if double == dest or double == cat:
                    self.log_text.append(
                        u"* Redirect loop from %s" %
                        dest.title(asLink=True, textlink=True))
                    # do a null edit on cat
                    try:
                        cat.save()
                    except:
                        pass
                else:
                    self.log_text.append(
                        u"* Fixed double-redirect: %s -> %s -> %s" %
                        (cat.title(asLink=True, textlink=True),
                         dest.title(asLink=True, textlink=True),
                         double.title(asLink=True, textlink=True)))
                    oldtext = cat.text
                    # remove the old redirect from the old text,
                    # leaving behind any non-redirect text
                    oldtext = template_regex.sub("", oldtext)
                    newtext = (u"{{%(redirtemp)s|%(ncat)s}}" % {
                        'redirtemp': self.template_list[0],
                        'ncat': double.title(withNamespace=False)
                    })
                    newtext = newtext + oldtext.strip()
                    try:
                        cat.text = newtext
                        cat.save(
                            i18n.twtranslate(self.site,
                                             self.dbl_redir_comment))
                    except pywikibot.Error as e:
                        self.log_text.append("** Failed: %s" % e)
                continue

            found, moved = self.move_contents(cat_title,
                                              dest.title(withNamespace=False),
                                              editSummary=comment)
            if found is None:
                self.log_text.append(u"* [[:%s%s]]: error in move_contents" %
                                     (self.catprefix, cat_title))
            elif found:
                record[cat_title][today] = found
                self.log_text.append(u"* [[:%s%s]]: %d found, %d moved" %
                                     (self.catprefix, cat_title, found, moved))
            counts[cat_title] = found
            # do a null edit on cat
            try:
                cat.save()
            except:
                pass

        with open(datafile, "wb") as f:
            cPickle.dump(record, f, protocol=config.pickle_protocol)

        self.log_text.sort()
        self.problems.sort()
        newredirs.sort()
        comment = i18n.twtranslate(self.site, self.maint_comment)
        self.log_page.text = (
            u"\n== %i-%02i-%02iT%02i:%02i:%02iZ ==\n" % time.gmtime()[:6] +
            u'\n'.join(self.log_text) +
            u'\n* New redirects since last report:\n' + u'\n'.join(newredirs) +
            u'\n' + u'\n'.join(self.problems) + u'\n' + self.get_log_text())
        self.log_page.save(comment)
        if self.edit_requests:
            edit_request_page.text = (self.edit_request_text % {
                'itemlist':
                u"\n" + u"\n".join((self.edit_request_item % item)
                                   for item in self.edit_requests)
            })
            edit_request_page.save(comment)
Пример #47
0
def main(*args):
    """
    Process command line arguments and perform task.

    If args is an empty list, sys.argv is used.

    @param args: command line arguments
    @type args: str
    """
    # Loading the comments
    global categoryToCheck, project_inserted
    # always, define a generator to understand if the user sets one,
    # defining what's genFactory
    always = False
    generator = False
    show = False
    moveBlockCheck = False
    protectedpages = False
    protectType = 'edit'
    namespace = 0

    # Process global args and prepare generator args parser
    local_args = pywikibot.handle_args(args)
    genFactory = pagegenerators.GeneratorFactory()

    # Process local args
    for arg in local_args:
        option, sep, value = arg.partition(':')
        if option == '-always':
            always = True
        elif option == '-move':
            moveBlockCheck = True
        elif option == '-show':
            show = True
        elif option in ('-protectedpages', '-moveprotected'):
            protectedpages = True
            if option == '-moveprotected':
                protectType = 'move'
            if value:
                namespace = int(value)
        else:
            genFactory.handleArg(arg)

    if config.mylang not in project_inserted:
        pywikibot.output('Your project is not supported by this script.\n'
                         'You have to edit the script and add it!')
        return

    site = pywikibot.Site()

    if protectedpages:
        generator = site.protectedpages(namespace=namespace, type=protectType)
    # Take the right templates to use, the category and the comment
    TSP = i18n.translate(site, templateSemiProtection)
    TTP = i18n.translate(site, templateTotalProtection)
    TSMP = i18n.translate(site, templateSemiMoveProtection)
    TTMP = i18n.translate(site, templateTotalMoveProtection)
    TNR = i18n.translate(site, templateNoRegex)
    TU = i18n.translate(site, templateUnique)

    categories = i18n.translate(site, categoryToCheck)
    commentUsed = i18n.twtranslate(site, 'blockpageschecker-summary')
    if not generator:
        generator = genFactory.getCombinedGenerator()
    if not generator:
        generator = []
        pywikibot.output('Loading categories...')
        # Define the category if no other generator has been set
        for CAT in categories:
            cat = pywikibot.Category(site, CAT)
            # Define the generator
            gen = pagegenerators.CategorizedPageGenerator(cat)
            for pageCat in gen:
                generator.append(pageCat)
        pywikibot.output('Categories loaded, start!')
    # Main Loop
    if not genFactory.nopreload:
        generator = pagegenerators.PreloadingGenerator(generator, groupsize=60)
    for page in generator:
        pagename = page.title(as_link=True)
        pywikibot.output('Loading %s...' % pagename)
        try:
            text = page.text
        except pywikibot.NoPage:
            pywikibot.output("%s doesn't exist! Skipping..." % pagename)
            continue
        except pywikibot.IsRedirectPage:
            pywikibot.output('{} is a redirect! Skipping...'.format(pagename))
            if show:
                showQuest(page)
            continue
        # FIXME: This check does not work :
        # PreloadingGenerator cannot set correctly page.editRestriction
        # (see bug T57322)
        # if not page.has_permission():
        #    pywikibot.output(
        #        "%s is sysop-protected : this account can't edit "
        #        "it! Skipping..." % pagename)
        #    continue
        restrictions = page.protection()
        try:
            editRestr = restrictions['edit']
        except KeyError:
            editRestr = None
        if not page.has_permission():
            pywikibot.output('%s is protected: '
                             "this account can't edit it! Skipping..." %
                             pagename)
            continue

        # Understand, according to the template in the page, what should be the
        # protection and compare it with what there really is.
        TemplateInThePage = understandBlock(text, TTP, TSP, TSMP, TTMP, TU)
        # Only to see if the text is the same or not...
        oldtext = text
        # keep track of the changes for each step (edit then move)
        changes = -1

        if not editRestr:
            # page is not edit-protected
            # Deleting the template because the page doesn't need it.
            if not (TTP or TSP):
                raise pywikibot.Error(
                    'This script is not localized to use it on \n{0}. '
                    'Missing "templateSemiProtection" or'
                    '"templateTotalProtection"'.format(site.sitename))

            if TU:
                replaceToPerform = '|'.join(TTP + TSP + TU)
            else:
                replaceToPerform = '|'.join(TTP + TSP)
            text, changes = re.subn(
                '<noinclude>(%s)</noinclude>' % replaceToPerform, '', text)
            if changes == 0:
                text, changes = re.subn('(%s)' % replaceToPerform, '', text)
            msg = 'The page is editable for all'
            if not moveBlockCheck:
                msg += ', deleting the template..'
            pywikibot.output(msg + '.')

        elif editRestr[0] == 'sysop':
            # total edit protection
            if (TemplateInThePage[0] == 'sysop-total' and TTP) or \
               (TemplateInThePage[0] == 'unique' and TU):
                msg = 'The page is protected to the sysop'
                if not moveBlockCheck:
                    msg += ', skipping...'
                pywikibot.output(msg)
            else:
                if not TNR or TU and not TNR[4] or not (TU or TNR[1]):
                    raise pywikibot.Error(
                        'This script is not localized to use it on \n{0}. '
                        'Missing "templateNoRegex"'.format(site.sitename))

                pywikibot.output('The page is protected to the sysop, but the '
                                 'template seems not correct. Fixing...')
                if TU:
                    text, changes = re.subn(TemplateInThePage[1], TNR[4], text)
                else:
                    text, changes = re.subn(TemplateInThePage[1], TNR[1], text)

        elif TSP or TU:
            # implicitly editRestr[0] = 'autoconfirmed', edit-Semi-protection
            if TemplateInThePage[0] == 'autoconfirmed-total' or \
               TemplateInThePage[0] == 'unique':
                msg = 'The page is editable only for the autoconfirmed users'
                if not moveBlockCheck:
                    msg += ', skipping...'
                pywikibot.output(msg)
            else:
                if not TNR or TU and not TNR[4] or not (TU or TNR[1]):
                    raise pywikibot.Error(
                        'This script is not localized to use it on \n{0}. '
                        'Missing "templateNoRegex"'.format(site.sitename))
                pywikibot.output('The page is editable only for the '
                                 'autoconfirmed users, but the template '
                                 'seems not correct. Fixing...')
                if TU:
                    text, changes = re.subn(TemplateInThePage[1], TNR[4], text)
                else:
                    text, changes = re.subn(TemplateInThePage[1], TNR[0], text)

        if changes == 0:
            # We tried to fix edit-protection templates, but it did not work.
            pywikibot.warning('No edit-protection template could be found')

        if moveBlockCheck and changes > -1:
            # checking move protection now
            try:
                moveRestr = restrictions['move']
            except KeyError:
                moveRestr = False
            changes = -1

            if not moveRestr:
                pywikibot.output('The page is movable for all, deleting the '
                                 'template...')
                # Deleting the template because the page doesn't need it.
                if TU:
                    replaceToPerform = '|'.join(TSMP + TTMP + TU)
                else:
                    replaceToPerform = '|'.join(TSMP + TTMP)
                text, changes = re.subn(
                    '<noinclude>(%s)</noinclude>' % replaceToPerform, '', text)
                if changes == 0:
                    text, changes = re.subn('({})'.format(replaceToPerform),
                                            '', text)
            elif moveRestr[0] == 'sysop':
                # move-total-protection
                if (TemplateInThePage[0] == 'sysop-move' and TTMP) or \
                   (TemplateInThePage[0] == 'unique' and TU):
                    pywikibot.output('The page is protected from moving to '
                                     'the sysop, skipping...')
                    if TU:
                        # no changes needed, better to revert the old text.
                        text = oldtext
                else:
                    pywikibot.output('The page is protected from moving to '
                                     'the sysop, but the template seems not '
                                     'correct. Fixing...')
                    if TU:
                        text, changes = re.subn(TemplateInThePage[1], TNR[4],
                                                text)
                    else:
                        text, changes = re.subn(TemplateInThePage[1], TNR[3],
                                                text)

            elif TSMP or TU:
                # implicitly moveRestr[0] = 'autoconfirmed',
                # move-semi-protection
                if TemplateInThePage[0] == 'autoconfirmed-move' or \
                   TemplateInThePage[0] == 'unique':
                    pywikibot.output('The page is movable only for the '
                                     'autoconfirmed users, skipping...')
                    if TU:
                        # no changes needed, better to revert the old text.
                        text = oldtext
                else:
                    pywikibot.output('The page is movable only for the '
                                     'autoconfirmed users, but the template '
                                     'seems not correct. Fixing...')
                    if TU:
                        text, changes = re.subn(TemplateInThePage[1], TNR[4],
                                                text)
                    else:
                        text, changes = re.subn(TemplateInThePage[1], TNR[2],
                                                text)

            if changes == 0:
                # We tried to fix move-protection templates but it did not work
                pywikibot.warning('No move-protection template could be found')

        if oldtext != text:
            # Ok, asking if the change has to be performed and do it if yes.
            pywikibot.output(
                color_format('\n\n>>> {lightpurple}{0}{default} <<<',
                             page.title()))
            pywikibot.showDiff(oldtext, text)
            if not always:
                choice = pywikibot.input_choice(
                    'Do you want to accept these '
                    'changes?', [('Yes', 'y'), ('No', 'n'), ('All', 'a')], 'n')
                if choice == 'a':
                    always = True
            if always or choice == 'y':
                save_page(page, text, commentUsed)
Пример #48
0
def main(*args):
    """
    Process command line arguments and invoke bot.

    If args is an empty list, sys.argv is used.

    @param args: command line arguments
    @type args: str
    """

    local_args = pywikibot.handle_args(args)

    # default values for options
    extra_summary = None

    for arg in local_args:
        option, sep, value = arg.partition(':')
        if option == '-summary':
            extra_summary = value
        else:
            pywikibot.warning("Unrecognized option {}".format(option))


    def check_option(option, value):
        if not value:
            pywikibot.error("Missing argument for option '{}'".format(option))
            return False
        return True


    page_number_regex = re.compile('\|([1-9][0-9]*)\}')
    filename_number_regex = re.compile('([1-9][0-9]*)')
    templates_ready = ['QC image', 'File information', 'Self']
    site = pywikibot.Site()
    looked_at = set()
    pages = request_pages()
    for p in pages:
        if p['title'] in looked_at:
            pywikibot.output("Done.")
            break
        else:
            looked_at.add(p['title'])
        try:
            page_title = 'File:' + p['title']
            page = pywikibot.Page(site, page_title)
            click_url = ROOT_URL + 'wiki/' + page.title(underscore=True)
            pywikibot.output("Page '{0}', id={1} | {2}".format(page_title, p['id'], click_url))
            ts = page.templatesWithParams()
            if len(ts) > 0:
                found_ready = False
                for t in ts:
                    for r in templates_ready:
                        if r in t[0].title():
                            pywikibot.output(color_format("Page {lightgreen}{0}{default} has template: {1}",
                                page_title, t[0]))
                            found_ready = True
                            break
                if found_ready:
                    pywikibot.output("\tSkipping.")
                    continue

            old_text = page.get()
            # categories = getCategoryLinks(old_text, site)
            # categories_text = '\n'.join(map(lambda c:c.aslink(), categories))
            (header, body, footer) = extract_sections(old_text, site)
            summary = None
            licensing = None
            description = None
            for section in body:
                if 'ummary' in section[0] or 'escription' in section[0]:
                    summary = section[1]
                if 'icens' in section[0]:
                    licensing = section[1]
            got_summary_from_header = False
            if summary is None:
                got_summary_from_header = True
                summary = header

            new_text = None
            pywikibot.output(color_format("Editing page {lightblue}{0}{default}.", page_title))
            if summary is not None and len(summary.strip()) > 0:
                summary = summary.strip()
                pywikibot.output("Have \"Summary\":\n\t{}".format(summary))
                i = summary.find('{')
                if i > 0:
                    summary = summary[0:i]
                i = summary.find(' in ')
                if i > 0:
                    summary = summary[0:i]
                summary = summary.strip()
                if summary[-1] == '.':
                    summary = summary[0:-1]
                pywikibot.output("Will have \"Summary\":\n\t{}".format(summary))
                choice = pywikibot.input_choice("Is it a good summary?",
                    [('Yes', 'y'), ('No', 'n'), ('open in Browser', 'b')], 'n')
                if choice == 'y':
                    description = summary
                elif choice == 'n':
                    pass
                elif choice == 'b':
                    pywikibot.bot.open_webbrowser(page)
            if description is None:
                pywikibot.output("Type '[s]kip' to skip the image completely.")
                description = pywikibot.input("Please describe the file:")
                if description in ['s', 'skip']:
                    continue
            if licensing is not None:
                pywikibot.output("Have \"Licensing\":\n\t{}".format(licensing.strip()))

            comic_num = None
            m = page_number_regex.search(old_text)
            if m:
                try:
                    comic_num = int(m.group(1))
                except:
                    pass
            if comic_num is None:
                m = filename_number_regex.search(page.title())
                if m:
                    try:
                        comic_num = int(m.group(1))
                    except:
                        pass
            if comic_num is not None:
                pywikibot.output("Have comic #:\n\t{}".format(comic_num))
                choice = pywikibot.input_choice("Is it a good comic number?",
                    [('Yes', 'y'), ('No', 'n'), ('open in Browser', 'b')], 'n')
                if choice == 'y':
                    pass
                else:
                    comic_num = None
                if choice == 'b':
                    pywikibot.bot.open_webbrowser(page)
            while comic_num is None:
                try:
                    pywikibot.output("Need comic number. Type 0 to skip")
                    comic_num = int(pywikibot.input("Comic number: "))
                except ValueError:
                    pass
            if comic_num == 0:
                comic_num = ''

            new_text = dedent("""
                == Summary ==
                {{{{QC image|{0}|{1}}}}}

                == Licensing ==
                {{{{Fairuse}}}}
                """.format(description, comic_num)).strip()
            header = header.strip()
            if not got_summary_from_header and len(header) > 0:
                new_text = header + '\n\n' + new_text
            footer = footer.strip()
            if len(footer) > 0:
                new_text += '\n\n' + footer

            # check if the edit is sensible
            if old_text == new_text:
                pywikibot.output("No changes. Nothing to do.")
                continue
            # report what will happen
            pywikibot.showDiff(old_text, new_text, context=3)

            summary = "add [[Template:QC image]]; mark as fair use " + \
                "([[User:AndrybakBot#Image maintenance|Image maintenance bot task]])"
            if extra_summary:
                summary = summary + " ({})".format(extra_summary)
            pywikibot.output(color_format("Summary will be" +
                "\n\t{lightblue}{0}{default}", summary))
            choice = pywikibot.input_choice(
                "Do you want to accept these changes?",
                [('Yes', 'y'), ('No', 'n'), ('open in Browser', 'b')], 'n')
            # if choice == 'y':
            #     pywikibot.output("Test run, doing nothing.")
            #     continue
            if choice == 'n':
                pywikibot.output("Okay, doing nothing.")
                continue
            elif choice == 'b':
                pywikibot.bot.open_webbrowser(page)
            elif choice == 'y':
                error_count = 0
                while True:
                    result = put_text(page, new_text, summary, error_count)
                    if result is not None:
                        pywikibot.output("Got result of saving: {}".format(result))
                        break
                    error_count += 1
                continue
            elif choice == 'q':
                break

        except pywikibot.NoPage:
            pywikibot.error("{} doesn't exist, skipping.".format(page.title()))
            continue
        except pywikibot.IsRedirectPage:
            pywikibot.error("{} is a redirect, skipping".format(page.title()))
            continue
        except pywikibot.Error as e:
            pywikibot.bot.suggest_help(exception=e)
            continue
        except QuitKeyboardInterrupt:
            sys.exit("User quit bot run.")
        else:
            pass
Пример #49
0
 def __iter__(self):
     """Iterator."""
     n = 0
     event = None
     while self._total is None or n < self._total:
         if not hasattr(self, 'source'):
             self.source = EventSource(**self.sse_kwargs)
             # sseclient >= 0.0.18 is required for eventstreams (T184713)
             # we don't have a version string inside but the instance
             # variable 'chunk_size' was newly introduced with 0.0.18
             if not hasattr(self.source, 'chunk_size'):
                 warning(
                     'You may not have the right sseclient version;\n'
                     'sseclient >= 0.0.18 is required for eventstreams.\n'
                     "Install it with 'pip install \"sseclient>=0.0.18\"'")
         try:
             event = next(self.source)
         except (ProtocolError, socket.error, httplib.IncompleteRead) as e:
             warning('Connection error: {0}.\n'
                     'Try to re-establish connection.'.format(e))
             del self.source
             if event is not None:
                 self.sse_kwargs['last_id'] = event.id
             continue
         if event.event == 'message':
             if event.data:
                 try:
                     element = json.loads(event.data)
                 except ValueError as e:
                     warning(
                         'Could not load json data from\n{0}\n{1}'.format(
                             event, e))
                 else:
                     if self.streamfilter(element):
                         n += 1
                         yield element
             else:
                 warning('Empty message found.')
         elif event.event == 'error':
             warning('Encountered error: {0}'.format(event.data))
         else:
             warning('Unknown event {0} occured.'.format(event.event))
     else:
         debug(
             '{0}: Stopped iterating due to '
             'exceeding item limit.'.format(self.__class__.__name__),
             _logger)
     del self.source
Пример #50
0
def main(*args):
    """
    Process command line arguments and invoke bot.

    If args is an empty list, sys.argv is used.

    @param args: command line arguments
    @type args: list of unicode
    """
    add_cat = None
    gen = None
    # summary message
    edit_summary = u""
    # Array which will collect commandline parameters.
    # First element is original text, second element is replacement text.
    commandline_replacements = []
    # A list of 2-tuples of original text and replacement text.
    replacements = []
    # Don't edit pages which contain certain texts.
    exceptions = {
        'title': [],
        'text-contains': [],
        'inside': [],
        'inside-tags': [],
        'require-title': [],  # using a seperate requirements dict needs some
    }  # major refactoring of code.

    # Should the elements of 'replacements' and 'exceptions' be interpreted
    # as regular expressions?
    regex = False
    # Predefined fixes from dictionary 'fixes' (see above).
    fixes_set = []
    # the dump's path, either absolute or relative, which will be used
    # if -xml flag is present
    xmlFilename = None
    useSql = False
    # will become True when the user presses a ('yes to all') or uses the
    # -always flag.
    acceptall = False
    # Will become True if the user inputs the commandline parameter -nocase
    caseInsensitive = False
    # Will become True if the user inputs the commandline parameter -dotall
    dotall = False
    # Will become True if the user inputs the commandline parameter -multiline
    multiline = False
    # Do all hits when they overlap
    allowoverlap = False
    # Do not recurse replacement
    recursive = False
    # Between a regex and another (using -fix) sleep some time (not to waste
    # too much CPU
    sleep = None
    # Request manual replacements even if replacements are already defined
    manual_input = False
    # Replacements loaded from a file
    replacement_file = None
    replacement_file_arg_misplaced = False

    # Read commandline parameters.

    local_args = pywikibot.handle_args(args)
    genFactory = pagegenerators.GeneratorFactory()

    for arg in local_args:
        if genFactory.handleArg(arg):
            continue
        if arg == '-regex':
            regex = True
        elif arg.startswith('-xmlstart'):
            if len(arg) == 9:
                xmlStart = pywikibot.input(
                    u'Please enter the dumped article to start with:')
            else:
                xmlStart = arg[10:]
        elif arg.startswith('-xml'):
            if len(arg) == 4:
                xmlFilename = i18n.input('pywikibot-enter-xml-filename')
            else:
                xmlFilename = arg[5:]
        elif arg == '-sql':
            useSql = True
        elif arg.startswith('-excepttitle:'):
            exceptions['title'].append(arg[13:])
        elif arg.startswith('-requiretitle:'):
            exceptions['require-title'].append(arg[14:])
        elif arg.startswith('-excepttext:'):
            exceptions['text-contains'].append(arg[12:])
        elif arg.startswith('-exceptinside:'):
            exceptions['inside'].append(arg[14:])
        elif arg.startswith('-exceptinsidetag:'):
            exceptions['inside-tags'].append(arg[17:])
        elif arg.startswith('-fix:'):
            fixes_set += [arg[5:]]
        elif arg.startswith('-sleep:'):
            sleep = float(arg[7:])
        elif arg == '-always':
            acceptall = True
        elif arg == '-recursive':
            recursive = True
        elif arg == '-nocase':
            caseInsensitive = True
        elif arg == '-dotall':
            dotall = True
        elif arg == '-multiline':
            multiline = True
        elif arg.startswith('-addcat:'):
            add_cat = arg[8:]
        elif arg.startswith('-summary:'):
            edit_summary = arg[9:]
        elif arg.startswith('-automaticsummary'):
            edit_summary = True
        elif arg.startswith('-allowoverlap'):
            allowoverlap = True
        elif arg.startswith('-manualinput'):
            manual_input = True
        elif arg.startswith('-replacementfile'):
            issue_deprecation_warning('-replacementfile', '-pairsfile', 2,
                                      ArgumentDeprecationWarning)
        elif arg.startswith('-pairsfile'):
            if len(commandline_replacements) % 2:
                replacement_file_arg_misplaced = True

            if arg == '-pairsfile':
                replacement_file = pywikibot.input(
                    u'Please enter the filename to read replacements from:')
            else:
                replacement_file = arg[len('-pairsfile:'):]
        else:
            commandline_replacements.append(arg)

    site = pywikibot.Site()

    if len(commandline_replacements) % 2:
        pywikibot.error('Incomplete command line pattern replacement pair.')
        return False

    if replacement_file_arg_misplaced:
        pywikibot.error('-pairsfile used between a pattern replacement pair.')
        return False

    if replacement_file:
        try:
            with codecs.open(replacement_file, 'r', 'utf-8') as f:
                # strip newlines, but not other characters
                file_replacements = f.read().splitlines()
        except (IOError, OSError) as e:
            pywikibot.error(u'Error loading {0}: {1}'.format(
                replacement_file, e))
            return False

        if len(file_replacements) % 2:
            pywikibot.error(
                '{0} contains an incomplete pattern replacement pair.'.format(
                    replacement_file))
            return False

        # Strip BOM from first line
        file_replacements[0].lstrip(u'\uFEFF')
        commandline_replacements.extend(file_replacements)

    if not (commandline_replacements or fixes_set) or manual_input:
        old = pywikibot.input('Please enter the text that should be replaced:')
        while old:
            new = pywikibot.input(u'Please enter the new text:')
            commandline_replacements += [old, new]
            old = pywikibot.input(
                'Please enter another text that should be replaced,'
                '\nor press Enter to start:')

    # The summary stored here won't be actually used but is only an example
    single_summary = None
    for i in range(0, len(commandline_replacements), 2):
        replacement = Replacement(commandline_replacements[i],
                                  commandline_replacements[i + 1])
        if not single_summary:
            single_summary = i18n.twtranslate(site, 'replace-replacing', {
                'description':
                ' (-%s +%s)' % (replacement.old, replacement.new)
            })
        replacements.append(replacement)

    # Perform one of the predefined actions.
    missing_fixes_summaries = []  # which a fixes/replacements miss a summary
    for fix_name in fixes_set:
        try:
            fix = fixes.fixes[fix_name]
        except KeyError:
            pywikibot.output(u'Available predefined fixes are: %s' %
                             ', '.join(fixes.fixes.keys()))
            if not fixes.user_fixes_loaded:
                pywikibot.output('The user fixes file could not be found: '
                                 '{0}'.format(fixes.filename))
            return
        if not fix['replacements']:
            pywikibot.warning('No replacements defined for fix '
                              '"{0}"'.format(fix_name))
            continue
        if "msg" in fix:
            if isinstance(fix['msg'], basestring):
                set_summary = i18n.twtranslate(site, str(fix['msg']))
            else:
                set_summary = i18n.translate(site, fix['msg'], fallback=True)
        else:
            set_summary = None
        replacement_set = ReplacementList(fix.get('regex'),
                                          fix.get('exceptions'),
                                          fix.get('nocase'),
                                          set_summary,
                                          name=fix_name)
        # Whether some replacements have a summary, if so only show which
        # have none, otherwise just mention the complete fix
        missing_fix_summaries = []
        for index, replacement in enumerate(fix['replacements'], start=1):
            summary = None if len(replacement) < 3 else replacement[2]
            if not set_summary and not summary:
                missing_fix_summaries.append('"{0}" (replacement #{1})'.format(
                    fix_name, index))
            if chars.contains_invisible(replacement[0]):
                pywikibot.warning('The old string "{0}" contains formatting '
                                  'characters like U+200E'.format(
                                      chars.replace_invisible(replacement[0])))
            if (not callable(replacement[1])
                    and chars.contains_invisible(replacement[1])):
                pywikibot.warning('The new string "{0}" contains formatting '
                                  'characters like U+200E'.format(
                                      chars.replace_invisible(replacement[1])))
            replacement_set.append(
                ReplacementListEntry(
                    old=replacement[0],
                    new=replacement[1],
                    fix_set=replacement_set,
                    edit_summary=summary,
                ))

        # Exceptions specified via 'fix' shall be merged to those via CLI.
        if replacement_set:
            replacements.extend(replacement_set)
            if replacement_set._exceptions is not None:
                for k, v in replacement_set._exceptions.items():
                    if k in exceptions:
                        exceptions[k] = list(set(exceptions[k]) | set(v))
                    else:
                        exceptions[k] = v

        if len(fix['replacements']) == len(missing_fix_summaries):
            missing_fixes_summaries.append(
                '"{0}" (all replacements)'.format(fix_name))
        else:
            missing_fixes_summaries += missing_fix_summaries

    if ((not edit_summary or edit_summary is True)
            and (missing_fixes_summaries or single_summary)):
        if single_summary:
            pywikibot.output(u'The summary message for the command line '
                             'replacements will be something like: %s' %
                             single_summary)
        if missing_fixes_summaries:
            pywikibot.output('The summary will not be used when the fix has '
                             'one defined but the following fix(es) do(es) '
                             'not have a summary defined: '
                             '{0}'.format(', '.join(missing_fixes_summaries)))
        if edit_summary is not True:
            edit_summary = pywikibot.input(
                'Press Enter to use this automatic message, or enter a '
                'description of the\nchanges your bot will make:')
        else:
            edit_summary = ''

    # Set the regular expression flags
    flags = re.UNICODE
    if caseInsensitive:
        flags = flags | re.IGNORECASE
    if dotall:
        flags = flags | re.DOTALL
    if multiline:
        flags = flags | re.MULTILINE

    # Pre-compile all regular expressions here to save time later
    for replacement in replacements:
        replacement.compile(regex, flags)

    precompile_exceptions(exceptions, regex, flags)

    if xmlFilename:
        try:
            xmlStart
        except NameError:
            xmlStart = None
        gen = XmlDumpReplacePageGenerator(xmlFilename, xmlStart, replacements,
                                          exceptions, site)
    elif useSql:
        whereClause = 'WHERE (%s)' % ' OR '.join([
            "old_text RLIKE '%s'" % prepareRegexForMySQL(old_regexp.pattern)
            for (old_regexp, new_text) in replacements
        ])
        if exceptions:
            exceptClause = 'AND NOT (%s)' % ' OR '.join([
                "old_text RLIKE '%s'" % prepareRegexForMySQL(exc.pattern)
                for exc in exceptions
            ])
        else:
            exceptClause = ''
        query = u"""
SELECT page_namespace, page_title
FROM page
JOIN text ON (page_id = old_id)
%s
%s
LIMIT 200""" % (whereClause, exceptClause)
        gen = pagegenerators.MySQLPageGenerator(query)

    gen = genFactory.getCombinedGenerator(gen, preload=True)

    if not gen:
        pywikibot.bot.suggest_help(missing_generator=True)
        return False

    bot = ReplaceRobot(gen,
                       replacements,
                       exceptions,
                       allowoverlap,
                       recursive,
                       add_cat,
                       sleep,
                       edit_summary,
                       always=acceptall,
                       site=site)
    site.login()
    bot.run()

    # Explicitly call pywikibot.stopme(). It will make sure the callback is
    # triggered before replace.py is unloaded.
    pywikibot.stopme()
    pywikibot.output(u'\n%s pages changed.' % bot.changed_pages)
Пример #51
0
def main(*args):
    """
    Process command line arguments and invoke bot.

    If args is an empty list, sys.argv is used.

    @param args: command line arguments
    @type args: unicode
    """
    local_args = pywikibot.handle_args(args)

    group_id = ''
    photoset_id = ''
    user_id = ''
    start_id = ''
    end_id = ''
    tags = ''
    addCategory = ''
    removeCategories = False
    autonomous = False
    totalPhotos = 0
    uploadedPhotos = 0

    # Do we mark the images as reviewed right away?
    if config.flickr['review']:
        flickrreview = config.flickr['review']
    else:
        flickrreview = False

    # Set the Flickr reviewer
    if config.flickr['reviewer']:
        reviewer = config.flickr['reviewer']
    elif 'commons' in config.sysopnames['commons']:
        pywikibot.output(config.sysopnames['commons'])
        reviewer = config.sysopnames['commons']['commons']
    elif 'commons' in config.usernames['commons']:
        reviewer = config.usernames['commons']['commons']
    else:
        reviewer = ''

    # Should be renamed to overrideLicense or something like that
    override = ''
    for arg in local_args:
        if arg.startswith('-group_id'):
            if len(arg) == 9:
                group_id = pywikibot.input('What is the group_id of the pool?')
            else:
                group_id = arg[10:]
        elif arg.startswith('-photoset_id'):
            if len(arg) == 12:
                photoset_id = pywikibot.input('What is the photoset_id?')
            else:
                photoset_id = arg[13:]
        elif arg.startswith('-user_id'):
            if len(arg) == 8:
                user_id = pywikibot.input(
                    'What is the user_id of the flickr user?')
            else:
                user_id = arg[9:]
        elif arg.startswith('-start_id'):
            if len(arg) == 9:
                start_id = pywikibot.input(
                    'What is the id of the photo you want to start at?')
            else:
                start_id = arg[10:]
        elif arg.startswith('-end_id'):
            if len(arg) == 7:
                end_id = pywikibot.input(
                    'What is the id of the photo you want to end at?')
            else:
                end_id = arg[8:]
        elif arg.startswith('-tags'):
            if len(arg) == 5:
                tags = pywikibot.input(
                    'What is the tag you want to filter out (currently only '
                    'one supported)?')
            else:
                tags = arg[6:]
        elif arg == '-flickrreview':
            flickrreview = True
        elif arg.startswith('-reviewer'):
            if len(arg) == 9:
                reviewer = pywikibot.input('Who is the reviewer?')
            else:
                reviewer = arg[10:]
        elif arg.startswith('-override'):
            if len(arg) == 9:
                override = pywikibot.input('What is the override text?')
            else:
                override = arg[10:]
        elif arg.startswith('-addcategory'):
            if len(arg) == 12:
                addCategory = pywikibot.input(
                    'What category do you want to add?')
            else:
                addCategory = arg[13:]
        elif arg == '-removecategories':
            removeCategories = True
        elif arg == '-autonomous':
            autonomous = True

    if isinstance(flickrapi, Exception):
        pywikibot.error('This script requires the python flickrapi module. \n'
                        'See: http://stuvel.eu/projects/flickrapi')

    elif not config.flickr['api_key']:
        pywikibot.warning('Flickr api key not found! Get yourself an api key\n'
                          'Any flickr user can get a key at\n'
                          'https://www.flickr.com/services/api/keys/apply/')

    elif user_id or group_id or photoset_id:
        if 'api_secret' in config.flickr and config.flickr['api_secret']:
            flickr = flickrapi.FlickrAPI(config.flickr['api_key'],
                                         config.flickr['api_secret'])
        else:
            pywikibot.output('Accessing public content only')
            flickr = flickrapi.FlickrAPI(config.flickr['api_key'])

        for photo_id in getPhotos(flickr, user_id, group_id, photoset_id,
                                  start_id, end_id, tags):
            uploadedPhotos += processPhoto(flickr, photo_id, flickrreview,
                                           reviewer, override, addCategory,
                                           removeCategories, autonomous)
            totalPhotos += 1
        pywikibot.output('Finished running')
        pywikibot.output('Total photos: ' + str(totalPhotos))
        pywikibot.output('Uploaded photos: ' + str(uploadedPhotos))
Пример #52
0
def main(*args):
    """
    Process command line arguments and invoke bot.

    If args is an empty list, sys.argv is used.

    @param args: command line arguments
    @type args: list of unicode
    """
    oldName = None
    options = {}
    fromToPairs = []

    # Process global args and prepare generator args parser
    local_args = pywikibot.handle_args(args)
    genFactory = pagegenerators.GeneratorFactory()

    for arg in local_args:
        if arg == '-pairs' or arg.startswith('-pairs:'):
            issue_deprecation_warning('-pairs', '-pairsfile', 2,
                                      ArgumentDeprecationWarning)
        elif arg.startswith('-pairsfile'):
            if len(arg) == len('-pairsfile'):
                filename = pywikibot.input(
                    u'Enter the name of the file containing pairs:')
            else:
                filename = arg[len('-pairsfile:'):]
            oldName1 = None
            for page in pagegenerators.TextfilePageGenerator(filename):
                if oldName1:
                    fromToPairs.append([oldName1, page.title()])
                    oldName1 = None
                else:
                    oldName1 = page.title()
            if oldName1:
                pywikibot.warning(u'file %s contains odd number of links' %
                                  filename)
        elif arg == '-noredirect':
            options['noredirect'] = True
        elif arg == '-notalkpage':
            options['movetalkpage'] = False
        elif arg == '-always':
            options['always'] = True
        elif arg == '-skipredirects':
            options['skipredirects'] = True
        elif arg.startswith('-from:'):
            if oldName:
                pywikibot.warning(u'-from:%s without -to:' % oldName)
            oldName = arg[len('-from:'):]
        elif arg.startswith('-to:'):
            if oldName:
                fromToPairs.append([oldName, arg[len('-to:'):]])
                oldName = None
            else:
                pywikibot.warning(u'%s without -from' % arg)
        elif arg.startswith('-prefix'):
            if len(arg) == len('-prefix'):
                options['prefix'] = pywikibot.input(u'Enter the prefix:')
            else:
                options['prefix'] = arg[8:]
        elif arg.startswith('-summary'):
            if len(arg) == len('-summary'):
                options['summary'] = pywikibot.input(u'Enter the summary:')
            else:
                options['summary'] = arg[9:]
        else:
            genFactory.handleArg(arg)

    if oldName:
        pywikibot.warning(u'-from:%s without -to:' % oldName)
    site = pywikibot.Site()
    for pair in fromToPairs:
        page = pywikibot.Page(site, pair[0])
        bot = MovePagesBot(None, **options)
        bot.moveOne(page, pair[1])

    gen = genFactory.getCombinedGenerator(preload=True)
    if gen:
        bot = MovePagesBot(gen, **options)
        bot.run()
        return True

    if not fromToPairs:
        pywikibot.bot.suggest_help(missing_generator=True)
        return False
    else:
        return True
Пример #53
0
def main(*args):
    """
    Process command line arguments and invoke bot.

    If args is an empty list, sys.argv is used.

    @param args: command line arguments
    @type args: str
    """
    local_args = pywikibot.handle_args(args)

    fromsite = pywikibot.Site()
    tolang = fromsite.code
    tofamily = fromsite.family.name
    prefix = ''
    overwrite = False
    target = False
    gen_args = []

    for arg in local_args:
        if arg.startswith('-tofamily'):
            tofamily = arg[len('-tofamily:'):]
        elif arg.startswith('-tolang'):
            tolang = arg[len('-tolang:'):]
        elif arg.startswith('-prefix'):
            prefix = arg[len('-prefix:'):]
        elif arg == '-overwrite':
            overwrite = True
        elif arg == '-target':
            target = True
        else:
            gen_args.append(arg)

    tosite = pywikibot.Site(tolang, tofamily)
    additional_text = ('Target site not different from source site.'
                       if fromsite == tosite else '')

    gen_factory = pagegenerators.GeneratorFactory(
        site=tosite if target else fromsite)
    unknown_args = [arg for arg in gen_args if not gen_factory.handleArg(arg)]

    gen = gen_factory.getCombinedGenerator()

    if suggest_help(missing_generator=not gen,
                    additional_text=additional_text,
                    unknown_parameters=unknown_args):
        return

    gen_args = ' '.join(gen_args)
    pywikibot.output("""
    Page transfer configuration
    ---------------------------
    Source: {fromsite}
    Target: {tosite}

    Generator of pages to transfer: {gen_args}
    {target}
    Prefix for transferred pages: {prefix}
    """.format(fromsite=fromsite,
               tosite=tosite,
               gen_args=gen_args,
               prefix=prefix if prefix else '(none)',
               target='from target site\n' if target else ''))

    for page in gen:
        title = page.namespace().canonical_prefix() + page.title(with_ns=False)
        if target:
            # page is at target site, fetch it from source
            target_title = prefix + page.title()
            page = pywikibot.Page(fromsite, title)
        else:
            target_title = (prefix + title)
        targetpage = pywikibot.Page(tosite, target_title)
        edithistpage = pywikibot.Page(tosite, target_title + '/edithistory')

        if targetpage.exists():
            if not overwrite:
                pywikibot.warning(
                    'Skipped {0} (target page {1} exists)'.format(
                        page.title(as_link=True, force_interwiki=True),
                        targetpage.title(as_link=True)))
                continue
            if not targetpage.botMayEdit():
                pywikibot.warning(
                    'Target page {0} is not editable by bots'.format(
                        targetpage.title(as_link=True)))
                continue

        if not page.exists():
            pywikibot.warning("Page {0} doesn't exist".format(
                page.title(as_link=True)))
            continue

        pywikibot.output('Moving {0} to {1}...'.format(
            page.title(as_link=True, force_interwiki=True),
            targetpage.title(as_link=True)))

        pywikibot.log('Getting page text.')
        text = page.get(get_redirect=True)
        source_link = page.title(as_link=True, insite=targetpage.site)
        text += (
            '<noinclude>\n\n<small>This page was moved from {0}. Its '
            'edit history can be viewed at {1}</small></noinclude>'.format(
                source_link,
                edithistpage.title(as_link=True, insite=targetpage.site)))

        pywikibot.log('Getting edit history.')
        historytable = page.getVersionHistoryTable()

        pywikibot.log('Putting edit history.')
        summary = 'Moved page from {source}'.format(source=source_link)
        edithistpage.put(historytable, summary=summary)

        pywikibot.log('Putting page text.')
        edithist_link = ' ([[{target}/edithistory|history]])'.format(
            target=targetpage.title(
            ) if not targetpage.namespace().subpages else '')
        summary += edithist_link
        targetpage.put(text, summary=summary)
Пример #54
0
def processPhoto(flickr,
                 photo_id='',
                 flickrreview=False,
                 reviewer='',
                 override='',
                 addCategory='',
                 removeCategories=False,
                 autonomous=False):
    """Process a single Flickr photo.

    For each image:
      * Check the license
      * Check if it isn't already on Commons
      * Build suggested filename
        * Check for name collision and maybe alter it
      * Pull description from Flinfo
      * Show image and description to user
        * Add a nice hotcat lookalike for the adding of categories
        * Filter the categories
      * Upload the image
    """
    if photo_id:
        pywikibot.output(str(photo_id))
        (photoInfo, photoSizes) = getPhoto(flickr, photo_id)
    if isAllowedLicense(photoInfo) or override:
        # Get the url of the largest photo
        photoUrl = getPhotoUrl(photoSizes)
        # Should download the photo only once
        photo = downloadPhoto(photoUrl)

        # Don't upload duplicate images, should add override option
        duplicates = findDuplicateImages(photo)
        if duplicates:
            pywikibot.output('Found duplicate image at {}'.format(
                duplicates.pop()))
        else:
            filename = getFilename(photoInfo)
            flinfoDescription = getFlinfoDescription(photo_id)
            photoDescription = buildDescription(flinfoDescription,
                                                flickrreview, reviewer,
                                                override, addCategory,
                                                removeCategories)
            # pywikibot.output(photoDescription)
            if not isinstance(Tkdialog, ImportError) and not autonomous:
                try:
                    (newPhotoDescription, newFilename,
                     skip) = Tkdialog(photoDescription, photo,
                                      filename).show_dialog()
                except ImportError as e:
                    pywikibot.warning(e)
                    pywikibot.warning('Switching to autonomous mode.')
                    autonomous = True
            elif not autonomous:
                pywikibot.warning('Switching to autonomous mode because GUI '
                                  'interface cannot be used')
                pywikibot.warning(Tkdialog)
                autonomous = True
            if autonomous:
                newPhotoDescription = photoDescription
                newFilename = filename
                skip = False

            # Do the actual upload
            # Would be nice to check before I upload if the file is already at
            # Commons. Not that important for this program, but maybe for
            # derived programs
            if not skip:
                bot = UploadRobot(photoUrl,
                                  description=newPhotoDescription,
                                  useFilename=newFilename,
                                  keepFilename=True,
                                  verifyDescription=False)
                bot.upload_image(debug=False)
                return 1
    else:
        pywikibot.output('Invalid license')
    return 0
Пример #55
0
    def badNameFilter(self, name, force=False):
        """Check for bad names."""
        if not globalvar.filtBadName:
            return False

        # initialize blacklist
        if not hasattr(self, '_blacklist') or force:
            elenco = [
                ' ano',
                ' anus',
                'anal ',
                'babies',
                'baldracca',
                'balle',
                'bastardo',
                'bestiali',
                'bestiale',
                'bastarda',
                'b.i.t.c.h.',
                'bitch',
                'boobie',
                'bordello',
                'breast',
                'cacata',
                'cacca',
                'cachapera',
                'cagata',
                'cane',
                'cazz',
                'cazzo',
                'cazzata',
                'chiavare',
                'chiavata',
                'chick',
                'christ ',
                'cristo',
                'clitoride',
                'coione',
                'cojdioonear',
                'cojones',
                'cojo',
                'coglione',
                'coglioni',
                'cornuto',
                'cula',
                'culatone',
                'culattone',
                'culo',
                'deficiente',
                'deficente',
                'dio',
                'die ',
                'died ',
                'ditalino',
                'ejackulate',
                'enculer',
                'eroticunt',
                'fanculo',
                'f******o',
                'fica ',
                'ficken',
                'figa',
                'sfiga',
                'fottere',
                'fotter',
                'fottuto',
                'f**k',
                'f.u.c.k.',
                'funkyass',
                'gay',
                'hentai.com',
                'horne',
                'horney',
                'virgin',
                'hotties',
                'idiot',
                '@alice.it',
                'incest',
                'jesus',
                'gesu',
                'gesù',
                'kazzo',
                'kill',
                'leccaculo',
                'lesbian',
                'lesbica',
                'lesbo',
                'masturbazione',
                'masturbare',
                'masturbo',
                'merda',
                'merdata',
                'merdoso',
                'mignotta',
                'minchia',
                'minkia',
                'minchione',
                'mona',
                'nudo',
                'nuda',
                'nudi',
                'oral',
                'sex',
                'orgasmso',
                'porc',
                'pompa',
                'pompino',
                'porno',
                'puttana',
                'puzza',
                'puzzone',
                'racchia',
                'sborone',
                'sborrone',
                'sborata',
                'sborolata',
                'sboro',
                'scopata',
                'scopare',
                'scroto',
                'scrotum',
                'sega',
                'sesso',
                'shit',
                'shiz',
                's.h.i.t.',
                'sadomaso',
                'sodomist',
                'stronzata',
                'stronzo',
                'succhiamelo',
                'succhiacazzi',
                'testicol',
                'troia',
                'universetoday.net',
                'vaffanculo',
                'v****a',
                'vibrator',
                'vacca',
                'yiddiot',
                'zoccola',
            ]
            elenco_others = [
                '@',
                ".com",
                ".sex",
                ".org",
                ".uk",
                ".en",
                ".it",
                "admin",
                "administrator",
                "amministratore",
                '@yahoo.com',
                '@alice.com',
                'amministratrice',
                'burocrate',
                'checkuser',
                'developer',
                'http://',
                'jimbo',
                'mediawiki',
                'on wheals',
                'on wheal',
                'on wheel',
                'planante',
                'razinger',
                'sysop',
                'troll',
                'vandal',
                ' v.f. ',
                'v. fighter',
                'vandal f.',
                'vandal fighter',
                'wales jimmy',
                'wheels',
                'wales',
                'www.',
            ]

            # blacklist from wikipage
            badword_page = pywikibot.Page(self.site,
                                          i18n.translate(self.site, bad_pag))
            list_loaded = []
            if badword_page.exists():
                pywikibot.output(u'\nLoading the bad words list from %s...' %
                                 self.site)
                list_loaded = load_word_function(badword_page.get())
            else:
                showStatus(4)
                pywikibot.output(u'The bad word page doesn\'t exist!')
            self._blacklist = elenco + elenco_others + list_loaded
            del elenco, elenco_others, list_loaded

        if not hasattr(self, '_whitelist') or force:
            # initialize whitelist
            whitelist_default = ['emiliano']
            wtlpg = i18n.translate(self.site, whitelist_pg)
            list_white = []
            if wtlpg:
                whitelist_page = pywikibot.Page(self.site, wtlpg)
                if whitelist_page.exists():
                    pywikibot.output(u'\nLoading the whitelist from %s...' %
                                     self.site)
                    list_white = load_word_function(whitelist_page.get())
                else:
                    showStatus(4)
                    pywikibot.output(u"The whitelist's page doesn't exist!")
            else:
                showStatus(4)
                pywikibot.warning(u"The whitelist hasn't been setted!")

            # Join the whitelist words.
            self._whitelist = list_white + whitelist_default
            del list_white, whitelist_default

        try:
            for wname in self._whitelist:
                if wname.lower() in str(name).lower():
                    name = name.lower().replace(wname.lower(), '')
                    for bname in self._blacklist:
                        self.bname[name] = bname
                        return bname.lower() in name.lower()
        except UnicodeEncodeError:
            pass
        try:
            for bname in self._blacklist:
                if bname.lower() in str(name).lower():  # bad name positive
                    self.bname[name] = bname
                    return True
        except UnicodeEncodeError:
            pass
        return False
Пример #56
0
from __future__ import absolute_import, division, unicode_literals

import pywikibot

# Requires PyMySql as first choice or
# MySQLdb <https://sourceforge.net/projects/mysql-python/>
try:
    import pymysql as mysqldb
except ImportError:
    try:
        import MySQLdb as mysqldb  # noqa: N813
    except ImportError:
        raise ImportError('No supported MySQL library installed. '
                          'Please install PyMySQL.')
    else:
        pywikibot.warning("PyMySQL not found. It'll fallback "
                          'on the deprecated library MySQLdb.')
else:
    mysqldb.install_as_MySQLdb()

from pywikibot import config2 as config
from pywikibot.tools import deprecated_args, UnicodeType


@deprecated_args(encoding=None)
def mysql_query(query, params=None, dbname=None, verbose=None):
    """Yield rows from a MySQL query.

    An example query that yields all ns0 pages might look like::

        SELECT
         page_namespace,
Пример #57
0
 def delete_1_broken_redirect(self, redir_name):
     """Treat one broken redirect."""
     if isinstance(redir_name, basestring):
         redir_page = pywikibot.Page(self.site, redir_name)
     else:
         redir_page = redir_name
     # Show the title of the page we're working on.
     # Highlight the title in purple.
     done = not self.getOption('delete')
     pywikibot.output(
         color_format('\n\n>>> {lightpurple}{0}{default} <<<',
                      redir_page.title()))
     try:
         targetPage = redir_page.getRedirectTarget()
     except pywikibot.IsNotRedirectPage:
         pywikibot.output(u'%s is not a redirect.' % redir_page.title())
     except pywikibot.CircularRedirect:
         pywikibot.output('%s is a circular redirect.' % redir_page.title())
     except pywikibot.NoPage:
         pywikibot.output(u'%s doesn\'t exist.' % redir_page.title())
     except pywikibot.InvalidTitle:
         pywikibot.exception()
     except pywikibot.InterwikiRedirectPage:
         pywikibot.output('%s is on another site.' % redir_page.title())
     else:
         try:
             targetPage.get()
         except pywikibot.BadTitle as e:
             pywikibot.warning(
                 u'Redirect target %s is not a valid page title.' %
                 str(e)[10:])
         except pywikibot.InvalidTitle:
             pywikibot.exception()
         except pywikibot.NoPage:
             movedTarget = None
             try:
                 movedTarget = targetPage.moved_target()
             except pywikibot.NoMoveTarget:
                 pass
             if movedTarget:
                 if not movedTarget.exists():
                     # FIXME: Test to another move
                     pywikibot.output(u'Target page %s does not exist' %
                                      (movedTarget))
                 elif redir_page == movedTarget:
                     pywikibot.output(
                         'Redirect to target page forms a redirect loop')
                 else:
                     pywikibot.output(u'%s has been moved to %s' %
                                      (redir_page, movedTarget))
                     reason = i18n.twtranslate(
                         self.site, 'redirect-fix-broken-moved',
                         {'to': movedTarget.title(asLink=True)})
                     content = redir_page.get(get_redirect=True)
                     redir_page.set_redirect_target(movedTarget,
                                                    keep_section=True,
                                                    save=False)
                     pywikibot.showDiff(content, redir_page.text)
                     pywikibot.output(u'Summary - %s' % reason)
                     if self.user_confirm(
                             u'Redirect target %s has been moved to %s.\n'
                             u'Do you want to fix %s?' %
                         (targetPage, movedTarget, redir_page)):
                         try:
                             redir_page.save(reason)
                         except pywikibot.NoUsername:
                             pywikibot.output(
                                 u"Page [[%s]] not saved; "
                                 u"sysop privileges required." %
                                 redir_page.title())
                         except pywikibot.LockedPage:
                             pywikibot.output(u'%s is locked.' %
                                              redir_page.title())
                         except pywikibot.PageSaveRelatedError:
                             pywikibot.exception()
                         else:
                             done = True
             if not done and self.user_confirm(
                     u'Redirect target %s does not exist.\n'
                     u'Do you want to delete %s?' %
                 (targetPage.title(asLink=True),
                  redir_page.title(asLink=True))):
                 self.delete_redirect(redir_page, 'redirect-remove-broken')
             elif not (self.getOption('delete') or movedTarget):
                 pywikibot.output(
                     'Cannot fix or delete the broken redirect')
         except pywikibot.IsRedirectPage:
             pywikibot.output(
                 "Redirect target {0} is also a redirect! {1}".format(
                     targetPage.title(asLink=True), "Won't delete anything."
                     if self.getOption('delete') else "Skipping."))
         else:
             # we successfully get the target page, meaning that
             # it exists and is not a redirect: no reason to touch it.
             pywikibot.output("Redirect target {0} does exist! {1}".format(
                 targetPage.title(asLink=True), "Won't delete anything."
                 if self.getOption('delete') else "Skipping."))
Пример #58
0
 def fix_1_double_redirect(self, redir_name):
     """Treat one double redirect."""
     if isinstance(redir_name, basestring):
         redir = pywikibot.Page(self.site, redir_name)
     else:
         redir = redir_name
     # Show the title of the page we're working on.
     # Highlight the title in purple.
     pywikibot.output(
         color_format('\n\n>>> {lightpurple}{0}{default} <<<',
                      redir.title()))
     newRedir = redir
     redirList = []  # bookkeeping to detect loops
     while True:
         redirList.append(
             u'%s:%s' %
             (newRedir.site.lang, newRedir.title(withSection=False)))
         try:
             targetPage = newRedir.getRedirectTarget()
         except pywikibot.IsNotRedirectPage:
             if len(redirList) == 1:
                 pywikibot.output(u'Skipping: Page %s is not a redirect.' %
                                  redir.title(asLink=True))
                 break  # do nothing
             elif len(redirList) == 2:
                 pywikibot.output(
                     u'Skipping: Redirect target %s is not a redirect.' %
                     newRedir.title(asLink=True))
                 break  # do nothing
             # else target found
         except pywikibot.SectionError:
             pywikibot.warning(
                 u"Redirect target section %s doesn't exist." %
                 newRedir.title(asLink=True))
         except (pywikibot.CircularRedirect,
                 pywikibot.InterwikiRedirectPage,
                 pywikibot.UnsupportedPage) as e:
             pywikibot.exception(e)
             pywikibot.output(u"Skipping %s." % newRedir)
             break
         except pywikibot.BadTitle as e:
             # str(e) is in the format 'BadTitle: [[Foo]]'
             pywikibot.warning(
                 u'Redirect target %s is not a valid page title.' %
                 str(e)[10:])
             break
         except pywikibot.NoPage:
             if len(redirList) == 1:
                 pywikibot.output(u'Skipping: Page %s does not exist.' %
                                  redir.title(asLink=True))
                 break
             else:
                 if self.getOption('always'):
                     pywikibot.output(
                         u"Skipping: Redirect target %s doesn't exist." %
                         newRedir.title(asLink=True))
                     break  # skip if automatic
                 else:
                     pywikibot.warning(
                         u"Redirect target %s doesn't exist." %
                         newRedir.title(asLink=True))
         except pywikibot.ServerError:
             pywikibot.output(u'Skipping due to server error: '
                              u'No textarea found')
             break
         else:
             pywikibot.output(u'   Links to: %s.' %
                              targetPage.title(asLink=True))
             try:
                 mw_msg = targetPage.site.mediawiki_message(
                     'wikieditor-toolbar-tool-redirect-example')
             except KeyError:
                 pass
             else:
                 if targetPage.title() == mw_msg:
                     pywikibot.output(
                         u"Skipping toolbar example: Redirect source is "
                         u"potentially vandalized.")
                     break
             # watch out for redirect loops
             if redirList.count(u'%s:%s' %
                                (targetPage.site.lang,
                                 targetPage.title(withSection=False))):
                 pywikibot.warning(
                     u'Redirect target %s forms a redirect loop.' %
                     targetPage.title(asLink=True))
                 break  # FIXME: doesn't work. edits twice!
                 if self.getOption('delete'):
                     # Delete the two redirects
                     # TODO: Check whether pages aren't vandalized
                     # and (maybe) do not have a version history
                     self.delete_redirect(targetPage,
                                          'redirect-remove-loop')
                     self.delete_redirect(redir, 'redirect-remove-loop')
                 break
             else:  # redirect target found
                 if targetPage.isStaticRedirect():
                     pywikibot.output(
                         u"   Redirect target is STATICREDIRECT.")
                 else:
                     newRedir = targetPage
                     continue
         try:
             oldText = redir.get(get_redirect=True)
         except pywikibot.BadTitle:
             pywikibot.output(u"Bad Title Error")
             break
         if self.is_repo and redir.namespace() == self.repo.item_namespace:
             redir = pywikibot.ItemPage(self.repo, redir.title())
             targetPage = pywikibot.ItemPage(self.repo, targetPage.title())
             pywikibot.output('Fixing double item redirect')
             redir.set_redirect_target(targetPage)
             break
         redir.set_redirect_target(targetPage,
                                   keep_section=True,
                                   save=False)
         summary = i18n.twtranslate(self.site, 'redirect-fix-double',
                                    {'to': targetPage.title(asLink=True)})
         pywikibot.showDiff(oldText, redir.text)
         if self.user_confirm(u'Do you want to accept the changes?'):
             try:
                 redir.save(summary)
             except pywikibot.LockedPage:
                 pywikibot.output(u'%s is locked.' % redir.title())
             except pywikibot.SpamfilterError as error:
                 pywikibot.output(
                     u"Saving page [[%s]] prevented by spam filter: %s" %
                     (redir.title(), error.url))
             except pywikibot.PageNotSaved as error:
                 pywikibot.output(u"Saving page [[%s]] failed: %s" %
                                  (redir.title(), error))
             except pywikibot.NoUsername:
                 pywikibot.output(
                     u"Page [[%s]] not saved; sysop privileges required." %
                     redir.title())
             except pywikibot.Error as error:
                 pywikibot.output(
                     u"Unexpected error occurred trying to save [[%s]]: %s"
                     % (redir.title(), error))
         break
Пример #59
0
def main(*args):
    """
    Process command line arguments and invoke bot.

    If args is an empty list, sys.argv is used.

    @param args: command line arguments
    @type args: list of unicode
    """
    for arg in pywikibot.handle_args(args):
        arg, sep, val = arg.partition(':')
        if arg == '-edit':
            globalvar.attachEditCount = int(val or pywikibot.input(
                'After how many edits would you like to welcome new users? '
                '(0 is allowed)'))
        elif arg == '-timeoffset':
            globalvar.timeoffset = int(val or pywikibot.input(
                'Which time offset (in minutes) for new users would you like '
                'to use?'))
        elif arg == '-time':
            globalvar.timeRecur = int(val or pywikibot.input(
                'For how many seconds would you like to bot to sleep before '
                'checking again?'))
        elif arg == '-offset':
            if not val:
                val = pywikibot.input(
                    'Which time offset for new users would you like to use? '
                    '(yyyymmddhhmmss)')
            try:
                globalvar.offset = pywikibot.Timestamp.fromtimestampformat(val)
            except ValueError:
                # upon request, we could check for software version here
                raise ValueError(
                    "Mediawiki has changed, -offset:# is not supported "
                    "anymore, but -offset:TIMESTAMP is, assuming TIMESTAMP "
                    "is yyyymmddhhmmss. -timeoffset is now also supported. "
                    "Please read this script source header for documentation.")
        elif arg == '-file':
            globalvar.randomSign = True
            globalvar.signFileName = val or pywikibot.input(
                'Where have you saved your signatures?')
        elif arg == '-sign':
            globalvar.defaultSign = val or pywikibot.input(
                'Which signature to use?')
            globalvar.defaultSign += timeselected
        elif arg == '-break':
            globalvar.recursive = False
        elif arg == '-nlog':
            globalvar.makeWelcomeLog = False
        elif arg == '-ask':
            globalvar.confirm = True
        elif arg == '-filter':
            globalvar.filtBadName = True
        elif arg == '-savedata':
            globalvar.saveSignIndex = True
        elif arg == '-random':
            globalvar.randomSign = True
        elif arg == '-sul':
            globalvar.welcomeAuto = True
        elif arg == '-limit':
            globalvar.queryLimit = int(val or pywikibot.input(
                u'How many of the latest new users would you like to load?'))
        elif arg == '-numberlog':
            globalvar.dumpToLog = int(val or pywikibot.input(
                'After how many welcomed users would you like to update the '
                'welcome log?'))
        elif arg == '-quiet':
            globalvar.quiet = True
        elif arg == '-quick':
            issue_deprecation_warning('The usage of "-quick" option',
                                      None,
                                      2,
                                      since='20160211')

    # Filename and Pywikibot path
    # file where is stored the random signature index
    filename = pywikibot.config.datafilepath(
        'welcome-%s-%s.data' %
        (pywikibot.Site().family.name, pywikibot.Site().code))
    if globalvar.offset and globalvar.timeoffset:
        pywikibot.warning(
            'both -offset and -timeoffset were provided, ignoring -offset')
        globalvar.offset = 0

    try:
        bot = WelcomeBot()
    except KeyError as error:
        # site not managed by welcome.py
        pywikibot.bot.suggest_help(exception=error)
        return False

    try:
        bot.run()
    except KeyboardInterrupt:
        if bot.welcomed_users:
            showStatus()
            pywikibot.output("Put welcomed users before quit...")
            bot.makelogpage(bot.welcomed_users)
        pywikibot.output("\nQuitting...")
    finally:
        # If there is the savedata, the script must save the number_user.
        if globalvar.randomSign and globalvar.saveSignIndex and \
           bot.welcomed_users:
            if sys.version_info[0] > 2:
                import pickle as cPickle
            else:
                import cPickle
            with open(filename, 'wb') as f:
                cPickle.dump(bot.welcomed_users,
                             f,
                             protocol=config.pickle_protocol)
Пример #60
0
 def delete_1_broken_redirect(self):
     """Treat one broken redirect."""
     redir_page = self.current_page
     done = not self.getOption('delete')
     try:
         targetPage = redir_page.getRedirectTarget()
     except (pywikibot.CircularRedirect,
             pywikibot.InvalidTitle,
             RuntimeError):
         pywikibot.exception()
     except pywikibot.InterwikiRedirectPage:
         pywikibot.output('{0} is on another site.'
                          .format(redir_page.title()))
     else:
         try:
             targetPage.get()
         except pywikibot.BadTitle as e:
             pywikibot.warning(
                 'Redirect target {0} is not a valid page title.'
                 .format(str(e)[10:]))
         except pywikibot.InvalidTitle:
             pywikibot.exception()
         except pywikibot.NoPage:
             movedTarget = None
             try:
                 movedTarget = targetPage.moved_target()
             except pywikibot.NoMoveTarget:
                 pass
             if movedTarget:
                 if not movedTarget.exists():
                     # FIXME: Test to another move
                     pywikibot.output('Target page {0} does not exist'
                                      .format(movedTarget))
                 elif redir_page == movedTarget:
                     pywikibot.output(
                         'Redirect to target page forms a redirect loop')
                 else:
                     pywikibot.output('{0} has been moved to {1}'
                                      .format(redir_page, movedTarget))
                     reason = i18n.twtranslate(self.site,
                                               'redirect-fix-broken-moved',
                                               {'to': movedTarget.title(
                                                   as_link=True)})
                     content = redir_page.get(get_redirect=True)
                     redir_page.set_redirect_target(
                         movedTarget, keep_section=True, save=False)
                     pywikibot.output('Summary - ' + reason)
                     done = self.userPut(redir_page, content,
                                         redir_page.text, summary=reason,
                                         ignore_save_related_errors=True,
                                         ignore_server_errors=True)
             if not done and self.user_confirm(
                     'Redirect target {0} does not exist.\n'
                     'Do you want to delete {1}?'
                     .format(targetPage.title(as_link=True),
                             redir_page.title(as_link=True))):
                 self.delete_redirect(redir_page, 'redirect-remove-broken')
             elif not (self.getOption('delete') or movedTarget):
                 pywikibot.output(
                     'Cannot fix or delete the broken redirect')
         except pywikibot.IsRedirectPage:
             pywikibot.output(
                 'Redirect target {0} is also a redirect! {1}'.format(
                     targetPage.title(as_link=True),
                     "Won't delete anything."
                     if self.getOption('delete') else 'Skipping.'))
         else:
             # we successfully get the target page, meaning that
             # it exists and is not a redirect: no reason to touch it.
             pywikibot.output(
                 'Redirect target {0} does exist! {1}'.format(
                     targetPage.title(as_link=True),
                     "Won't delete anything."
                     if self.getOption('delete') else 'Skipping.'))