PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/SMHoF/plugin.py

https://github.com/theY4Kman/Yakbot-plugins
Python | 148 lines | 89 code | 26 blank | 33 comment | 17 complexity | 56027b4c43a166e6d27242e97017814b MD5 | raw file
  1. #!/usr/bin/env python
  2. # =============================================================================
  3. # SourceMod Donor Hall of Fame
  4. # Copyright (C) 2010 Zach "theY4Kman" Kanzler <they4kman@gmail.com>
  5. # =============================================================================
  6. #
  7. # This program is free software; you can redistribute it and/or modify it under
  8. # the terms of the GNU General Public License, version 3.0, as published by the
  9. # Free Software Foundation.
  10. #
  11. # This program is distributed in the hope that it will be useful, but WITHOUT
  12. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  13. # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  14. # details.
  15. #
  16. # You should have received a copy of the GNU General Public License along with
  17. # this program. If not, see <http://www.gnu.org/licenses/>.
  18. import re
  19. from urllib2 import urlopen
  20. import supybot.utils as utils
  21. from supybot.commands import *
  22. import supybot.plugins as plugins
  23. import supybot.ircutils as ircutils
  24. import supybot.callbacks as callbacks
  25. import htmlentitydefs
  26. def unescape(text):
  27. '''
  28. Removes HTML or XML character references
  29. and entities from a text string.
  30. keep &amp;, &gt;, &lt; in the source code.
  31. from Fredrik Lundh
  32. http://effbot.org/zone/re-sub.htm#unescape-html
  33. '''
  34. def fixup(m):
  35. text = m.group(0)
  36. if text[:2] == "&#":
  37. # character reference
  38. try:
  39. if text[:3] == "&#x":
  40. return unichr(int(text[3:-1], 16))
  41. else:
  42. return unichr(int(text[2:-1]))
  43. except ValueError:
  44. pass
  45. else:
  46. # named entity
  47. try:
  48. text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
  49. except KeyError:
  50. pass
  51. return text # leave as is
  52. return re.sub("&#?\w+;", fixup, text)
  53. class SMHoF(callbacks.Plugin):
  54. """
  55. !top
  56. !latest
  57. """
  58. threaded = True
  59. RGX_DONOR = re.compile('<td style="width: 45px;">\s*<i>(?P<date>[^<]+)</i>\s*</td>\s*<td>'
  60. '\s*\\$(?P<amount>\d+) - (<a href="http://forums\\.alliedmods\\.net/member\\.php'
  61. '\\?u=(?P<forum_uid>\d+)">)?(?P<name>[^<]+)(</a>)?\s*'
  62. '(\\(<a href="(?P<homepage>[^"]*)">homepage</a>\\))?\s*</td>', re.M)
  63. RGX_TOPDONOR = re.compile('<td style="width: 45px;">\s*\\$(?P<amount>\d+)'
  64. '\s*</td>\s*<td>\s*(<a href="http://forums\\.alliedmods\\.net/member\\.php'
  65. '\\?u=(?P<forum_uid>\d+)">)?(?P<name>[^<]+)(</a>)?\s*'
  66. '(\\(<a href="(?P<homepage>[^"]*)">homepage</a>\\))?\s*</td>', re.M)
  67. def top(self, irc, msg, args):
  68. '''- Displays the top 10 donors.'''
  69. donors = self.TOP_DONORS()
  70. r = ', '.join(['$%s - %s' % (d['amount'], d['name']) for d in donors])
  71. irc.reply('Top donors: ' + r)
  72. top = wrap(top, [])
  73. def latest(self, irc, msg, args):
  74. '''- Displays the latest 10 donors.'''
  75. donors = self.LATEST_DONORS()[:10]
  76. r = ', '.join(['$%s - %s (%s)' % (d['amount'], d['name'], d['date']) for d in donors])
  77. irc.reply('Latest donors: ' + r)
  78. latest = wrap(latest, [])
  79. def TOP_DONORS(self):
  80. page = urlopen('http://www.sourcemod.net/halloffame.php')
  81. if page is None:
  82. raise HallOfFameError('could not access sourcemod.net/halloffame.php')
  83. contents = page.read()
  84. mtx = self.RGX_TOPDONOR.findall(contents)
  85. if len(mtx) == 0:
  86. raise HallOfFameError('no top donors. Get on the tippy top of the hall of fame!'
  87. ' http://www.sourcemod.net/donate.php')
  88. donors = []
  89. for amount,crumtussels,uid,name,sapcrangle,frizcramble,homepage in mtx[:10]:
  90. donors.append({
  91. 'amount': amount,
  92. 'uid': uid,
  93. 'homepage': unescape(homepage),
  94. 'name': unescape(name.strip()),
  95. })
  96. return donors
  97. def LATEST_DONORS(self):
  98. page = urlopen('http://www.sourcemod.net/halloffame.php')
  99. if page is None:
  100. raise HallOfFameError('could not access sourcemod.net/halloffame.php')
  101. contents = page.read()
  102. latest_idx = contents.find('Donors this month:')
  103. if latest_idx == -1:
  104. raise HallOfFameError('could not find latest donors on '
  105. 'sourcemod.net/halloffame.php')
  106. goodbits = contents[latest_idx:]
  107. mtx = self.RGX_DONOR.findall(goodbits)
  108. if len(mtx) == 0:
  109. raise HallOfFameError('no recent donors. Get on the hall of fame!'
  110. ' http://www.sourcemod.net/donate.php')
  111. donors = []
  112. for date,amount,crumtussels,uid,name,sapcrangle,frizcramble,homepage in mtx:
  113. donors.append({
  114. 'date': date,
  115. 'amount': amount,
  116. 'uid': uid,
  117. 'homepage': unescape(homepage),
  118. 'name': unescape(name.strip()),
  119. })
  120. return donors
  121. Class = SMHoF
  122. # vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: