Skip to content

Commit

Permalink
currency: Improved exception handling
Browse files Browse the repository at this point in the history
Co-authored-by: dgw <dgw@technobabbl.es>
Co-authored-by: Humorous Baby <humorbaby@humorbaby.net>
  • Loading branch information
3 people committed Apr 29, 2019
1 parent c7573f0 commit 6cc8d47
Showing 1 changed file with 55 additions and 34 deletions.
89 changes: 55 additions & 34 deletions sopel/modules/currency.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,45 @@

class CurrencySection(StaticSection):
fixer_io_key = ValidatedAttribute('fixer_io_key', default=None)
"""Optional API key for Fixer.io (increases currency support)"""
auto_convert = ValidatedAttribute('auto_convert', parse=bool, default=False)
"""Whether to convert currencies without an explicit command"""


def configure(config):
"""
| name | example | purpose |
| ---- | ------- | ------- |
| auto\\_convert | False | Whether to convert currencies without an explicit command |
| fixer\\_io\\_key | 0123456789abcdef0123456789abcdef | Optional API key for Fixer.io (increases currency support) |
"""
config.define_section('currency', CurrencySection, validate=False)
config.currency.configure_setting('fixer_io_key', 'Optional API key for Fixer.io (leave blank to use exchangeratesapi.io):')
config.currency.configure_setting('auto_convert', 'Automatically respond to currency conversion lines?')
config.currency.configure_setting('auto_convert', 'Whether to convert currencies without an explicit command?')


def setup(bot):
bot.config.define_section('currency', CurrencySection)


class FixerError(Exception):
"""A Fixer.io API Error Exception"""
def __init__(self, status):
super(FixerError, self).__init__("FixerError: {}".format(status))


class UnsupportedCurrencyError(Exception):
"""A currency is currently not supported by the API"""
def __init__(self, currency):
super(UnsupportedCurrencyError, self).__init__(currency)


def update_rates(bot):
global rates_fiat_json, rates_btc_json, rates_updated

# If we have data that are less than 24h old, return
if 'date' in rates_fiat_json:
if time.time() - rates_updated < 24 * 60 * 60:
return
# If we have data that is less than 24h old, return
if time.time() - rates_updated < 24 * 60 * 60:
return

# Update crypto rates
response = requests.get(CRYPTO_URL)
Expand All @@ -69,8 +88,7 @@ def update_rates(bot):
if bot.config.currency.fixer_io_key is not None:
response = requests.get(FIXER_URL.format(bot.config.currency.fixer_io_key))
if not response.json()['success']:
LOGGER.error(str(response.json()['error']))
return bot.reply('Sorry, something went wrong')
raise FixerError('Fixer.io request failed with error: {}'.format(response.json()['error']))
else:
response = requests.get(FIAT_URL)

Expand All @@ -86,7 +104,7 @@ def btc_rate(code, reverse=False):
if search in rates_btc_json:
rate = rates_btc_json[search]['averages']['day']
else:
return UNSUPPORTED_CURRENCY.format(code)
raise UnsupportedCurrencyError(code)

if reverse:
return 1 / rate
Expand All @@ -98,21 +116,16 @@ def get_rate(of, to):
of = of.upper()
to = to.upper()

if of == 'BTC' or to == 'BTC':
if of == 'BTC':
code = to
reverse = False
else:
code = of
reverse = True

return btc_rate(code, reverse)
if of == 'BTC':
return btc_rate(to, False)
elif to == 'BTC':
return btc_rate(of, True)

if of not in rates_fiat_json['rates']:
return UNSUPPORTED_CURRENCY.format(of)
raise UnsupportedCurrencyError(of)

if to not in rates_fiat_json['rates']:
return UNSUPPORTED_CURRENCY.format(to)
raise UnsupportedCurrencyError(to)

return (1 / rates_fiat_json['rates'][of]) * rates_fiat_json['rates'][to]

Expand All @@ -125,14 +138,18 @@ def exchange(bot, match):

try:
update_rates(bot) # Try and update rates. Rate-limiting is done in update_rates()
except requests.exceptions.RequestException as e:
except requests.exceptions.RequestException as err:
bot.reply("Something went wrong while I was getting the exchange rate.")
LOGGER.error("Error in GET request: {}".format(e))
LOGGER.error("Error in GET request: {}".format(err))
return NOLIMIT
except ValueError:
bot.reply("Error: Got malformed data.")
LOGGER.error("Invalid json on update_rates")
return NOLIMIT
except FixerError as err:
bot.reply('Sorry, something went wrong with Fixer')
LOGGER.error(err)
return NOLIMIT

query = match.string

Expand All @@ -151,11 +168,24 @@ def exchange(bot, match):
except OverflowError:
bot.reply("Sorry, input amount was out of range.")

if not amount:
bot.reply("Zero is zero, no matter what country you're in.")
return NOLIMIT

out_string = '{} {} is'.format(amount, of.upper())

for to in others:
try:
out_string = build_reply(bot, amount, of.upper(), to.upper(), out_string)
out_string = build_reply(amount, of.upper(), to.upper(), out_string)
except ValueError:
LOGGER.error("Raw rate wasn't a float")
return NOLIMIT
except KeyError as err:
bot.reply("Error: Invalid rates")
LOGGER.error("No key: {} in json".format(err))
return NOLIMIT
except UnsupportedCurrencyError as cur:
bot.reply(UNSUPPORTED_CURRENCY.format(cur))
return NOLIMIT

bot.reply(out_string[0:-1])
Expand Down Expand Up @@ -183,18 +213,9 @@ def exchange_re(bot, trigger):
exchange(bot, match)


def build_reply(bot, amount, of, to, out_string):
if not amount:
bot.reply("Zero is zero, no matter what country you're in.")

rate_raw = ''
try:
rate_raw = get_rate(of, to)
rate = float(rate_raw)
except ValueError:
bot.reply(rate_raw)
raise

def build_reply(amount, of, to, out_string):
rate_raw = get_rate(of, to)
rate = float(rate_raw)
result = float(rate * amount)

if to == 'BTC':
Expand Down

0 comments on commit 6cc8d47

Please sign in to comment.