Additional IRC commands and bot tasks for EarwigBot 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.

118 lines
4.1 KiB

  1. # Copyright (C) 2015 Ben Kurtovic <ben.kurtovic@gmail.com>
  2. #
  3. # Permission is hereby granted, free of charge, to any person obtaining a copy
  4. # of this software and associated documentation files (the "Software"), to deal
  5. # in the Software without restriction, including without limitation the rights
  6. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. # copies of the Software, and to permit persons to whom the Software is
  8. # furnished to do so, subject to the following conditions:
  9. #
  10. # The above copyright notice and this permission notice shall be included in
  11. # all copies or substantial portions of the Software.
  12. #
  13. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  19. # SOFTWARE.
  20. from json import loads
  21. from urllib.error import HTTPError
  22. from urllib.request import urlopen
  23. from earwigbot.commands import Command
  24. class Stars(Command):
  25. """Get the number of stargazers for a given GitHub repository."""
  26. name = "stars"
  27. commands = ["stars", "stargazers"]
  28. API_REPOS = "https://api.github.com/repos/{repo}"
  29. API_USERS = "https://api.github.com/users/{user}/repos?per_page=100"
  30. EXAMPLE = "!stars earwig/earwigbot"
  31. def process(self, data):
  32. if not data.args:
  33. msg = "Which GitHub repository or user should I look up? Example: \x0306{0}\x0f."
  34. self.reply(data, msg.format(self.EXAMPLE))
  35. return
  36. arg = data.args[0]
  37. if "/" in arg:
  38. self.handle_repo(data, arg)
  39. else:
  40. self.handle_user(data, arg)
  41. def handle_repo(self, data, arg):
  42. """Handle !stars <user>/<repo>."""
  43. repo = self.get_repo(arg)
  44. if repo is None:
  45. self.reply(data, "Repository not found. Is it private?")
  46. return
  47. count = int(repo["stargazers_count"])
  48. plural = "" if count == 1 else "s"
  49. msg = "\x0303{0}\x0f has \x02{1}\x0f stargazer{2}: {3}"
  50. self.reply(data, msg.format(repo["full_name"], count, plural, repo["html_url"]))
  51. def handle_user(self, data, arg):
  52. """Handle !stars <user>."""
  53. repos = self.get_user_repos(arg)
  54. if repos is None:
  55. self.reply(data, "User not found.")
  56. return
  57. star_count = sum(repo["stargazers_count"] for repo in repos)
  58. repo_count = len(repos)
  59. star_plural = "" if star_count == 1 else "s"
  60. repo_plural = "" if len(repos) == 1 else "s"
  61. if len(repos) == 100:
  62. star_count = f"{star_count}+"
  63. repo_count = f"{repo_count}+"
  64. if len(repos) > 0:
  65. name = repos[0]["owner"]["login"]
  66. url = repos[0]["owner"]["html_url"]
  67. else:
  68. name = arg
  69. url = f"https://github.com/{name}"
  70. msg = (
  71. "\x0303{0}\x0f has \x02{1}\x0f stargazer{2} across \x02{3}\x0f repo{4}: {5}"
  72. )
  73. self.reply(
  74. data,
  75. msg.format(name, star_count, star_plural, repo_count, repo_plural, url),
  76. )
  77. def get_repo(self, repo):
  78. """Return the API JSON dump for a given repository.
  79. Return None if the repo doesn't exist or is private.
  80. """
  81. try:
  82. query = urlopen(self.API_REPOS.format(repo=repo)).read()
  83. except HTTPError:
  84. return None
  85. res = loads(query)
  86. if res and "id" in res and not res["private"]:
  87. return res
  88. return None
  89. def get_user_repos(self, user):
  90. """Return the API JSON dump for a given user's repositories.
  91. Return None if the user doesn't exist.
  92. """
  93. try:
  94. query = urlopen(self.API_USERS.format(user=user)).read()
  95. except HTTPError:
  96. return None
  97. res = loads(query)
  98. if res and isinstance(res, list):
  99. return res
  100. return None