mirror of
https://github.com/spiral-project/ihatemoney.git
synced 2025-04-29 01:42:37 +02:00

* hotfix: hardcode list of currencies to workaround failing API calls See https://github.com/spiral-project/ihatemoney/issues/1232 for a discussion on currencies * Temporarily disable some currency operations to prevent crashes Here is what is disabled: - setting or changing the default currency on an existing project - adding or editing a bill with a currency that differs from the default currency of the project --------- Co-authored-by: Baptiste Jonglez <git@bitsofnetworks.org>
228 lines
4.8 KiB
Python
228 lines
4.8 KiB
Python
import traceback
|
|
import warnings
|
|
|
|
from cachetools import TTLCache, cached
|
|
import requests
|
|
|
|
|
|
class Singleton(type):
|
|
_instances = {}
|
|
|
|
def __call__(cls, *args, **kwargs):
|
|
if cls not in cls._instances:
|
|
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
|
|
return cls._instances[cls]
|
|
|
|
|
|
class CurrencyConverter(object, metaclass=Singleton):
|
|
# Get exchange rates
|
|
no_currency = "XXX"
|
|
api_url = "https://api.exchangerate.host/latest?base=USD"
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@cached(cache=TTLCache(maxsize=1, ttl=86400))
|
|
def get_rates(self):
|
|
try:
|
|
rates = requests.get(self.api_url).json()["rates"]
|
|
except Exception:
|
|
warnings.warn(
|
|
f"Call to {self.api_url} failed: {traceback.format_exc(limit=0).strip()}"
|
|
)
|
|
# In case of any exception, let's have an empty value
|
|
rates = {}
|
|
rates[self.no_currency] = 1.0
|
|
return rates
|
|
|
|
def get_currencies(self, with_no_currency=True):
|
|
currencies = [
|
|
"AED",
|
|
"AFN",
|
|
"ALL",
|
|
"AMD",
|
|
"ANG",
|
|
"AOA",
|
|
"ARS",
|
|
"AUD",
|
|
"AWG",
|
|
"AZN",
|
|
"BAM",
|
|
"BBD",
|
|
"BDT",
|
|
"BGN",
|
|
"BHD",
|
|
"BIF",
|
|
"BMD",
|
|
"BND",
|
|
"BOB",
|
|
"BRL",
|
|
"BSD",
|
|
"BTC",
|
|
"BTN",
|
|
"BWP",
|
|
"BYN",
|
|
"BZD",
|
|
"CAD",
|
|
"CDF",
|
|
"CHF",
|
|
"CLF",
|
|
"CLP",
|
|
"CNH",
|
|
"CNY",
|
|
"COP",
|
|
"CRC",
|
|
"CUC",
|
|
"CUP",
|
|
"CVE",
|
|
"CZK",
|
|
"DJF",
|
|
"DKK",
|
|
"DOP",
|
|
"DZD",
|
|
"EGP",
|
|
"ERN",
|
|
"ETB",
|
|
"EUR",
|
|
"FJD",
|
|
"FKP",
|
|
"GBP",
|
|
"GEL",
|
|
"GGP",
|
|
"GHS",
|
|
"GIP",
|
|
"GMD",
|
|
"GNF",
|
|
"GTQ",
|
|
"GYD",
|
|
"HKD",
|
|
"HNL",
|
|
"HRK",
|
|
"HTG",
|
|
"HUF",
|
|
"IDR",
|
|
"ILS",
|
|
"IMP",
|
|
"INR",
|
|
"IQD",
|
|
"IRR",
|
|
"ISK",
|
|
"JEP",
|
|
"JMD",
|
|
"JOD",
|
|
"JPY",
|
|
"KES",
|
|
"KGS",
|
|
"KHR",
|
|
"KMF",
|
|
"KPW",
|
|
"KRW",
|
|
"KWD",
|
|
"KYD",
|
|
"KZT",
|
|
"LAK",
|
|
"LBP",
|
|
"LKR",
|
|
"LRD",
|
|
"LSL",
|
|
"LYD",
|
|
"MAD",
|
|
"MDL",
|
|
"MGA",
|
|
"MKD",
|
|
"MMK",
|
|
"MNT",
|
|
"MOP",
|
|
"MRU",
|
|
"MUR",
|
|
"MVR",
|
|
"MWK",
|
|
"MXN",
|
|
"MYR",
|
|
"MZN",
|
|
"NAD",
|
|
"NGN",
|
|
"NIO",
|
|
"NOK",
|
|
"NPR",
|
|
"NZD",
|
|
"OMR",
|
|
"PAB",
|
|
"PEN",
|
|
"PGK",
|
|
"PHP",
|
|
"PKR",
|
|
"PLN",
|
|
"PYG",
|
|
"QAR",
|
|
"RON",
|
|
"RSD",
|
|
"RUB",
|
|
"RWF",
|
|
"SAR",
|
|
"SBD",
|
|
"SCR",
|
|
"SDG",
|
|
"SEK",
|
|
"SGD",
|
|
"SHP",
|
|
"SLL",
|
|
"SOS",
|
|
"SRD",
|
|
"SSP",
|
|
"STD",
|
|
"STN",
|
|
"SVC",
|
|
"SYP",
|
|
"SZL",
|
|
"THB",
|
|
"TJS",
|
|
"TMT",
|
|
"TND",
|
|
"TOP",
|
|
"TRY",
|
|
"TTD",
|
|
"TWD",
|
|
"TZS",
|
|
"UAH",
|
|
"UGX",
|
|
"USD",
|
|
"UYU",
|
|
"UZS",
|
|
"VEF",
|
|
"VES",
|
|
"VND",
|
|
"VUV",
|
|
"WST",
|
|
"XAF",
|
|
"XAG",
|
|
"XAU",
|
|
"XCD",
|
|
"XDR",
|
|
"XOF",
|
|
"XPD",
|
|
"XPF",
|
|
"XPT",
|
|
"YER",
|
|
"ZAR",
|
|
"ZMW",
|
|
"ZWL",
|
|
]
|
|
if with_no_currency:
|
|
currencies.append(self.no_currency)
|
|
return currencies
|
|
|
|
def exchange_currency(self, amount, source_currency, dest_currency):
|
|
if (
|
|
source_currency == dest_currency
|
|
or source_currency == self.no_currency
|
|
or dest_currency == self.no_currency
|
|
):
|
|
return amount
|
|
|
|
rates = self.get_rates()
|
|
source_rate = rates[source_currency]
|
|
dest_rate = rates[dest_currency]
|
|
new_amount = (float(amount) / source_rate) * dest_rate
|
|
# round to two digits because we are dealing with money
|
|
return round(new_amount, 2)
|