Additional IRC commands and bot tasks for EarwigBot https://en.wikipedia.org/wiki/User:EarwigBot
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
5.1 KiB

  1. # -*- coding: utf-8 -*-
  2. #
  3. # Copyright (C) 2015 Ben Kurtovic <ben.kurtovic@gmail.com>
  4. #
  5. # Permission is hereby granted, free of charge, to any person obtaining a copy
  6. # of this software and associated documentation files (the "Software"), to deal
  7. # in the Software without restriction, including without limitation the rights
  8. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. # copies of the Software, and to permit persons to whom the Software is
  10. # furnished to do so, subject to the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included in
  13. # all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. # SOFTWARE.
  22. from __future__ import unicode_literals
  23. from earwigbot.tasks import Task
  24. from earwigbot.wiki import constants
  25. import mwparserfromhell
  26. class InfoboxStation(Task):
  27. """
  28. A task to replace ``{{Infobox China station}}`` and
  29. ``{{Infobox Japan station}}`` with ``{{Infobox station}}``.
  30. """
  31. name = "infobox_station"
  32. number = 20
  33. def setup(self):
  34. self.site = self.bot.wiki.getsite()
  35. self._targets = {
  36. "China": (
  37. ["Infobox China station", "Infobox china station"],
  38. "Infobox China station/sandbox",
  39. "Infobox China station/sandbox/cats",
  40. "Wikipedia:Templates for discussion/Log/2015 February 8#Template:Infobox China station"
  41. ),
  42. "Japan": (
  43. ["Infobox Japan station", "Infobox japan station"],
  44. "Infobox Japan station/sandbox",
  45. "Infobox Japan station/sandbox/cats",
  46. "Wikipedia:Templates for discussion/Log/2015 May 9#Template:Infobox Japan station"
  47. ),
  48. }
  49. self._replacement = "{{Infobox station}}"
  50. self.summary = self.make_summary(
  51. "Replacing {source} with {dest} per [[{discussion}|TfD]].")
  52. def run(self, **kwargs):
  53. for name, args in self._targets.items():
  54. if self.shutoff_enabled():
  55. return
  56. self._replace(name, args)
  57. def _replace(self, name, args):
  58. """
  59. Replace a template in all pages that transclude it.
  60. """
  61. self.logger.info("Replacing {0} infobox template".format(name))
  62. count = 0
  63. for search in args[0]:
  64. for title in self._get_transclusions(search):
  65. count += 1
  66. if count % 10 == 0 and self.shutoff_enabled():
  67. return
  68. page = self.site.get_page(title)
  69. self._process_page(page, search, args)
  70. def _process_page(self, page, search, args):
  71. """
  72. Process a single page to replace a template.
  73. """
  74. self.logger.debug("Processing [[{0}]]".format(page.title))
  75. if not page.check_exclusion():
  76. self.logger.warn("Bot excluded from [[{0}]]".format(page.title))
  77. return
  78. code = mwparserfromhell.parse(page.get(), skip_style_tags=True)
  79. for tmpl in code.filter_templates():
  80. if tmpl.name.matches(search):
  81. tmpl.name = "subst:" + args[2]
  82. self._add_cats(code, unicode(tmpl))
  83. tmpl.name = "subst:" + args[1]
  84. break
  85. if code == page.get():
  86. msg = "Couldn't figure out what to edit in [[{0}]]"
  87. self.logger.warn(msg.format(page.title))
  88. return
  89. summary = self.summary.format(
  90. source="{{" + search + "}}", dest="{{" + self._replacement + "}}",
  91. discussion=args[3])
  92. page.edit(unicode(code), summary, minor=True)
  93. def _add_cats(self, code, cats):
  94. """Add category data (*cats*) to wikicode."""
  95. for link in code.ifilter_wikilinks():
  96. if link.title.lower().startswith("category:"):
  97. code.insert_before(link, cats + "\n")
  98. return
  99. for tmpl in code.filter_templates():
  100. if tmpl.name.lower().endswith("stub"):
  101. prev = code.get(code.index(tmpl) - 1)
  102. if prev.endswith("\n\n"):
  103. code.replace(prev, prev[:-1])
  104. code.insert_before(tmpl, cats + "\n\n")
  105. def _get_transclusions(self, title):
  106. """
  107. Return a list of mainspace translusions of the given template.
  108. """
  109. query = """SELECT page_title
  110. FROM templatelinks
  111. LEFT JOIN page ON tl_from = page_id
  112. WHERE tl_namespace = ? AND tl_title = ? AND tl_from_namespace = ?"""
  113. results = self.site.sql_query(query, (
  114. constants.NS_TEMPLATE, title.replace(" ", "_"), constants.NS_MAIN))
  115. return [title for (title,) in results]