def choosecats(pagetext): """Coose categories.""" chosen = [] done = False length = 1000 # TODO: → input_choice pywikibot.output("""Give the new categories, one per line. Empty line: if the first, don't change. Otherwise: Ready. -: I made a mistake, let me start over. ?: Give the text of the page with GUI. ??: Give the text of the page in console. xx: if the first, remove all categories and add no new. q: quit.""") while not done: choice = pywikibot.input('?') if choice == '': done = True elif choice == '-': chosen = choosecats(pagetext) done = True elif choice == '?': from pywikibot import editor as editarticle editor = editarticle.TextEditor() editor.edit(pagetext) elif choice == '??': pywikibot.output(pagetext[0:length]) length = length + 500 elif choice == 'xx' and not chosen: chosen = None done = True elif choice == 'q': raise QuitKeyboardInterrupt else: chosen.append(choice) return chosen
def result(self, value): """Open a text editor and let the user change it.""" editor = editarticle.TextEditor() self.new_text = editor.edit(self._text, jumpIndex=self._start, highlight=self._title) return super(EditOption, self).result(value)
def choosecats(pagetext): chosen = [] done = False length = 1000 print("""Give the new categories, one per line. Empty line: if the first, don't change. Otherwise: Ready. -: I made a mistake, let me start over. ?: Give the text of the page with GUI. ??: Give the text of the page in console. xx: if the first, remove all categories and add no new. q: quit.""") while not done: choice = pywikibot.input(u"?") if choice == "": done = True elif choice == "-": chosen = choosecats(pagetext) done = True elif choice == "?": from pywikibot import editor as editarticle editor = editarticle.TextEditor() editor.edit(pagetext) elif choice == "??": pywikibot.output(pagetext[0:length]) length = length + 500 elif choice == "xx" and chosen == []: chosen = None done = True elif choice == "q": print "quit..." sys.exit() else: chosen.append(choice) return chosen
def showQuest(page): """Ask for an editor and invoke it.""" quest = pywikibot.input_choice( u'Do you want to open the page?', [('with browser', 'b'), ('with gui', 'g'), ('no', 'n')], 'n', automatic_quit=False) if quest == 'b': webbrowser.open('%s?redirect=no' % page.full_url()) elif quest == 'g': from pywikibot import editor as editarticle editor = editarticle.TextEditor() editor.edit(page.text)
def showQuest(site, page): quest = pywikibot.inputChoice(u'Do you want to open the page?', ['with browser', 'with gui', 'no'], ['b', 'g', 'n'], 'n') pathWiki = site.family.nicepath(site.lang) url = 'http://%s%s%s?&redirect=no' % (pywikibot.getSite().hostname(), pathWiki, page.urlname()) if quest == 'b': webbrowser.open(url) elif quest == 'g': from pywikibot import editor as editarticle editor = editarticle.TextEditor() text = editor.edit(page.get())
def showQuest(page): quest = pywikibot.inputChoice(u'Do you want to open the page?', ['with browser', 'with gui', 'no'], ['b', 'g', 'n'], 'n') site = page.site url = '%s://%s%s?redirect=no' % (site.protocol(), site.hostname(), site.nice_get_address( page.title(asUrl=True))) if quest == 'b': webbrowser.open(url) elif quest == 'g': from pywikibot import editor as editarticle editor = editarticle.TextEditor() editor.edit(page.text)
def showQuest(page): """Ask for an editor and invoke it.""" quest = pywikibot.input_choice(u'Do you want to open the page?', [('with browser', 'b'), ('with gui', 'g'), ('no', 'n')], 'n', automatic_quit=False) site = page.site url = '%s://%s%s?redirect=no' % (site.protocol(), site.hostname(), site.nice_get_address( page.title(asUrl=True))) if quest == 'b': webbrowser.open(url) elif quest == 'g': from pywikibot import editor as editarticle editor = editarticle.TextEditor() editor.edit(page.text)
def run(self) -> None: pages = [self.parent] + self.children for page in pages: original_text = page.text new_text = page.get_newtext() if original_text == new_text: break while True: pywikibot.output(color_format( '\n\n>>> {lightpurple}{0}{default} <<<', page.title())) pywikibot.showDiff(original_text, new_text) choice = pywikibot.input_choice('この変更を投稿しますか', [('はい', 'y'), ('いいえ', 'n'), ('エディタで編集する', 'e')]) if choice == 'n': break if choice == 'e': editor = editarticle.TextEditor() as_edited = editor.edit(new_text) if as_edited: new_text = as_edited continue if choice == 'y': page.text = new_text page.save( 'Botによる: [[User:YuukinBot#作業内容2|カテゴリの整備]]', asynchronous=True, callback=self._async_callback, quiet=True) self._pending_processing_titles.put(page.title(as_link=True)) while not self._pending_processed_titles.empty(): proc_title, res = self._pending_processed_titles.get() pywikibot.output('{0}{1}'.format(proc_title, 'が投稿されました' if res else 'は投稿されませんでした')) break while not all((self._pending_processing_titles.empty(), self._pending_processed_titles.empty())): proc_title, res = self._pending_processed_titles.get() pywikibot.output('{0}{1}'.format(proc_title, 'が投稿されました' if res else 'は投稿されませんでした')) pywikibot.output(f'{self.changed_pages} ページ編集しました') pywikibot.output(f'{self.parent.title(as_link=True)} 関連の整備が完了しました')
def process_filename(self): """Return base filename portion of self.url""" # Isolate the pure name filename = self.url # Filename may be either a local file path or a URL if "://" in filename: # extract the path portion of the URL filename = urlparse.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) # FIXME: these 2 belong somewhere else, presumably in family forbidden = '/' # to be extended allowed_formats = (u'gif', u'jpg', u'jpeg', u'mid', u'midi', u'ogg', u'png', u'svg', u'xcf', u'djvu', u'ogv', u'oga', u'tif', u'tiff') # ask until it's valid while True: newfn = pywikibot.input( u'Enter a better name, or press enter to accept:') if newfn == "": newfn = filename break ext = os.path.splitext(newfn)[1].lower().strip('.') # are any chars in forbidden also in newfn? invalid = set(forbidden) & set(newfn) if invalid: c = "".join(invalid) print "Invalid character(s): %s. Please try again" % c continue if ext not in allowed_formats: choice = pywikibot.inputChoice( u"File format is not one of [%s], but %s. Continue?" % (u' '.join(allowed_formats), ext), ['yes', 'no'], ['y', 'N'], 'N') if choice == 'n': continue break if newfn != '': filename = newfn # A proper description for the submission. pywikibot.output(u"The suggested description is:") pywikibot.output(self.description) if self.verifyDescription: newDescription = u'' choice = pywikibot.inputChoice( u'Do you want to change this description?', ['Yes', 'No'], ['y', 'N'], 'n') if choice == 'y': from pywikibot import editor as editarticle editor = editarticle.TextEditor() newDescription = editor.edit(self.description) # if user saved / didn't press Cancel if newDescription: self.description = newDescription return filename
def handle_bad_page(self, *values): """Process one bad page.""" try: self.content = self.page.get() except IsRedirectPageError: pywikibot.output('Already redirected, skipping.') return except NoPageError: pywikibot.output('Already deleted') return for d in pywikibot.translate(self.site.code, done): if d in self.content: pywikibot.output( 'Found: "{}" in content, nothing necessary'.format(d)) return pywikibot.output('---- Start content ----------------') pywikibot.output(self.content) pywikibot.output('---- End of content ---------------') # Loop other user answer answered = False while not answered: answer = pywikibot.input(self.question) if answer == 'q': raise QuitKeyboardInterrupt if answer == 'd': pywikibot.output('Trying to delete page [[{}]].' .format(self.page.title())) self.page.delete() return if answer == 'e': old = self.content new = editor.TextEditor().edit(old) msg = pywikibot.input('Summary message:') self.userPut(self.page, old, new, summary=msg) return if answer == 'b': pywikibot.output('Blanking page [[{}]].' .format(self.page.title())) try: self.page.put('', summary=i18n.twtranslate( self.site.lang, 'followlive-blanking', {'content': self.content})) except EditConflictError: pywikibot.output( 'An edit conflict occurred! Automatically retrying') self.handle_bad_page(self) return if answer == '': pywikibot.output('Page correct! Proceeding with next pages.') return # Check user input: if answer[0] == 'u': # Answer entered as string answer = answer[1:] try: choices = answer.split(',') except ValueError: # User entered wrong value pywikibot.error('"{}" is not valid'.format(answer)) continue # test input for choice in choices: try: x = int(choice) except ValueError: break else: answered = (x >= 1 and x <= len(self.questionlist)) if not answered: pywikibot.error('"{}" is not valid'.format(answer)) continue summary = '' for choice in choices: answer = int(choice) # grab the template parameters tpl = pywikibot.translate(self.site, templates)[self.questionlist[answer]] if tpl['pos'] == 'top': pywikibot.output( 'prepending {}...'.format(self.questionlist[answer])) self.content = self.questionlist[answer] + '\n' + self.content elif tpl['pos'] == 'bottom': pywikibot.output('appending {}...' .format(self.questionlist[answer])) self.content += '\n' + self.questionlist[answer] else: raise RuntimeError( '"pos" should be "top" or "bottom" for template {}. ' 'Contact a developer.'.format(self.questionlist[answer])) summary += tpl['msg'] + ' ' pywikibot.output('Probably added ' + self.questionlist[answer]) self.page.put(self.content, summary=summary) pywikibot.output('with comment {}\n'.format(summary))
def process_filename(self, file_url): """Return base filename portion of file_url.""" # 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.use_filename: filename = self.use_filename if self.filename_prefix: filename = self.filename_prefix + filename if not self.keep_filename: pywikibot.output( '\nThe filename on the target wiki will default to: {}\n'. format(filename)) assert not self.opt.always newfn = pywikibot.input( '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.target_site.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 self.opt.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): {}. Please try again'.format(c)) continue if allowed_formats and ext not in allowed_formats: if self.opt.always: pywikibot.output('File format is not one of ' '[{}]'.format(' '.join(allowed_formats))) continue if not pywikibot.input_yn( 'File format is not one of [{}], but {!r}. Continue?'. format(' '.join(allowed_formats), ext), default=False): continue potential_file_page = pywikibot.FilePage(self.target_site, 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.has_permission(): if overwrite is None: overwrite = not pywikibot.input_yn( 'File with name {} already exists. ' 'Would you like to change the name? ' '(Otherwise file will be overwritten.)'.format( filename), default=True, automatic_quit=False) if not overwrite: continue break pywikibot.output('File with name {} already exists and ' 'cannot be overwritten.'.format(filename)) continue with suppress(NoPageError): if potential_file_page.file_is_shared(): pywikibot.output( 'File with name {} already exists in shared ' 'repository and cannot be overwritten.'.format( filename)) continue break # A proper description for the submission. # Empty descriptions are not accepted. if self.description: pywikibot.output('The suggested description is:\n{}'.format( self.description)) while not self.description or self.verify_description: if not self.description: pywikibot.output( color_format( '{lightred}It is not possible to upload a file ' 'without a description.{default}')) assert not self.opt.always # if no description, ask if user want to add one or quit, # and loop until one is filled. # if self.verify_description, ask if user want to change it # or continue. if self.description: question = 'Do you want to change this description?' else: question = 'No description was given. Add one?' if pywikibot.input_yn(question, default=not self.description, automatic_quit=self.description): from pywikibot import editor as editarticle editor = editarticle.TextEditor() try: new_description = editor.edit(self.description) except ImportError: raise except Exception as e: pywikibot.error(e) continue # if user saved / didn't press Cancel if new_description: self.description = new_description elif not self.description: raise QuitKeyboardInterrupt self.verify_description = False return filename
def edit_page(page, summary, always=False, dry_run=False): pywikibot.output(page.title()) try: original_text = page.get() if not page.canBeEdited(): pywikibot.output("You can't edit page " + page.title(as_link=True)) return always except pywikibot.NoPage: pywikibot.output(u"Page {0} not found".format( page.title(as_link=True))) return always except pywikibot.IsRedirectPage: return always new_text = replace_text(original_text) if new_text == original_text: pywikibot.output('No changes were necessary in ' + page.title(as_link=True)) return always context = 0 if dry_run: pywikibot.showDiff(original_text, new_text, context=context) return always while True: pywikibot.showDiff(original_text, new_text, context=context) if always: break choice = pywikibot.input_choice('Do you want to accept these changes?', [('Yes', 'y'), ('No', 'n'), ('Edit original', 'e'), ('edit Latest', 'l'), ('open in Browser', 'b'), ('More context', 'm'), ('All', 'a')], default='N') if choice == 'm': context = context * 3 if context else 3 continue if choice == 'e': editor = editarticle.TextEditor() as_edited = editor.edit(original_text) # if user didn't press Cancel if as_edited and as_edited != new_text: new_text = as_edited continue if choice == 'l': editor = editarticle.TextEditor() as_edited = editor.edit(new_text) # if user didn't press Cancel if as_edited and as_edited != new_text: new_text = as_edited # prevent changes from being applied again last_text = new_text continue if choice == 'b': pywikibot.bot.open_webbrowser(page) try: original_text = page.get(get_redirect=True, force=True) except pywikibot.NoPage: pywikibot.output('Page {0} has been deleted.'.format( page.title())) break new_text = original_text last_text = None continue if choice == 'a': always = True if choice == 'y': page.text = new_text page.save(summary=summary) break if always and new_text != original_text: try: page.text = new_text page.save(summary=summary) except pywikibot.EditConflict: pywikibot.output('Skipping {0} because of edit conflict'.format( page.title(), )) except pywikibot.SpamfilterError as e: pywikibot.output( 'Cannot change {0} because of blacklist entry {1}'.format( page.title(), e.url)) except pywikibot.LockedPage: pywikibot.output('Skipping {0} (locked page)'.format( page.title(), )) except pywikibot.PageNotSaved as error: pywikibot.output('Error putting page: {0}'.format(error.args, )) return always
def run(self): """ Starts the bot. """ # Run the generator which will yield Pages which might need to be # changed. for page in self.generator: if self.isTitleExcepted(page.title()): pywikibot.output( u'Skipping %s because the title is on the exceptions list.' % page.title(asLink=True)) continue try: # Load the page's text from the wiki original_text = page.get(get_redirect=True) if not page.canBeEdited(): pywikibot.output(u"You can't edit page %s" % page.title(asLink=True)) continue except pywikibot.NoPage: pywikibot.output(u'Page %s not found' % page.title(asLink=True)) continue new_text = original_text while True: if self.isTextExcepted(new_text): pywikibot.output(u'Skipping %s because it contains text ' u'that is on the exceptions list.' % page.title(asLink=True)) break new_text = self.doReplacements(new_text) if new_text == original_text: pywikibot.output(u'No changes were necessary in %s' % page.title(asLink=True)) break if self.recursive: newest_text = self.doReplacements(new_text) while (newest_text != new_text): new_text = newest_text newest_text = self.doReplacements(new_text) if hasattr(self, "addedCat"): cats = page.categories(nofollow_redirects=True) if self.addedCat not in cats: cats.append(self.addedCat) new_text = pywikibot.replaceCategoryLinks( new_text, cats) # 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} <<<" % page.title()) pywikibot.showDiff(original_text, new_text) if self.acceptall: break choice = pywikibot.inputChoice( u'Do you want to accept these changes?', ['Yes', 'No', 'Edit', 'open in Browser', 'All', 'Quit'], ['y', 'N', 'e', 'b', 'a', 'q'], 'N') if choice == 'e': editor = editarticle.TextEditor() as_edited = editor.edit(original_text) # if user didn't press Cancel if as_edited and as_edited != new_text: new_text = as_edited continue if choice == 'b': webbrowser.open( "http://%s%s" % (page.site.hostname(), page.site.nice_get_address(page.title(asUrl=True)))) i18n.input('pywikibot-enter-finished-browser') try: original_text = page.get(get_redirect=True, force=True) except pywikibot.NoPage: pywikibot.output(u'Page %s has been deleted.' % page.title()) break new_text = original_text continue if choice == 'q': return if choice == 'a': self.acceptall = True if choice == 'y': page.put_async(new_text, self.summary) # choice must be 'N' break if self.acceptall and new_text != original_text: try: page.put(new_text, self.summary) except pywikibot.EditConflict: pywikibot.output(u'Skipping %s because of edit conflict' % (page.title(), )) except pywikibot.SpamfilterError as e: pywikibot.output( u'Cannot change %s because of blacklist entry %s' % (page.title(), e.url)) except pywikibot.PageNotSaved as error: pywikibot.output(u'Error putting page: %s' % (error.args, )) except pywikibot.LockedPage: pywikibot.output(u'Skipping %s (locked page)' % (page.title(), ))
def run(self): """Start the bot.""" # Run the generator which will yield Pages which might need to be # changed. for page in self.generator: if self.isTitleExcepted(page.title()): pywikibot.output( 'Skipping {0} because the title is on the exceptions list.' .format(page.title(as_link=True))) continue try: # Load the page's text from the wiki original_text = page.get(get_redirect=True) if not page.canBeEdited(): pywikibot.output("You can't edit page " + page.title(as_link=True)) continue except pywikibot.NoPage: pywikibot.output('Page {0} not found'.format( page.title(as_link=True))) continue applied = set() new_text = original_text last_text = None context = 0 while True: if self.isTextExcepted(new_text): pywikibot.output('Skipping {0} because it contains text ' 'that is on the exceptions list.'.format( page.title(as_link=True))) break while new_text != last_text: last_text = new_text new_text = self.apply_replacements(last_text, applied, page) if not self.recursive: break if new_text == original_text: pywikibot.output('No changes were necessary in ' + page.title(as_link=True)) break if hasattr(self, 'addedCat'): # Fetch only categories in wikitext, otherwise the others # will be explicitly added. cats = textlib.getCategoryLinks(new_text, site=page.site) if self.addedCat not in cats: cats.append(self.addedCat) new_text = textlib.replaceCategoryLinks(new_text, cats, site=page.site) # Show the title of the page we're working on. # Highlight the title in purple. pywikibot.output( color_format('\n\n>>> {lightpurple}{0}{default} <<<', page.title())) pywikibot.showDiff(original_text, new_text, context=context) if self.getOption('always'): break choice = pywikibot.input_choice( 'Do you want to accept these changes?', [('Yes', 'y'), ('No', 'n'), ('Edit original', 'e'), ('edit Latest', 'l'), ('open in Browser', 'b'), ('More context', 'm'), ('All', 'a')], default='N') if choice == 'm': context = context * 3 if context else 3 continue if choice == 'e': editor = editarticle.TextEditor() as_edited = editor.edit(original_text) # if user didn't press Cancel if as_edited and as_edited != new_text: new_text = as_edited continue if choice == 'l': editor = editarticle.TextEditor() as_edited = editor.edit(new_text) # if user didn't press Cancel if as_edited and as_edited != new_text: new_text = as_edited # prevent changes from being applied again last_text = new_text continue if choice == 'b': pywikibot.bot.open_webbrowser(page) try: original_text = page.get(get_redirect=True, force=True) except pywikibot.NoPage: pywikibot.output('Page {0} has been deleted.'.format( page.title())) break new_text = original_text last_text = None continue if choice == 'a': self.options['always'] = True if choice == 'y': page.text = new_text page.save(summary=self.generate_summary(applied), asynchronous=True, callback=self._replace_async_callback, quiet=True) while not self._pending_processed_titles.empty(): proc_title, res = self._pending_processed_titles.get() pywikibot.output('Page {0}{1} saved'.format( proc_title, '' if res else ' not')) # choice must be 'N' break if self.getOption('always') and new_text != original_text: try: page.text = new_text page.save(summary=self.generate_summary(applied), callback=self._replace_sync_callback, quiet=True) except pywikibot.EditConflict: pywikibot.output( 'Skipping {0} because of edit conflict'.format( page.title(), )) except pywikibot.SpamfilterError as e: pywikibot.output( 'Cannot change {0} because of blacklist entry {1}'. format(page.title(), e.url)) except pywikibot.LockedPage: pywikibot.output('Skipping {0} (locked page)'.format( page.title(), )) except pywikibot.PageNotSaved as error: pywikibot.output('Error putting page: {0}'.format( error.args, )) if self._pending_processed_titles.qsize() > 50: while not self._pending_processed_titles.empty(): proc_title, res = self._pending_processed_titles.get() pywikibot.output('Page {0}{1} saved'.format( proc_title, '' if res else ' not'))
def process_filename(self): """Return base filename portion of self.url.""" # Isolate the pure name filename = self.url # Filename may be either a local file path or a URL 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) # FIXME: these 2 belong somewhere else, presumably in family forbidden = '/' # to be extended allowed_formats = (u'gif', u'jpg', u'jpeg', u'mid', u'midi', u'ogg', u'png', u'svg', u'xcf', u'djvu', u'ogv', u'oga', u'tif', u'tiff') # ask until it's valid while True: newfn = pywikibot.input( u'Enter a better name, or press enter to accept:') if newfn == "": newfn = filename break ext = os.path.splitext(newfn)[1].lower().strip('.') # are any chars in forbidden also in newfn? invalid = set(forbidden) & set(newfn) if invalid: c = "".join(invalid) pywikibot.output( 'Invalid character(s): %s. Please try again' % c) continue if ext not in allowed_formats: if 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 break if newfn != '': filename = newfn # 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}') # 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
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( color_format( '{lightred}It is not possible to upload a file ' 'without a summary/description.{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
def run(self): """Start the bot.""" # Run the generator which will yield Pages which might need to be # changed. for page in self.generator: if self.isTitleExcepted(page.title()): pywikibot.output( u'Skipping %s because the title is on the exceptions list.' % page.title(asLink=True)) continue try: # Load the page's text from the wiki original_text = page.get(get_redirect=True) if not page.canBeEdited(): pywikibot.output(u"You can't edit page %s" % page.title(asLink=True)) continue except pywikibot.NoPage: pywikibot.output(u'Page %s not found' % page.title(asLink=True)) continue applied = set() new_text = original_text while True: if self.isTextExcepted(new_text): pywikibot.output(u'Skipping %s because it contains text ' u'that is on the exceptions list.' % page.title(asLink=True)) break last_text = None while new_text != last_text: last_text = new_text new_text = self.apply_replacements(last_text, applied) if not self.recursive: break if new_text == original_text: pywikibot.output(u'No changes were necessary in %s' % page.title(asLink=True)) break if hasattr(self, 'addedCat'): # Fetch only categories in wikitext, otherwise the others will # be explicitly added. cats = textlib.getCategoryLinks(new_text, site=page.site) if self.addedCat not in cats: cats.append(self.addedCat) new_text = textlib.replaceCategoryLinks(new_text, cats, site=page.site) # 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} <<<" % page.title()) pywikibot.showDiff(original_text, new_text) if self.getOption('always'): break choice = pywikibot.input_choice( u'Do you want to accept these changes?', [('Yes', 'y'), ('No', 'n'), ('Edit', 'e'), ('open in Browser', 'b'), ('all', 'a')], default='N') if choice == 'e': editor = editarticle.TextEditor() as_edited = editor.edit(original_text) # if user didn't press Cancel if as_edited and as_edited != new_text: new_text = as_edited continue if choice == 'b': pywikibot.bot.open_webbrowser(page) try: original_text = page.get(get_redirect=True, force=True) except pywikibot.NoPage: pywikibot.output(u'Page %s has been deleted.' % page.title()) break new_text = original_text continue if choice == 'a': self.options['always'] = True if choice == 'y': page.put_async(new_text, self.generate_summary(applied), callback=self.count_changes) # choice must be 'N' break if self.getOption('always') and new_text != original_text: try: page.put(new_text, self.generate_summary(applied), callback=self.count_changes) except pywikibot.EditConflict: pywikibot.output(u'Skipping %s because of edit conflict' % (page.title(), )) except pywikibot.SpamfilterError as e: pywikibot.output( u'Cannot change %s because of blacklist entry %s' % (page.title(), e.url)) except pywikibot.LockedPage: pywikibot.output(u'Skipping %s (locked page)' % (page.title(), )) except pywikibot.PageNotSaved as error: pywikibot.output(u'Error putting page: %s' % (error.args, ))
def treat(self, refPage, disambPage): """ Parameters: disambPage - The disambiguation page or redirect we don't want anything to link to refPage - A page linking to disambPage Returns False if the user pressed q to completely quit the program. Otherwise, returns True. """ # TODO: break this function up into subroutines! dn_template_str = i18n.translate(self.mysite, dn_template) include = False unlink = False new_targets = [] try: text = refPage.get(throttle=False) ignoreReason = self.checkContents(text) if ignoreReason: pywikibot.output( '\n\nSkipping %s because it contains %s.\n\n' % (refPage.title(), ignoreReason)) else: include = True except pywikibot.IsRedirectPage: pywikibot.output(u'%s is a redirect to %s' % (refPage.title(), disambPage.title())) if disambPage.isRedirectPage(): target = self.alternatives[0] choice = pywikibot.inputChoice( u'Do you want to make redirect %s point to %s?' % (refPage.title(), target), ['yes', 'no'], ['y', 'N'], 'N') if choice == 'y': redir_text = '#%s [[%s]]' \ % (self.mysite.redirect(default=True), target) try: refPage.put_async(redir_text, comment=self.comment) except pywikibot.PageNotSaved as error: pywikibot.output(u'Page not saved: %s' % error.args) else: choice = pywikibot.inputChoice( u'Do you want to work on pages linking to %s?' % refPage.title(), ['yes', 'no', 'change redirect'], ['y', 'N', 'c'], 'N') if choice == 'y': gen = ReferringPageGeneratorWithIgnore( refPage, self.primary) preloadingGen = pagegenerators.PreloadingGenerator(gen) for refPage2 in preloadingGen: # run until the user selected 'quit' if not self.treat(refPage2, refPage): break elif choice == 'c': text = refPage.get(throttle=False, get_redirect=True) include = "redirect" except pywikibot.NoPage: pywikibot.output( u'Page [[%s]] does not seem to exist?! Skipping.' % refPage.title()) include = False if include in (True, "redirect"): # make a backup of the original text so we can show the changes later original_text = text n = 0 curpos = 0 dn = False edited = False # This loop will run until we have finished the current page while True: m = self.linkR.search(text, pos=curpos) if not m: if n == 0: pywikibot.output(u"No changes necessary in %s" % refPage.title()) return True else: # stop loop and save page break # Make sure that next time around we will not find this same hit. curpos = m.start() + 1 try: foundlink = pywikibot.Link(m.group('title'), disambPage.site) except pywikibot.Error: continue # ignore interwiki links if foundlink.site != disambPage.site: continue # Check whether the link found is to disambPage. try: if foundlink.canonical_title() != disambPage.title(): continue except pywikibot.Error: # must be a broken link pywikibot.log(u"Invalid link [[%s]] in page [[%s]]" % (m.group('title'), refPage.title())) continue n += 1 # how many bytes should be displayed around the current link context = 60 #there's a {{dn}} here already already_dn = text[m.end():m.end() + 8].find( dn_template_str[:4]) > -1 if already_dn and self.dnSkip: continue # This loop will run while the user doesn't choose an option # that will actually change the page while True: self.current_page = refPage if not self.always: # at the beginning of the link, start red color. # at the end of the link, reset the color to default pywikibot.output(text[max(0, m.start() - context):m.start()] + '\03{lightred}' + text[m.start():m.end()] + '\03{default}' + text[m.end():m.end() + context]) if edited: choice = pywikibot.input( u"Option (#, r#, [s]kip link, [e]dit page, [n]ext page, [u]nlink, [q]uit,\n" u" [t]ag template " + dn_template_str + ",\n" u" [m]ore context, [l]ist, [a]dd new, x=save in this form):" ) else: choice = pywikibot.input( u"Option (#, r#, [s]kip link, [e]dit page, [n]ext page, [u]nlink, [q]uit,\n" u" [t]ag template " + dn_template_str + ",\n" u" [m]ore context, show [d]isambiguation page, [l]ist, [a]dd new):" ) else: choice = self.always if choice in ['a', 'A']: newAlternative = pywikibot.input(u'New alternative:') self.alternatives.append(newAlternative) self.listAlternatives() elif choice in ['e', 'E']: editor = editarticle.TextEditor() newText = editor.edit(text, jumpIndex=m.start(), highlight=disambPage.title()) # if user didn't press Cancel if newText and newText != text: text = newText break elif choice in ['d', 'D']: editor = editarticle.TextEditor() if disambPage.isRedirectPage(): disambredir = disambPage.getRedirectTarget() editor.edit(disambredir.get(), jumpIndex=m.start(), highlight=disambredir.title()) else: editor.edit(disambPage.get(), jumpIndex=m.start(), highlight=disambPage.title()) elif choice in ['l', 'L']: self.listAlternatives() elif choice in ['m', 'M']: # show more text around the link we're working on context *= 2 else: break if choice in ['e', 'E']: # user has edited the page and then pressed 'OK' edited = True curpos = 0 continue elif choice in ['n', 'N']: # skip this page if self.primary: # If run with the -primary argument, skip this # occurence next time. self.primaryIgnoreManager.ignore(refPage) return True elif choice in ['q', 'Q']: # quit the program self.quit() elif choice in ['s', 'S']: # Next link on this page n -= 1 continue elif choice in ['x', 'X'] and edited: # Save the page as is break # 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') trailing_chars = m.group('linktrail') if trailing_chars: link_text += trailing_chars # '?', '/' for old choice if choice in ['t', 'T', '?', '/']: # small chunk of text to search search_text = text[m.end():m.end() + context] # figure out where the link (and sentance) ends, put note # there end_of_word_match = re.search("\s", search_text) if end_of_word_match: position_split = end_of_word_match.start(0) else: position_split = 0 #insert dab needed template text = (text[:m.end() + position_split] + dn_template_str + text[m.end() + position_split:]) dn = True continue elif choice in ['u', 'U']: # unlink - we remove the section if there's any text = text[:m.start()] + link_text + text[m.end():] unlink = True continue else: if len(choice) > 0 and choice[0] == 'r': # we want to throw away the original link text replaceit = True choice = choice[1:] elif include == "redirect": replaceit = True else: replaceit = False try: choice = int(choice) except ValueError: pywikibot.output(u"Unknown option") # step back to ask the user again what to do with the # current link curpos -= 1 continue if choice >= len(self.alternatives) or choice < 0: pywikibot.output( u"Choice out of range. Please select a number " u"between 0 and %i." % (len(self.alternatives) - 1)) # show list of possible choices self.listAlternatives() # step back to ask the user again what to do with the # current link curpos -= 1 continue new_page_title = self.alternatives[choice] repPl = pywikibot.Page( pywikibot.Link(new_page_title, disambPage.site)) if (new_page_title[0].isupper() or link_text[0].isupper()): new_page_title = repPl.title() else: new_page_title = repPl.title() new_page_title = (new_page_title[0].lower() + new_page_title[1:]) if new_page_title not in new_targets: new_targets.append(new_page_title) if replaceit and trailing_chars: newlink = "[[%s%s]]%s" % (new_page_title, section, trailing_chars) elif replaceit or (new_page_title == link_text and not section): newlink = "[[%s]]" % 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(self.trailR, '', link_text[len(new_page_title):]) == '') and (not section)): newlink = "[[%s]]%s" \ % (link_text[:len(new_page_title)], link_text[len(new_page_title):]) else: newlink = "[[%s%s|%s]]" \ % (new_page_title, section, link_text) text = text[:m.start()] + newlink + text[m.end():] continue pywikibot.output(text[max(0, m.start() - 30):m.end() + 30]) if text == original_text: pywikibot.output(u'\nNo changes have been made:\n') else: pywikibot.output(u'\nThe following changes have been made:\n') pywikibot.showDiff(original_text, text) pywikibot.output(u'') # save the page self.setSummaryMessage(disambPage, new_targets, unlink, dn) try: refPage.put_async(text, comment=self.comment) except pywikibot.LockedPage: pywikibot.output(u'Page not saved: page is locked') except pywikibot.PageNotSaved as error: pywikibot.output(u'Page not saved: %s' % error.args) return True
def result(self, value): """Open a text editor and show the text.""" editor = editarticle.TextEditor() editor.edit(self._page.text, jumpIndex=self._start, highlight=self._page.title())
def treat(self, page): """Work on each page retrieved from generator.""" original_text = page.text applied = set() new_text = original_text last_text = None context = 0 while True: if self.isTextExcepted(new_text): pywikibot.output( 'Skipping {} because it contains text ' 'that is on the exceptions list.'.format(page)) return while new_text != last_text: last_text = new_text new_text = self.apply_replacements(last_text, applied, page) if not self.opt.recursive: break if new_text == original_text: pywikibot.output('No changes were necessary in ' + page.title(as_link=True)) return if self.opt.addcat: # Fetch only categories in wikitext, otherwise the others # will be explicitly added. cats = textlib.getCategoryLinks(new_text, site=page.site) if self.opt.addcat not in cats: cats.append(self.opt.addcat) new_text = textlib.replaceCategoryLinks(new_text, cats, site=page.site) # Show the title of the page we're working on. # Highlight the title in purple. self.current_page = page pywikibot.showDiff(original_text, new_text, context=context) if self.opt.always: break choice = pywikibot.input_choice( 'Do you want to accept these changes?', [('Yes', 'y'), ('No', 'n'), ('Edit original', 'e'), ('edit Latest', 'l'), ('open in Browser', 'b'), ('More context', 'm'), ('All', 'a')], default='N') if choice == 'm': context = context * 3 if context else 3 continue if choice in ('e', 'l'): text_editor = editor.TextEditor() edit_text = original_text if choice == 'e' else new_text as_edited = text_editor.edit(edit_text) # if user didn't press Cancel if as_edited and as_edited != new_text: new_text = as_edited if choice == 'l': # prevent changes from being applied again last_text = new_text continue if choice == 'b': pywikibot.bot.open_webbrowser(page) try: original_text = page.get(get_redirect=True, force=True) except pywikibot.NoPage: pywikibot.output('Page {0} has been deleted.'.format( page.title())) break new_text = original_text last_text = None continue if choice == 'a': self.opt.always = True if choice == 'y': self.save(page, original_text, new_text, applied, show_diff=False, quiet=True, callback=self._replace_async_callback, asynchronous=True) while not self._pending_processed_titles.empty(): proc_title, res = self._pending_processed_titles.get() pywikibot.output('Page {0}{1} saved'.format( proc_title, '' if res else ' not')) # choice must be 'N' break if self.opt.always and new_text != original_text: self.save(page, original_text, new_text, applied, show_diff=False, asynchronous=False)