diff --git a/plugins/Weather.py b/plugins/Weather.py
index 9ce6e07e8..b639f5122 100644
--- a/plugins/Weather.py
+++ b/plugins/Weather.py
@@ -78,7 +78,7 @@ class WeatherCommand(registry.String):
# Registry variables moved to the bottom to use Weather.weatherCommands.
class Weather(callbacks.Privmsg):
- weatherCommands = ['ham', 'cnn']
+ weatherCommands = ['ham', 'cnn', 'wunder']
threaded = True
def callCommand(self, method, irc, msg, *L):
try:
@@ -129,24 +129,24 @@ class Weather(callbacks.Privmsg):
unit = 'F'
return '%s%s%s' % (temp, deg, unit)
- _cityregex = re.compile(
+ _hamLoc = re.compile(
r'
'
r'(.*?), (.*?),(.*?) | ', re.I)
_interregex = re.compile(
r''
r'([^,]+), ([^<]+) | ', re.I)
- _condregex = re.compile(
+ _hamCond = re.compile(
r''
r'([^<]+) | ', re.I)
- _tempregex = re.compile(
+ _hamTemp = re.compile(
r''
r'(-?\d+)(.*?)(F|C) | ', re.I)
_temp = re.compile(r'(-?\d+)(.*?)(F|C)')
- _chillregex = re.compile(
+ _hamChill = re.compile(
r'Wind Chill:\s+'
r'([^N][^<]+) | ',
re.I | re.S)
- _heatregex = re.compile(
+ _hamHeat = re.compile(
r'Heat Index:\s+'
r'([^N][^<]+) | ',
re.I | re.S)
@@ -220,7 +220,7 @@ class Weather(callbacks.Privmsg):
irc.error('No such location could be found.')
return
- headData = self._cityregex.search(html)
+ headData = self._hamLoc.search(html)
if headData is not None:
(city, state, country) = headData.groups()
else:
@@ -233,7 +233,7 @@ class Weather(callbacks.Privmsg):
city = city.strip()
state = state.strip()
- temp = self._tempregex.search(html)
+ temp = self._hamTemp.search(html)
convert = self.registryValue('convert', msg.args[0])
if temp is not None:
(temp, deg, unit) = temp.groups()
@@ -241,11 +241,11 @@ class Weather(callbacks.Privmsg):
temp = self._getTemp(int(temp), deg, unit, msg.args[0])
else:
temp = deg.join((temp, unit))
- conds = self._condregex.search(html)
+ conds = self._hamCond.search(html)
if conds is not None:
conds = conds.group(1)
index = ''
- chill = self._chillregex.search(html)
+ chill = self._hamChill.search(html)
if chill is not None:
chill = chill.group(1)
chill = utils.htmlToText(chill)
@@ -256,7 +256,7 @@ class Weather(callbacks.Privmsg):
chill = self._getTemp(int(chill), deg, unit,msg.args[0])
if float(chill[:-2]) < float(temp[:-2]):
index = ' (Wind Chill: %s)' % chill
- heat = self._heatregex.search(html)
+ heat = self._hamHeat.search(html)
if heat is not None:
heat = heat.group(1)
heat = utils.htmlToText(heat)
@@ -270,18 +270,19 @@ class Weather(callbacks.Privmsg):
index = ' (Heat Index: %s)' % heat
if temp and conds and city and state:
conds = conds.replace('Tsra', 'Thunderstorms')
- s = 'The current temperature in %s, %s is %s%s. Conditions: %s.'% \
+ s = 'The current temperature at %s, %s is %s%s. Conditions: %s.'% \
(city, state, temp, index, conds)
irc.reply(s)
else:
irc.error('The format of the page was odd.')
_cnnUrl = 'http://weather.cnn.com/weather/search?wsearch='
- _fTemp = re.compile(r'(-?\d+)(°)(F)', re.I | re.S)
- _conds = re.compile(r'align="center">([^<]+)', re.I|re.S)
- _humidity = re.compile(r'Rel. Humidity: (\d+%)', re.I | re.S)
- _wind = re.compile(r'Wind: ([^<]+)', re.I | re.S)
- _location = re.compile(r'([^<]+)', re.I | re.S)
+ _cnnFTemp = re.compile(r'(-?\d+)(°)(F)', re.I | re.S)
+ _cnnCond = re.compile(r'align="center">([^<]+)',
+ re.I | re.S)
+ _cnnHumid = re.compile(r'Rel. Humidity: (\d+%)', re.I | re.S)
+ _cnnWind = re.compile(r'Wind: ([^<]+)', re.I | re.S)
+ _cnnLoc = re.compile(r'([^<]+)', re.I | re.S)
# Certain countries are expected to use a standard abbreviation
# The weather we pull uses weird codes. Map obvious ones here.
_cnnCountryMap = {'uk': 'en', 'de': 'ge'}
@@ -314,11 +315,11 @@ class Weather(callbacks.Privmsg):
if "No search results" in text or "does not match a zip code" in text:
irc.error('No such location could be found.')
return
- location = self._location.search(text)
- temp = self._fTemp.search(text)
- conds = self._conds.search(text)
- humidity = self._humidity.search(text)
- wind = self._wind.search(text)
+ location = self._cnnLoc.search(text)
+ temp = self._cnnFTemp.search(text)
+ conds = self._cnnCond.search(text)
+ humidity = self._cnnHumid.search(text)
+ wind = self._cnnWind.search(text)
convert = self.registryValue('convert', msg.args[0])
if location and temp:
location = location.group(1)
@@ -328,8 +329,7 @@ class Weather(callbacks.Privmsg):
temp = self._getTemp(int(temp), deg, unit, msg.args[0])
else:
temp = deg.join((temp, unit))
- resp = 'The current temperature in %s is %s.' % (location, temp)
- resp = [resp]
+ resp = ['The current temperature at %s is %s.' % (location, temp)]
if conds is not None:
resp.append('Conditions: %s.' % conds.group(1))
if humidity is not None:
@@ -337,7 +337,104 @@ class Weather(callbacks.Privmsg):
if wind is not None:
resp.append('Wind: %s.' % wind.group(1))
resp = map(utils.htmlToText, resp)
- irc.reply(' '.join(resp))
+ irc.reply(' '.join(resp))
+ else:
+ irc.error('Could not find weather information.')
+
+ _wunderUrl = 'http://www.weatherunderground.com/cgi-bin/findweather/'\
+ 'getForecast?query='
+ _wunderLoc = re.compile(r'[^:]+: ([^<]+)', re.I | re.S)
+ _wunderFTemp = re.compile(
+ r'graphics/conds.*?(-?\d+) (°)(F)',
+ re.I | re.S)
+ _wunderCond = re.compile(r'
\s+([^<]+)',
+ re.I | re.S)
+ _wunderHumid = re.compile(r'Humidity:]+>(\d+%)',
+ re.I | re.S)
+ _wunderDew = re.compile(r'Dew Point: | ]+>\s+'
+ r'(-?\d+) (°)(F)',
+ re.I | re.S)
+ _wunderWind = re.compile(
+ r'Wind: | ]+>\s+\s+(\d+) (mph)'
+ r'\s+/\s+(\d+) (km/h)\s+'
+ r'\s+from the\s+(\w{3})', re.I | re.S)
+ _wunderPressure = re.compile(
+ r'Pressure: | \s+(\d+\.\d+) (in)\s+/\s+'
+ r'(\d+) (hPa)', re.I | re.S)
+ _wunderVisible = re.compile(
+ r'Visibility: | ]+>\s+(\w+) (miles)'
+ r'\s+/\s+(\w+) (kilometers)',
+ re.I | re.S)
+ _wunderUv = re.compile(r'UV: | ]+>(\d\d?)', re.I | re.S)
+ _wunderTime = re.compile(r'Updated:\s+([\w\s:,]+)', re.I | re.S)
+ def wunder(self, irc, msg, args):
+ """
+
+ Returns the approximate weather conditions for a given city.
+ """
+ loc = ' '.join(args)
+ url = '%s%s' % (self._wunderUrl, urllib.quote(loc))
+ try:
+ text = webutils.getUrl(url)
+ except webutils.WebError, e:
+ irc.error(str(e))
+ return
+ if 'Search not found' in text:
+ irc.error('No such location could be found.')
+ return
+ if 'Search results for' in text:
+ irc.error('Multiple locations found. Please be more specific.')
+ return
+ location = self._wunderLoc.search(text)
+ temp = self._wunderFTemp.search(text)
+ convert = self.registryValue('convert', msg.args[0])
+ if location and temp:
+ location = location.group(1)
+ location = location.replace(' Forecast', '')
+ (temp, deg, unit) = temp.groups()
+ if convert:
+ temp = self._getTemp(int(temp), deg, unit, msg.args[0])
+ else:
+ temp = deg.join((temp, unit))
+ time = self._wunderTime.search(text)
+ if time is not None:
+ time = ' (%s)' % time.group(1)
+ else:
+ time = ''
+ resp = ['The current temperature at %s is %s%s.' %\
+ (location, temp, time)]
+ conds = self._wunderCond.search(text)
+ if conds is not None:
+ resp.append('Conditions: %s.' % conds.group(1))
+ humidity = self._wunderHumid.search(text)
+ if humidity is not None:
+ resp.append('Humidity: %s.' % humidity.group(1))
+ dewpt = self._wunderDew.search(text)
+ if dewpt is not None:
+ (dew, deg, unit) = dewpt.groups()
+ if convert:
+ dew = self._getTemp(int(dew), deg, unit, msg.args[0])
+ else:
+ dew = deg.join((dew, unit))
+ resp.append('Dew Point: %s.' % dew)
+ wind = self._wunderWind.search(text)
+ if wind is not None:
+ resp.append('Wind: %s at %s %s (%s %s).' % (wind.group(5),
+ wind.group(1),
+ wind.group(2),
+ wind.group(3),
+ wind.group(4)))
+ press = self._wunderPressure.search(text)
+ if press is not None:
+ resp.append('Pressure: %s %s (%s %s).' % press.groups())
+ vis = self._wunderVisible.search(text)
+ if vis is not None:
+ resp.append('Visibility: %s %s (%s %s).' % vis.groups())
+ uv = self._wunderUv.search(text)
+ if uv is not None:
+ resp.append('UV: %s' % uv.group(1))
+ resp = map(utils.htmlToText, resp)
+ irc.reply(' '.join(resp))
else:
irc.error('Could not find weather information.')
|