import os import time import datetime import requests from dotenv import load_dotenv from cachier import cachier import logging import gradio as gr from babel import numbers as babel_numbers logging.getLogger("urllib3.connectionpool").setLevel(logging.WARNING) load_dotenv() API_KEY = os.getenv("EXCHANGE_API_KEY") VALID_CURRENCIES = [ "AED", "AFN", "ALL", "AMD", "ANG", "AOA", "ARS", "AUD", "AWG", "AZN", "BAM", "BBD", "BDT", "BGN", "BHD", "BIF", "BMD", "BND", "BOB", "BRL", "BSD", "BTN", "BWP", "BYN", "BZD", "CAD", "CDF", "CHF", "CLF", "CLP", "CNH", "CNY", "COP", "CRC", "CUP", "CVE", "CZK", "DJF", "DKK", "DOP", "DZD", "EGP", "ERN", "ETB", "EUR", "FJD", "FKP", "FOK", "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", "KID", "KMF", "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", "SLE", "SLL", "SOS", "SRD", "SSP", "STN", "SYP", "SZL", "THB", "TJS", "TMT", "TND", "TOP", "TRY", "TTD", "TVD", "TWD", "TZS", "UAH", "UGX", "USD", "UYU", "UZS", "VES", "VND", "VUV", "WST", "XAF", "XCD", "XCG", "XDR", "XOF", "XPF", "YER", "ZAR", "ZMW", "ZWG", "ZWL" ] currency_choices = [ (f"{babel_numbers.get_currency_name(code, locale='en_US')} ({code})", code) for code in VALID_CURRENCIES ] SEPARATOR = "=" * 50 logging.basicConfig(format="%(message)s", level=logging.DEBUG) if not API_KEY: raise ValueError("EXCHANGE_API_KEY environment variable not set!") BASE_URL = f"https://v6.exchangerate-api.com/v6/{API_KEY}/latest/" @cachier(stale_after=datetime.timedelta(days=1)) def get_exchange_data(base_currency): url = BASE_URL + base_currency try: response = requests.get(url, timeout=10) if response.status_code == 200: data = response.json() if data.get("result") == "success": logging.info("Fresh data fetched from API") data["_fetched_at"] = time.time() return data else: logging.error(f"API Error: {data.get('error-type')}") else: logging.error(f"HTTP Error: Status Code {response.status_code}") except requests.RequestException as e: logging.error(f"Network Error: {e}") return None def get_valid_currency(prompt): while True: user_input = input(prompt).upper().strip() if not user_input.isalpha() or len(user_input) != 3: logging.error("Error: Currency code must be 3 letters (e.g., USD).") continue if user_input not in VALID_CURRENCIES: logging.error( f"Warning: '{user_input}' might not be supported or is invalid." ) continue return user_input def get_valid_amount(currency_name): while True: user_input = input(f"Enter {currency_name} amount: ").strip() try: val = float(user_input) if val < 0: logging.error("Error: Amount cannot be negative.") continue return val except ValueError: logging.error("Error: Please enter a valid numeric amount.") def convert_currency(base_currency, target_currency, amount): data = get_exchange_data(base_currency) if not data: return None rates = data.get("conversion_rates", {}) rate = rates.get(target_currency) if not rate: logging.error(f"Currency {target_currency} not found") return None exchange_amount = amount * rate fetch_time = data.get("_fetched_at", 0) is_cached = (time.time() - fetch_time) > 2 return { "amount": exchange_amount, "rate": rate, "timestamp": data.get("time_last_update_utc"), "from_cache": is_cached, } def get_currency_symbol_name(currency): name = babel_numbers.get_currency_name(currency, locale="en_US") sym = babel_numbers.get_currency_symbol(currency, locale="en_US") return sym, name def currency_covertor(base_currency, target_currency, amount): result = convert_currency(base_currency, target_currency, amount) b_sym, b_name = get_currency_symbol_name(base_currency) t_sym, t_name = get_currency_symbol_name(target_currency) if result: base_output = f"Currency: {b_name}\n" f"Amount: {b_sym} {amount:,.2f}" if result: target_output = ( f"Currency: {t_name}\n" f"Amount: {t_sym} {result['amount']:,.2f}" ) data = get_exchange_data(base_currency) rates = data.get("conversion_rates", {}) exchange_rate = f"1 {b_name}({base_currency}) is {rates.get(target_currency)} {t_name}({target_currency})" return base_output, target_output, exchange_rate with gr.Blocks(title="Day12-Currency-Converter(using API)") as demo: gr.Markdown("# 💱 Currency-Converter") gr.Markdown("### Select currency types and enter your amount") with gr.Column(): with gr.Row(): base_currency = gr.Dropdown( choices=currency_choices, label="Base Currency", interactive=True, value="USD", ) target_currency = gr.Dropdown( choices=currency_choices, label="Base Currency", interactive=True, value="INR", ) amount = gr.Number( label="Enter amount for your selected base currency", value=100 ) convert_button = gr.Button("Convert", interactive=True, variant="primary") with gr.Row(): base_output = gr.Textbox(label="Base Currency Details") target_output = gr.Textbox(label="Target Currency Details") exchange_rate = gr.Textbox(label="Exchange Rate Details") convert_button.click( fn=currency_covertor, inputs=[base_currency, target_currency, amount], outputs=[base_output, target_output, exchange_rate], ) if __name__ == "__main__": demo.launch()