/SMHoF/plugin.py
Python | 148 lines | 89 code | 26 blank | 33 comment | 17 complexity | 56027b4c43a166e6d27242e97017814b MD5 | raw file
- #!/usr/bin/env python
- # =============================================================================
- # SourceMod Donor Hall of Fame
- # Copyright (C) 2010 Zach "theY4Kman" Kanzler <they4kman@gmail.com>
- # =============================================================================
- #
- # This program is free software; you can redistribute it and/or modify it under
- # the terms of the GNU General Public License, version 3.0, as published by the
- # Free Software Foundation.
- #
- # This program is distributed in the hope that it will be useful, but WITHOUT
- # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- # details.
- #
- # You should have received a copy of the GNU General Public License along with
- # this program. If not, see <http://www.gnu.org/licenses/>.
- import re
- from urllib2 import urlopen
- import supybot.utils as utils
- from supybot.commands import *
- import supybot.plugins as plugins
- import supybot.ircutils as ircutils
- import supybot.callbacks as callbacks
- import htmlentitydefs
- def unescape(text):
- '''
- Removes HTML or XML character references
- and entities from a text string.
- keep &, >, < in the source code.
- from Fredrik Lundh
- http://effbot.org/zone/re-sub.htm#unescape-html
- '''
- def fixup(m):
- text = m.group(0)
- if text[:2] == "&#":
- # character reference
- try:
- if text[:3] == "&#x":
- return unichr(int(text[3:-1], 16))
- else:
- return unichr(int(text[2:-1]))
- except ValueError:
- pass
- else:
- # named entity
- try:
- text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
- except KeyError:
- pass
- return text # leave as is
- return re.sub("&#?\w+;", fixup, text)
- class SMHoF(callbacks.Plugin):
- """
- !top
- !latest
- """
- threaded = True
-
- RGX_DONOR = re.compile('<td style="width: 45px;">\s*<i>(?P<date>[^<]+)</i>\s*</td>\s*<td>'
- '\s*\\$(?P<amount>\d+) - (<a href="http://forums\\.alliedmods\\.net/member\\.php'
- '\\?u=(?P<forum_uid>\d+)">)?(?P<name>[^<]+)(</a>)?\s*'
- '(\\(<a href="(?P<homepage>[^"]*)">homepage</a>\\))?\s*</td>', re.M)
- RGX_TOPDONOR = re.compile('<td style="width: 45px;">\s*\\$(?P<amount>\d+)'
- '\s*</td>\s*<td>\s*(<a href="http://forums\\.alliedmods\\.net/member\\.php'
- '\\?u=(?P<forum_uid>\d+)">)?(?P<name>[^<]+)(</a>)?\s*'
- '(\\(<a href="(?P<homepage>[^"]*)">homepage</a>\\))?\s*</td>', re.M)
-
-
- def top(self, irc, msg, args):
- '''- Displays the top 10 donors.'''
- donors = self.TOP_DONORS()
- r = ', '.join(['$%s - %s' % (d['amount'], d['name']) for d in donors])
- irc.reply('Top donors: ' + r)
- top = wrap(top, [])
-
- def latest(self, irc, msg, args):
- '''- Displays the latest 10 donors.'''
- donors = self.LATEST_DONORS()[:10]
- r = ', '.join(['$%s - %s (%s)' % (d['amount'], d['name'], d['date']) for d in donors])
- irc.reply('Latest donors: ' + r)
- latest = wrap(latest, [])
-
- def TOP_DONORS(self):
- page = urlopen('http://www.sourcemod.net/halloffame.php')
- if page is None:
- raise HallOfFameError('could not access sourcemod.net/halloffame.php')
-
- contents = page.read()
-
- mtx = self.RGX_TOPDONOR.findall(contents)
- if len(mtx) == 0:
- raise HallOfFameError('no top donors. Get on the tippy top of the hall of fame!'
- ' http://www.sourcemod.net/donate.php')
-
- donors = []
- for amount,crumtussels,uid,name,sapcrangle,frizcramble,homepage in mtx[:10]:
- donors.append({
- 'amount': amount,
- 'uid': uid,
- 'homepage': unescape(homepage),
- 'name': unescape(name.strip()),
- })
-
- return donors
- def LATEST_DONORS(self):
- page = urlopen('http://www.sourcemod.net/halloffame.php')
- if page is None:
- raise HallOfFameError('could not access sourcemod.net/halloffame.php')
-
- contents = page.read()
-
- latest_idx = contents.find('Donors this month:')
- if latest_idx == -1:
- raise HallOfFameError('could not find latest donors on '
- 'sourcemod.net/halloffame.php')
-
- goodbits = contents[latest_idx:]
- mtx = self.RGX_DONOR.findall(goodbits)
- if len(mtx) == 0:
- raise HallOfFameError('no recent donors. Get on the hall of fame!'
- ' http://www.sourcemod.net/donate.php')
-
- donors = []
- for date,amount,crumtussels,uid,name,sapcrangle,frizcramble,homepage in mtx:
- donors.append({
- 'date': date,
- 'amount': amount,
- 'uid': uid,
- 'homepage': unescape(homepage),
- 'name': unescape(name.strip()),
- })
-
- return donors
- Class = SMHoF
- # vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79: