diff --git a/clock.py b/clock.py index 23d7c0bf0e..b93188eee0 100644 --- a/clock.py +++ b/clock.py @@ -11,6 +11,13 @@ from willie.module import commands, example, OP +def configure(config): + config.interactive_add('clock', 'tz', + 'Preferred time zone (http://dft.ba/-tz)', 'UTC') + config.interactive_add('clock', 'time_format', + 'Preferred time format (http://strftime.net)', '%F - %T%Z') + + def setup(bot): #Having a db means pref's exists. Later, we can just use `if bot.db`. if bot.db and not bot.db.preferences.has_columns('tz'): @@ -38,7 +45,7 @@ def f_time(bot, trigger): return else: bot.say("I'm sorry, I don't know about the %s timezone or" - " user." % tz) + " user. Try one from http://dft.ba/-tz" % tz) return #We don't have a timzeone. Is there one set? If not, just use UTC elif bot.db: @@ -46,12 +53,10 @@ def f_time(bot, trigger): tz = bot.db.preferences.get(trigger.nick, 'tz') if not tz and trigger.sender in bot.db.preferences: tz = bot.db.preferences.get(trigger.sender, 'tz') - if not tz: - tz = 'UTC' - else: - tz = 'UTC' - tzi = pytz.timezone(tz) - now = datetime.datetime.now(tzi) + if not tz and bot.config.has_option('clock', 'tz'): + tz = bot.config.clock.tz + + now = datetime.datetime.now(pytz.timezone(tz or 'UTC')) tformat = '' if bot.db: @@ -111,6 +116,9 @@ def update_user_format(bot, trigger): tz = bot.db.preferences.get(trigger.nick, 'tz') if not tz and trigger.sender in bot.db.preferences: tz = bot.db.preferences.get(trigger.sender, 'tz') + if not tz and bot.config.has_option('clock', 'tz'): + tz = bot.config.clock.tz + now = datetime.datetime.now(pytz.timezone(tz or 'UTC')) timef = '' try: @@ -178,6 +186,9 @@ def update_channel_format(bot, trigger): tz = bot.db.preferences.get(trigger.nick, 'tz') if not tz and trigger.sender in bot.db.preferences: tz = bot.db.preferences.get(trigger.sender, 'tz') + if not tz and bot.config.has_option('clock', 'tz'): + tz = bot.config.clock.tz + now = datetime.datetime.now(pytz.timezone(tz or 'UTC')) timef = '' try: diff --git a/currency.py b/currency.py index 879a0c15dc..fed6423740 100644 --- a/currency.py +++ b/currency.py @@ -16,7 +16,7 @@ # Bank of England, or the European Central Bank. Who knew? base_url = 'http://www.bankofcanada.ca/stats/assets/rates_rss/noon/en_{}.xml' regex = re.compile(r''' - (\d+(?:\.\d+)?) # Decimal number + (\d+(?:\.\d+)?) # Decimal number \s*([a-zA-Z]{3}) # 3-letter currency code \s+(?:in|as|of|to)\s+ # preposition ([a-zA-Z]{3}) # 3-letter currency code @@ -41,13 +41,13 @@ def get_rate(code): return float(rate), name -@commands('cur', 'currrency', 'exchange') +@commands('cur', 'currency', 'exchange') @example('.cur 20 EUR in USD') def exchange(bot, trigger): """Show the exchange rate between two currencies""" match = regex.match(trigger.group(2)) if not match: - #It's appologetic, because it's using Canadian data. + # It's apologetic, because it's using Canadian data. bot.reply("Sorry, I didn't understand the input.") return NOLIMIT diff --git a/github.py b/github.py index 14f19b9f76..e9068686c0 100644 --- a/github.py +++ b/github.py @@ -9,10 +9,12 @@ from datetime import datetime from urllib2 import HTTPError import json -from willie import web -from willie.module import commands +from willie import web, tools +from willie.module import commands, rule, NOLIMIT import os +import re +issueURL = r'https?://(?:www\.)?github.com/([A-z0-9\-]+/[A-z0-9\-]+)/issues/([\d]+)' def checkConfig(bot): if not bot.config.has_option('github', 'oauth_token') or not bot.config.has_option('github', 'repo'): @@ -34,6 +36,11 @@ def configure(config): config.interactive_add('github', 'repo', 'Github repository', 'embolalia/willie') return chunk +def setup(bot): + regex = re.compile(issueURL) + if not bot.memory.contains('url_callbacks'): + bot.memory['url_callbacks'] = tools.WillieMemory() + bot.memory['url_callbacks'][regex] = issue_info @commands('makeissue', 'makebug') def issue(bot, trigger): @@ -55,7 +62,8 @@ def issue(bot, trigger): try: raw = web.post('https://api.github.com/repos/' + gitAPI[1] + '/issues?access_token=' + gitAPI[0], json.dumps(data)) except HTTPError: - return bot.say('The GitHub API returned an error.') + bot.say('The GitHub API returned an error.') + return NOLIMIT data = json.loads(raw) bot.say('Issue #%s posted. %s' % (data['number'], data['html_url'])) @@ -114,7 +122,8 @@ def add_traceback(bot, trigger): + number + '/comments?access_token=' + gitAPI[0], json.dumps({'body': '``\n' + post + '``'})) except OSError: # HTTPError: - return bot.say('The GitHub API returned an error.') + bot.say('The GitHub API returned an error.') + return NOLIMIT data = json.loads(raw) bot.say('Added traceback to issue #%s. %s' % (number, data['html_url'])) @@ -145,7 +154,8 @@ def findIssue(bot, trigger): try: raw = web.get(URL) except HTTPError: - return bot.say('The GitHub API returned an error.') + bot.say('The GitHub API returned an error.') + return NOLIMIT try: if firstParam.isdigit(): @@ -165,6 +175,29 @@ def findIssue(bot, trigger): ('API returned an invalid result on query request ' + trigger.group(2)), 'always') - return bot.say('Invalid result, please try again later.') + bot.say('Invalid result, please try again later.') + return NOLIMIT bot.reply('[#%s]\x02title:\x02 %s \x02|\x02 %s' % (data['number'], data['title'], body)) bot.say(data['html_url']) + +@rule('.*%s.*' % issueURL) +def issue_info(bot, trigger, match=None): + match = match or trigger + URL = 'https://api.github.com/repos/%s/issues/%s' % (match.group(1), match.group(2)) + + try: + raw = web.get(URL) + except HTTPError: + bot.say('The GitHub API returned an error.') + return NOLIMIT + data = json.loads(raw) + try: + if len(data['body'].split('\n')) > 1: + body = data['body'].split('\n')[0] + '...' + else: + body = data['body'].split('\n')[0] + except (KeyError): + bot.say('The API says this is an invalid issue. Please report this if you know it\'s a correct link!') + return NOLIMIT + bot.reply('[#%s]\x02title:\x02 %s \x02|\x02 %s' % (data['number'], data['title'], body)) + diff --git a/rss.py b/rss.py index fa3062ddcb..e283c2ab15 100644 --- a/rss.py +++ b/rss.py @@ -116,7 +116,7 @@ def migrate_from_old_tables(bot, c): def colour_text(text, fg, bg=''): """Given some text and fore/back colours, return a coloured text string.""" - if not fg: + if fg == '': return text else: colour = '{0},{1}'.format(fg, bg) if bg != '' else fg @@ -314,7 +314,7 @@ def _rss_list(self, bot, trigger, c): filtered = [feed for feed in feeds if (feed.channel == channel or channel is None) - and (feed.name == feed_name or feed_name is None)] + and (feed_name is None or feed.name.lower() == feed_name.lower())] if not filtered: bot.reply("No feeds matched the command.") @@ -434,12 +434,15 @@ def disable_feed(): if not fp.entries: continue - feed_etag = fp.etag if hasattr(fp, 'etag') else None - feed_modified = fp.modified if hasattr(fp, 'modified') else None + feed_etag = getattr(fp, 'etag', None) + feed_modified = getattr(fp, 'modified', None) entry = fp.entries[0] + # parse published and updated times into datetime objects (or None) entry_dt = (datetime.fromtimestamp(time.mktime(entry.published_parsed)) - if 'published' in entry else None) + if hasattr(entry, 'published_parsed') else None) + entry_update_dt = (datetime.fromtimestamp(time.mktime(entry.updated_parsed)) + if hasattr(entry, 'updated_parsed') else None) # check if article is new, and skip otherwise if (feed.title == entry.title and feed.link == entry.link @@ -468,11 +471,23 @@ def disable_feed(): feed.name, entry.title, published_dt, entry_dt), 'verbose') continue - # print new entry + # create message for new entry message = u"[\x02{0}\x02] \x02{1}\x02 {2}".format( colour_text(feed.name, feed.fg, feed.bg), entry.title, entry.link) - if entry.updated: - message += " - " + entry.updated + + # append update time if it exists, or published time if it doesn't + timestamp = entry_update_dt or entry_dt + if timestamp: + # attempt to get time format from preferences + tformat = '' + if feed.channel in bot.db.preferences: + tformat = bot.db.preferences.get(feed.channel, 'time_format') or tformat + if not tformat and bot.config.has_option('clock', 'time_format'): + tformat = bot.config.clock.time_format + + message += " - {0}".format(timestamp.strftime(tformat or '%F - %T%Z')) + + # print message bot.msg(feed.channel, message) conn.close() diff --git a/weather.py b/weather.py index c68f6810bf..66602149b3 100644 --- a/weather.py +++ b/weather.py @@ -49,9 +49,9 @@ def get_cover(parsed): def get_temp(parsed): try: condition = parsed.entries[0]['yweather_condition'] - except KeyError: + temp = int(condition['temp']) + except (KeyError, ValueError): return 'unknown' - temp = int(condition['temp']) f = round((temp * 1.8) + 32, 2) return (u'%d\u00B0C (%d\u00B0F)' % (temp, f)) @@ -59,26 +59,22 @@ def get_temp(parsed): def get_pressure(parsed): try: pressure = parsed['feed']['yweather_atmosphere']['pressure'] - except KeyError: + millibar = float(pressure) + inches = int(millibar / 33.7685) + except (KeyError, ValueError): return 'unknown' - millibar = float(pressure) - inches = int(millibar / 33.7685) return ('%din (%dmb)' % (inches, int(millibar))) def get_wind(parsed): try: wind_data = parsed['feed']['yweather_wind'] - except KeyError: - return 'unknown' - try: kph = float(wind_data['speed']) - except ValueError: - kph = -1 - # Incoming data isn't a number, default to zero. - # This is a dirty fix for issue #218 - speed = int(round(kph / 1.852, 0)) - degrees = int(wind_data['direction']) + speed = int(round(kph / 1.852, 0)) + degrees = int(wind_data['direction']) + except (KeyError, ValueError): + return 'unknown' + if speed < 1: description = 'Calm' elif speed < 4: