A Python robot that edits Wikipedia and interacts with people over IRC https://en.wikipedia.org/wiki/User:EarwigBot
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
пре 13 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. # -*- coding: utf-8 -*-
  2. import re
  3. from classes import BaseCommand
  4. import config
  5. import wiki
  6. class Command(BaseCommand):
  7. """Get the number of pending AfC submissions, open redirect requests, and
  8. open file upload requests."""
  9. name = "status"
  10. hooks = ["join", "msg"]
  11. def check(self, data):
  12. commands = ["status", "count", "num", "number"]
  13. if data.is_command and data.command in commands:
  14. return True
  15. try:
  16. if data.line[1] == "JOIN" and data.chan == "#wikipedia-en-afc":
  17. if data.nick != config.irc["frontend"]["nick"]:
  18. return True
  19. except IndexError:
  20. pass
  21. return False
  22. def process(self, data):
  23. self.site = wiki.get_site()
  24. self.site._maxlag = None
  25. if data.line[1] == "JOIN":
  26. status = " ".join(("\x02Current status:\x0F", self.get_status()))
  27. self.connection.notice(data.nick, status)
  28. return
  29. if data.args:
  30. action = data.args[0].lower()
  31. if action.startswith("sub") or action == "s":
  32. subs = self.count_submissions()
  33. msg = "there are \x0305{0}\x0301 pending AfC submissions (\x0302WP:AFC\x0301)."
  34. self.connection.reply(data, msg.format(subs))
  35. elif action.startswith("redir") or action == "r":
  36. redirs = self.count_redirects()
  37. msg = "there are \x0305{0}\x0301 open redirect requests (\x0302WP:AFC/R\x0301)."
  38. self.connection.reply(data, msg.format(redirs))
  39. elif action.startswith("file") or action == "f":
  40. files = self.count_redirects()
  41. msg = "there are \x0305{0}\x0301 open file upload requests (\x0302WP:FFU\x0301)."
  42. self.connection.reply(data, msg.format(files))
  43. elif action.startswith("agg") or action == "a":
  44. try:
  45. agg_num = int(data.args[1])
  46. except IndexError:
  47. agg_data = (self.count_submissions(),
  48. self.count_redirects(), self.count_files())
  49. agg_num = self.get_aggregate_number(agg_data)
  50. except ValueError:
  51. msg = "\x0303{0}\x0301 isn't a number!"
  52. self.connection.reply(data, msg.format(data.args[1]))
  53. return
  54. aggregate = self.get_aggregate(agg_num)
  55. msg = "aggregate is \x0305{0}\x0301 (AfC {1})."
  56. self.connection.reply(data, msg.format(agg_num, aggregate))
  57. elif action.startswith("nocolor") or action == "n":
  58. self.connection.reply(data, self.get_status(color=False))
  59. else:
  60. msg = "unknown argument: \x0303{0}\x0301. Valid args are 'subs', 'redirs', 'files', 'agg', 'nocolor'."
  61. self.connection.reply(data, msg.format(data.args[0]))
  62. else:
  63. self.connection.reply(data, self.get_status())
  64. def get_status(self, color=True):
  65. subs = self.count_submissions()
  66. redirs = self.count_redirects()
  67. files = self.count_files()
  68. agg_num = self.get_aggregate_number((subs, redirs, files))
  69. aggregate = self.get_aggregate(agg_num)
  70. if color:
  71. msg = "Articles for creation {0} (\x0302AFC\x0301: \x0305{1}\x0301; \x0302AFC/R\x0301: \x0305{2}\x0301; \x0302FFU\x0301: \x0305{3}\x0301)."
  72. else:
  73. msg = "Articles for creation {0} (AFC: {1}; AFC/R: {2}; FFU: {3})."
  74. return msg.format(aggregate, subs, redirs, files)
  75. def count_submissions(self):
  76. """Returns the number of open AFC submissions (count of CAT:PEND)."""
  77. cat = self.site.get_category("Pending AfC submissions")
  78. subs = len(cat.members(limit=2500, use_sql=True))
  79. # Remove [[Wikipedia:Articles for creation/Redirects]] and
  80. # [[Wikipedia:Files for upload]], which aren't real submissions:
  81. return subs - 2
  82. def count_redirects(self):
  83. """Returns the number of open redirect submissions. Calculated as the
  84. total number of submissions minus the closed ones."""
  85. title = "Wikipedia:Articles for creation/Redirects"
  86. content = self.site.get_page(title).get()
  87. total = len(re.findall("^\s*==(.*?)==\s*$", content, re.MULTILINE))
  88. closed = content.lower().count("{{afc-c|b}}")
  89. redirs = total - closed
  90. return redirs
  91. def count_files(self):
  92. """Returns the number of open WP:FFU (Files For Upload) requests.
  93. Calculated as the total number of requests minus the closed ones."""
  94. content = self.site.get_page("Wikipedia:Files for upload").get()
  95. total = len(re.findall("^\s*==(.*?)==\s*$", content, re.MULTILINE))
  96. closed = content.lower().count("{{ifu-c|b}}")
  97. files = total - closed
  98. return files
  99. def get_aggregate(self, num):
  100. """Returns a human-readable AFC status based on the number of pending
  101. AFC submissions, open redirect requests, and open FFU requests. This
  102. does not match {{AFC status}} directly because my algorithm factors in
  103. WP:AFC/R and WP:FFU while the template only looks at the main
  104. submissions. My reasoning is that AFC/R and FFU are still part of
  105. the project, so even if there are no pending submissions, a backlog at
  106. FFU (for example) indicates that our work is *not* done and the
  107. project-wide backlog is most certainly *not* clear."""
  108. if num == 0:
  109. return "is \x02\x0303clear\x0301\x0F"
  110. elif num < 125: # < 25 subs
  111. return "is \x0303almost clear\x0301"
  112. elif num < 200: # < 40 subs
  113. return "is \x0312normal\x0301"
  114. elif num < 275: # < 55 subs
  115. return "is \x0307lightly backlogged\x0301"
  116. elif num < 350: # < 70 subs
  117. return "is \x0304backlogged\x0301"
  118. elif num < 500: # < 100 subs
  119. return "is \x02\x0304heavily backlogged\x0301\x0F"
  120. else: # >= 100 subs
  121. return "is \x02\x1F\x0304severely backlogged\x0301\x0F"
  122. def get_aggregate_number(self, (subs, redirs, files)):
  123. """Returns an 'aggregate number' based on the real number of pending
  124. submissions in CAT:PEND (subs), open redirect submissions in WP:AFC/R
  125. (redirs), and open files-for-upload requests in WP:FFU (files)."""
  126. num = (subs * 5) + (redirs * 2) + (files * 2)
  127. return num