A Python robot that edits Wikipedia and interacts with people over IRC https://en.wikipedia.org/wiki/User:EarwigBot
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

106 rindas
4.6 KiB

  1. # -*- coding: utf-8 -*-
  2. #
  3. # Copyright (C) 2009-2012 by Ben Kurtovic <ben.kurtovic@verizon.net>
  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 earwigbot.wiki.page import Page
  23. __all__ = ["Category"]
  24. class Category(Page):
  25. """
  26. **EarwigBot's Wiki Toolset: Category Class**
  27. Represents a category on a given :py:class:`~earwigbot.wiki.site.Site`, a
  28. subclass of :py:class:`~earwigbot.wiki.page.Page`. Provides additional
  29. methods, but :py:class:`~earwigbot.wiki.page.Page`'s own methods should
  30. work fine on :py:class:`Category` objects. :py:meth:`site.get_page()
  31. <earwigbot.wiki.site.Site.get_page>` will return a :py:class:`Category`
  32. instead of a :py:class:`~earwigbot.wiki.page.Page` if the given title is in
  33. the category namespace; :py:meth:`~earwigbot.wiki.site.Site.get_category`
  34. is shorthand, accepting category names without the namespace prefix.
  35. *Public methods:*
  36. - :py:meth:`get_members`: returns a list of page titles in the category
  37. """
  38. def __repr__(self):
  39. """Returns the canonical string representation of the Category."""
  40. res = "Category(title={0!r}, follow_redirects={1!r}, site={2!r})"
  41. return res.format(self._title, self._follow_redirects, self._site)
  42. def __str__(self):
  43. """Returns a nice string representation of the Category."""
  44. return '<Category "{0}" of {1}>'.format(self.title(), str(self._site))
  45. def _get_members_via_sql(self, limit):
  46. """Return a list of tuples of (title, pageid) in the category."""
  47. query = """SELECT page_title, page_namespace, page_id FROM page
  48. JOIN categorylinks ON page_id = cl_from
  49. WHERE cl_to = ?"""
  50. title = self.title().replace(" ", "_").split(":", 1)[1]
  51. if limit:
  52. query += " LIMIT ?"
  53. result = self._site.sql_query(query, (title, limit))
  54. else:
  55. result = self._site.sql_query(query, (title,))
  56. members = []
  57. for row in result:
  58. base = row[0].replace("_", " ").decode("utf8")
  59. namespace = self._site.namespace_id_to_name(row[1])
  60. if namespace:
  61. title = u":".join((namespace, base))
  62. else: # Avoid doing a silly (albeit valid) ":Pagename" thing
  63. title = base
  64. members.append((title, row[2]))
  65. return members
  66. def _get_members_via_api(self, limit):
  67. """Return a list of page titles in the category using the API."""
  68. params = {"action": "query", "list": "categorymembers",
  69. "cmlimit": limit, "cmtitle": self._title}
  70. if not limit:
  71. params["cmlimit"] = 50 # Default value
  72. result = self._site.api_query(**params)
  73. members = result['query']['categorymembers']
  74. return [member["title"] for member in members]
  75. def get_members(self, use_sql=False, limit=None):
  76. """Returns a list of page titles in the category.
  77. If *use_sql* is ``True``, we will use a SQL query instead of the API.
  78. Pages will be returned as tuples of ``(title, pageid)`` instead of just
  79. titles.
  80. If *limit* is provided, we will provide this many titles, or less if
  81. the category is smaller. It defaults to 50 for API queries; normal
  82. users can go up to 500, and bots can go up to 5,000 on a single API
  83. query. If we're using SQL, the limit is ``None`` by default (returning
  84. all pages in the category), but an arbitrary limit can still be chosen.
  85. """
  86. if use_sql:
  87. return self._get_members_via_sql(limit)
  88. else:
  89. return self._get_members_via_api(limit)