# -*- coding: UTF-8 -*- # pylint: disable=C0111,R0903 """Displays currency exchange rates. Currently, displays currency between GBP and USD/EUR only. Requires the following python packages: * requests Parameters: * currency.interval: Interval in minutes between updates, default is 1. * currency.source: Source currency (ex. 'GBP', 'EUR'). Defaults to 'auto', which infers the local one from IP address. * currency.destination: Comma-separated list of destination currencies (defaults to 'USD,EUR') * currency.sourceformat: String format for source formatting; Defaults to '{}: {}' and has two variables, the base symbol and the rate list * currency.destinationdelimiter: Delimiter used for separating individual rates (defaults to '|') Note: source and destination names right now must correspond to the names used by the API of https://markets.ft.com """ import requests try: from babel.numbers import format_currency except ImportError: format_currency = None import json import os import core.module import core.widget import core.decorators import util.format import util.location SYMBOL = {"GBP": "£", "EUR": "€", "USD": "$", "JPY": "¥", "KRW": "₩"} DEFAULT_DEST = "USD,EUR,auto" DEFAULT_SRC = "GBP" API_URL = "https://markets.ft.com/data/currencies/ajax/conversion?baseCurrency={}&comparison={}" def load_country_to_currency(): return [ {"country": "Afghanistan", "currency_code": "AFN"}, {"country": "Albania", "currency_code": "ALL"}, {"country": "Algeria", "currency_code": "DZD"}, {"country": "American Samoa", "currency_code": "USD"}, {"country": "Andorra", "currency_code": "EUR"}, {"country": "Angola", "currency_code": "AOA"}, {"country": "Anguilla", "currency_code": "XCD"}, {"country": "Antarctica", "currency_code": "XCD"}, {"country": "Antigua and Barbuda", "currency_code": "XCD"}, {"country": "Argentina", "currency_code": "ARS"}, {"country": "Armenia", "currency_code": "AMD"}, {"country": "Aruba", "currency_code": "AWG"}, {"country": "Australia", "currency_code": "AUD"}, {"country": "Austria", "currency_code": "EUR"}, {"country": "Azerbaijan", "currency_code": "AZN"}, {"country": "Bahamas", "currency_code": "BSD"}, {"country": "Bahrain", "currency_code": "BHD"}, {"country": "Bangladesh", "currency_code": "BDT"}, {"country": "Barbados", "currency_code": "BBD"}, {"country": "Belarus", "currency_code": "BYR"}, {"country": "Belgium", "currency_code": "EUR"}, {"country": "Belize", "currency_code": "BZD"}, {"country": "Benin", "currency_code": "XOF"}, {"country": "Bermuda", "currency_code": "BMD"}, {"country": "Bhutan", "currency_code": "BTN"}, {"country": "Bolivia", "currency_code": "BOB"}, {"country": "Bosnia and Herzegovina", "currency_code": "BAM"}, {"country": "Botswana", "currency_code": "BWP"}, {"country": "Bouvet Island", "currency_code": "NOK"}, {"country": "Brazil", "currency_code": "BRL"}, {"country": "British Indian Ocean Territory", "currency_code": "USD"}, {"country": "Brunei", "currency_code": "BND"}, {"country": "Bulgaria", "currency_code": "BGN"}, {"country": "Burkina Faso", "currency_code": "XOF"}, {"country": "Burundi", "currency_code": "BIF"}, {"country": "Cambodia", "currency_code": "KHR"}, {"country": "Cameroon", "currency_code": "XAF"}, {"country": "Canada", "currency_code": "CAD"}, {"country": "Cape Verde", "currency_code": "CVE"}, {"country": "Cayman Islands", "currency_code": "KYD"}, {"country": "Central African Republic", "currency_code": "XAF"}, {"country": "Chad", "currency_code": "XAF"}, {"country": "Chile", "currency_code": "CLP"}, {"country": "China", "currency_code": "CNY"}, {"country": "Christmas Island", "currency_code": "AUD"}, {"country": "Cocos (Keeling) Islands", "currency_code": "AUD"}, {"country": "Colombia", "currency_code": "COP"}, {"country": "Comoros", "currency_code": "KMF"}, {"country": "Congo", "currency_code": "XAF"}, {"country": "Cook Islands", "currency_code": "NZD"}, {"country": "Costa Rica", "currency_code": "CRC"}, {"country": "Croatia", "currency_code": "HRK"}, {"country": "Cuba", "currency_code": "CUP"}, {"country": "Cyprus", "currency_code": "EUR"}, {"country": "Czech Republic", "currency_code": "CZK"}, {"country": "Denmark", "currency_code": "DKK"}, {"country": "Djibouti", "currency_code": "DJF"}, {"country": "Dominica", "currency_code": "XCD"}, {"country": "Dominican Republic", "currency_code": "DOP"}, {"country": "East Timor", "currency_code": "USD"}, {"country": "Ecuador", "currency_code": "ECS"}, {"country": "Egypt", "currency_code": "EGP"}, {"country": "El Salvador", "currency_code": "SVC"}, {"country": "England", "currency_code": "GBP"}, {"country": "Equatorial Guinea", "currency_code": "XAF"}, {"country": "Eritrea", "currency_code": "ERN"}, {"country": "Estonia", "currency_code": "EUR"}, {"country": "Ethiopia", "currency_code": "ETB"}, {"country": "Falkland Islands", "currency_code": "FKP"}, {"country": "Faroe Islands", "currency_code": "DKK"}, {"country": "Fiji Islands", "currency_code": "FJD"}, {"country": "Finland", "currency_code": "EUR"}, {"country": "France", "currency_code": "EUR"}, {"country": "French Guiana", "currency_code": "EUR"}, {"country": "French Polynesia", "currency_code": "XPF"}, {"country": "French Southern territories", "currency_code": "EUR"}, {"country": "Gabon", "currency_code": "XAF"}, {"country": "Gambia", "currency_code": "GMD"}, {"country": "Georgia", "currency_code": "GEL"}, {"country": "Germany", "currency_code": "EUR"}, {"country": "Ghana", "currency_code": "GHS"}, {"country": "Gibraltar", "currency_code": "GIP"}, {"country": "Greece", "currency_code": "EUR"}, {"country": "Greenland", "currency_code": "DKK"}, {"country": "Grenada", "currency_code": "XCD"}, {"country": "Guadeloupe", "currency_code": "EUR"}, {"country": "Guam", "currency_code": "USD"}, {"country": "Guatemala", "currency_code": "QTQ"}, {"country": "Guinea", "currency_code": "GNF"}, {"country": "Guinea-Bissau", "currency_code": "CFA"}, {"country": "Guyana", "currency_code": "GYD"}, {"country": "Haiti", "currency_code": "HTG"}, {"country": "Heard Island and McDonald Islands", "currency_code": "AUD"}, {"country": "Holy See (Vatican City State)", "currency_code": "EUR"}, {"country": "Honduras", "currency_code": "HNL"}, {"country": "Hong Kong", "currency_code": "HKD"}, {"country": "Hungary", "currency_code": "HUF"}, {"country": "Iceland", "currency_code": "ISK"}, {"country": "India", "currency_code": "INR"}, {"country": "Indonesia", "currency_code": "IDR"}, {"country": "Iran", "currency_code": "IRR"}, {"country": "Iraq", "currency_code": "IQD"}, {"country": "Ireland", "currency_code": "EUR"}, {"country": "Israel", "currency_code": "ILS"}, {"country": "Italy", "currency_code": "EUR"}, {"country": "Ivory Coast", "currency_code": "XOF"}, {"country": "Jamaica", "currency_code": "JMD"}, {"country": "Japan", "currency_code": "JPY"}, {"country": "Jordan", "currency_code": "JOD"}, {"country": "Kazakhstan", "currency_code": "KZT"}, {"country": "Kenya", "currency_code": "KES"}, {"country": "Kiribati", "currency_code": "AUD"}, {"country": "Kuwait", "currency_code": "KWD"}, {"country": "Kyrgyzstan", "currency_code": "KGS"}, {"country": "Laos", "currency_code": "LAK"}, {"country": "Latvia", "currency_code": "LVL"}, {"country": "Lebanon", "currency_code": "LBP"}, {"country": "Lesotho", "currency_code": "LSL"}, {"country": "Liberia", "currency_code": "LRD"}, {"country": "Libyan Arab Jamahiriya", "currency_code": "LYD"}, {"country": "Liechtenstein", "currency_code": "CHF"}, {"country": "Lithuania", "currency_code": "LTL"}, {"country": "Luxembourg", "currency_code": "EUR"}, {"country": "Macao", "currency_code": "MOP"}, {"country": "North Macedonia", "currency_code": "MKD"}, {"country": "Madagascar", "currency_code": "MGF"}, {"country": "Malawi", "currency_code": "MWK"}, {"country": "Malaysia", "currency_code": "MYR"}, {"country": "Maldives", "currency_code": "MVR"}, {"country": "Mali", "currency_code": "XOF"}, {"country": "Malta", "currency_code": "EUR"}, {"country": "Marshall Islands", "currency_code": "USD"}, {"country": "Martinique", "currency_code": "EUR"}, {"country": "Mauritania", "currency_code": "MRO"}, {"country": "Mauritius", "currency_code": "MUR"}, {"country": "Mayotte", "currency_code": "EUR"}, {"country": "Mexico", "currency_code": "MXN"}, {"country": "Micronesia, Federated States of", "currency_code": "USD"}, {"country": "Moldova", "currency_code": "MDL"}, {"country": "Monaco", "currency_code": "EUR"}, {"country": "Mongolia", "currency_code": "MNT"}, {"country": "Montserrat", "currency_code": "XCD"}, {"country": "Morocco", "currency_code": "MAD"}, {"country": "Mozambique", "currency_code": "MZN"}, {"country": "Myanmar", "currency_code": "MMR"}, {"country": "Namibia", "currency_code": "NAD"}, {"country": "Nauru", "currency_code": "AUD"}, {"country": "Nepal", "currency_code": "NPR"}, {"country": "Netherlands", "currency_code": "EUR"}, {"country": "Netherlands Antilles", "currency_code": "ANG"}, {"country": "New Caledonia", "currency_code": "XPF"}, {"country": "New Zealand", "currency_code": "NZD"}, {"country": "Nicaragua", "currency_code": "NIO"}, {"country": "Niger", "currency_code": "XOF"}, {"country": "Nigeria", "currency_code": "NGN"}, {"country": "Niue", "currency_code": "NZD"}, {"country": "Norfolk Island", "currency_code": "AUD"}, {"country": "North Korea", "currency_code": "KPW"}, {"country": "Northern Ireland", "currency_code": "GBP"}, {"country": "Northern Mariana Islands", "currency_code": "USD"}, {"country": "Norway", "currency_code": "NOK"}, {"country": "Oman", "currency_code": "OMR"}, {"country": "Pakistan", "currency_code": "PKR"}, {"country": "Palau", "currency_code": "USD"}, {"country": "Palestine", "currency_code": null}, {"country": "Panama", "currency_code": "PAB"}, {"country": "Papua New Guinea", "currency_code": "PGK"}, {"country": "Paraguay", "currency_code": "PYG"}, {"country": "Peru", "currency_code": "PEN"}, {"country": "Philippines", "currency_code": "PHP"}, {"country": "Pitcairn", "currency_code": "NZD"}, {"country": "Poland", "currency_code": "PLN"}, {"country": "Portugal", "currency_code": "EUR"}, {"country": "Puerto Rico", "currency_code": "USD"}, {"country": "Qatar", "currency_code": "QAR"}, {"country": "Reunion", "currency_code": "EUR"}, {"country": "Romania", "currency_code": "RON"}, {"country": "Russian Federation", "currency_code": "RUB"}, {"country": "Rwanda", "currency_code": "RWF"}, {"country": "Saint Helena", "currency_code": "SHP"}, {"country": "Saint Kitts and Nevis", "currency_code": "XCD"}, {"country": "Saint Lucia", "currency_code": "XCD"}, {"country": "Saint Pierre and Miquelon", "currency_code": "EUR"}, {"country": "Saint Vincent and the Grenadines", "currency_code": "XCD"}, {"country": "Samoa", "currency_code": "WST"}, {"country": "San Marino", "currency_code": "EUR"}, {"country": "Sao Tome and Principe", "currency_code": "STD"}, {"country": "Saudi Arabia", "currency_code": "SAR"}, {"country": "Scotland", "currency_code": "GBP"}, {"country": "Senegal", "currency_code": "XOF"}, {"country": "Seychelles", "currency_code": "SCR"}, {"country": "Sierra Leone", "currency_code": "SLL"}, {"country": "Singapore", "currency_code": "SGD"}, {"country": "Slovakia", "currency_code": "EUR"}, {"country": "Slovenia", "currency_code": "EUR"}, {"country": "Solomon Islands", "currency_code": "SBD"}, {"country": "Somalia", "currency_code": "SOS"}, {"country": "South Africa", "currency_code": "ZAR"}, { "country": "South Georgia and the South Sandwich Islands", "currency_code": "GBP", }, {"country": "South Korea", "currency_code": "KRW"}, {"country": "South Sudan", "currency_code": "SSP"}, {"country": "Spain", "currency_code": "EUR"}, {"country": "SriLanka", "currency_code": "LKR"}, {"country": "Sudan", "currency_code": "SDG"}, {"country": "Suriname", "currency_code": "SRD"}, {"country": "Svalbard and Jan Mayen", "currency_code": "NOK"}, {"country": "Swaziland", "currency_code": "SZL"}, {"country": "Sweden", "currency_code": "SEK"}, {"country": "Switzerland", "currency_code": "CHF"}, {"country": "Syria", "currency_code": "SYP"}, {"country": "Tajikistan", "currency_code": "TJS"}, {"country": "Tanzania", "currency_code": "TZS"}, {"country": "Thailand", "currency_code": "THB"}, {"country": "The Democratic Republic of Congo", "currency_code": "CDF"}, {"country": "Togo", "currency_code": "XOF"}, {"country": "Tokelau", "currency_code": "NZD"}, {"country": "Tonga", "currency_code": "TOP"}, {"country": "Trinidad and Tobago", "currency_code": "TTD"}, {"country": "Tunisia", "currency_code": "TND"}, {"country": "Turkey", "currency_code": "TRY"}, {"country": "Turkmenistan", "currency_code": "TMT"}, {"country": "Turks and Caicos Islands", "currency_code": "USD"}, {"country": "Tuvalu", "currency_code": "AUD"}, {"country": "Uganda", "currency_code": "UGX"}, {"country": "Ukraine", "currency_code": "UAH"}, {"country": "United Arab Emirates", "currency_code": "AED"}, {"country": "United Kingdom", "currency_code": "GBP"}, {"country": "United States", "currency_code": "USD"}, {"country": "United States Minor Outlying Islands", "currency_code": "USD"}, {"country": "Uruguay", "currency_code": "UYU"}, {"country": "Uzbekistan", "currency_code": "UZS"}, {"country": "Vanuatu", "currency_code": "VUV"}, {"country": "Venezuela", "currency_code": "VEF"}, {"country": "Vietnam", "currency_code": "VND"}, {"country": "Virgin Islands, British", "currency_code": "USD"}, {"country": "Virgin Islands, U.S.", "currency_code": "USD"}, {"country": "Wales", "currency_code": "GBP"}, {"country": "Wallis and Futuna", "currency_code": "XPF"}, {"country": "Western Sahara", "currency_code": "MAD"}, {"country": "Yemen", "currency_code": "YER"}, {"country": "Yugoslavia", "currency_code": null}, {"country": "Zambia", "currency_code": "ZMW"}, {"country": "Zimbabwe", "currency_code": "ZWD"}, ] class Module(core.module.Module): @core.decorators.every(minutes=5) def __init__(self, config, theme): super().__init__(config, theme, core.widget.Widget(self.price)) self.__data = [] src = self.parameter("source", DEFAULT_SRC) if src == "auto": self.__base = self.find_local_currency() else: self.__base = src self.__symbols = [] for d in util.format.aslist(self.parameter("destination", DEFAULT_DEST)): if d == "auto": new = self.find_local_currency() else: new = d if new != self.__base: self.__symbols.append(new) def price(self, widget): if len(self.__data) == 0: return "?" rates = [] for sym, rate in self.__data: rate_float = float(rate.replace(",", "")) if format_currency: rates.append(format_currency(rate_float, sym)) else: rate = self.fmt_rate(rate) rates.append("{}{}".format(rate, SYMBOL[sym] if sym in SYMBOL else sym)) basefmt = "{}".format(self.parameter("sourceformat", "{}={}")) ratefmt = "{}".format(self.parameter("destinationdelimiter", "=")) if format_currency: base_val = format_currency(1, self.__base) else: base_val = "1{}".format( SYMBOL[self.__base] if self.__base in SYMBOL else self.__base ) return basefmt.format(base_val, ratefmt.join(rates)) def update(self): self.__data = [] for symbol in self.__symbols: url = API_URL.format(self.__base, symbol) try: response = requests.get(url).json() self.__data.append((symbol, response["data"]["exchangeRate"])) except Exception: pass def find_local_currency(self): """Use geolocation lookup to find local currency""" try: country = util.location.country() currency_map = load_country_to_currency() return currency_map.get(country, DEFAULT_SRC) except: return DEFAULT_SRC def fmt_rate(self, rate): float_rate = float(rate.replace(",", "")) if not 0.01 < float_rate < 100: ret = rate else: ret = "%.3g" % float_rate return ret # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4