From cca512c34785e26a26b87ad50e142945063957f6 Mon Sep 17 00:00:00 2001 From: Y4shu Date: Sun, 15 Jun 2025 22:22:54 +0530 Subject: [PATCH 1/3] Added the API key free Currency Converter --- .../API-key_free_Currency_Converter/README.md | 98 ++++++++++++ .../assets/Dark Mode.png | Bin 0 -> 12137 bytes .../assets/Light Mode.png | Bin 0 -> 11939 bytes .../currency_converter.py | 140 ++++++++++++++++++ 4 files changed, 238 insertions(+) create mode 100644 Beginner_Projects/API-key_free_Currency_Converter/README.md create mode 100644 Beginner_Projects/API-key_free_Currency_Converter/assets/Dark Mode.png create mode 100644 Beginner_Projects/API-key_free_Currency_Converter/assets/Light Mode.png create mode 100644 Beginner_Projects/API-key_free_Currency_Converter/currency_converter.py diff --git a/Beginner_Projects/API-key_free_Currency_Converter/README.md b/Beginner_Projects/API-key_free_Currency_Converter/README.md new file mode 100644 index 0000000000..d589f51a1c --- /dev/null +++ b/Beginner_Projects/API-key_free_Currency_Converter/README.md @@ -0,0 +1,98 @@ +# 💱 Currency Converter GUI (Python + Tkinter) + +A simple, elegant desktop application that converts currencies using real-time exchange rates. Built with Python and Tkinter, and includes light/dark theme toggle support! 🌗 + +--- + +## 📚 Table of Contents + +- [🚀 Features](#-features) +- [🖼️ App Preview](#️-app-preview) +- [⚙️ How to Run](#️-how-to-run) +- [🔐 API Access Notes](#-api-access-notes) +- [👤 Signature](#-project-admin) + +--- + +## 🚀 Features + +- 💵 Convert any currency to another using **live exchange rates** +- 🌗 Toggle between **light and dark themes** +- ✅ Validates user input with helpful error messages +- 💡 Beginner-friendly GUI design using Tkinter +- 📶 No API key required — uses [Frankfurter API](https://frankfurter.app/) + +--- + +## 🖼️ App Preview + +> Example: +> ![screenshot](assets/Light Mode.png) +> ![screenshot](assets/Dark Mode.png) + +--- + +## ⚙️ How to Run + +1. **Clone this repo** + ```bash + git clone https://github.com/UTSAV26/PyVerse.git + cd PyVerse/Beginner_Projects/API-key_free_Currency_Converter + ``` + +2. **Install dependencies** + -Make sure Python 3.6+ is Installed + -(Only `requests` is needed) + ```bash + pip install requests + ``` + -Tkinter is usually pre-installed with Python. If not: + -On Windows: Install Python from the official website + -On Linux: sudo apt-get install python3-tk + -On Mac: Already included with Python + +3. **Run the application** + ```bash + currency_converter.py + ``` + +--- + +## 🔐 API Access Notes + +This app currently uses the **[Frankfurter API](https://www.frankfurter.app/)**, which is free and does **not** require an API key. +If this changes in the future, follow these steps: + +1. **Check the official docs:** [frankfurter.app/docs](https://www.frankfurter.app/docs) +2. **If an API key is required**: + - Register for one on their website + - Update the API call in your code: + ```python + url = f"https://api.frankfurter.app/latest?amount={amount}&from={from_curr}&to={to_curr}&apikey=YOUR_API_KEY" + ``` + - For security: + - Store the key in a `.env` file using the `python-dotenv` package + - Never commit API keys to GitHub + +3. **Alternative APIs you can switch to**: + - [CurrencyFreaks](https://currencyfreaks.com/) + - [Open Exchange Rates](https://openexchangerates.org/) + +--- + +### Ways to Contribute: +- 🐛 Report issues or bugs +- 🎨 Improve the UI or theme +- 🌍 Add localization/multi-language support + +Fork the repo, make your changes, and open a PR! 💖 + +--- + +## 👤 Signature: + +> **Yashasvi Jain** +> Github: https://github.com/Y4shu +> LinkedIn: https://www.linkedin.com/in/yashasvi-jain-44a553322/ + +--- diff --git a/Beginner_Projects/API-key_free_Currency_Converter/assets/Dark Mode.png b/Beginner_Projects/API-key_free_Currency_Converter/assets/Dark Mode.png new file mode 100644 index 0000000000000000000000000000000000000000..247258a0a8895adb6572053a4bb79c175d42a80a GIT binary patch literal 12137 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 C4gCWE literal 0 HcmV?d00001 diff --git a/Beginner_Projects/API-key_free_Currency_Converter/assets/Light Mode.png b/Beginner_Projects/API-key_free_Currency_Converter/assets/Light Mode.png new file mode 100644 index 0000000000000000000000000000000000000000..a5bae29beaf6ea261f298404f23bebf0064f2747 GIT binary patch literal 11939 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 literal 0 HcmV?d00001 diff --git a/Beginner_Projects/API-key_free_Currency_Converter/currency_converter.py b/Beginner_Projects/API-key_free_Currency_Converter/currency_converter.py new file mode 100644 index 0000000000..999f425c12 --- /dev/null +++ b/Beginner_Projects/API-key_free_Currency_Converter/currency_converter.py @@ -0,0 +1,140 @@ +import tkinter as tk +import requests # type: ignore +from tkinter import messagebox + +#keeping the intial theme as light +is_dark_mode = False + +#the different themes: +Themes = { + "light":{ + "background_color": "#E0F7FA", + "foreground_color": "#333333", + "entry_bg": "#F0F0F0", + "button_background": "#4CAF50", + "button_forrground": "#F0F0F0" + }, + "dark":{ + "background_color": "#2C2C2C", + "foreground_color": "#EEEEEE", + "entry_bg": "#292929", + "button_background": "#FFB300", + "button_forrground": "#F0F7FA" + } +} + +#window components setting +root = tk.Tk() +root.title("Currency Converter") +root.geometry("360x380") +root.resizable(False, False) + +FONT_LABEL = ("Helvetica", 10, "bold") +FONT_ENTRY = ("Helvetica", 11) +FONT_RESULT = ("Helvetica", 12, "bold") + +#func to apply theme +def apply_theme(theme_name): + theme = Themes[theme_name] + root.configure(bg=theme["background_color"]) + for widget in root.winfo_children(): + cls = widget.__class__.__name__ + if cls == "Entry": + widget.configure(bg=theme["entry_bg"], fg=theme["foreground_color"]) + elif cls == "Button": + if widget['text'] == "Switch Theme": + widget.configure(bg="#888", fg="#F0F0F0") + else: + widget.configure(bg=theme["button_background"], fg=theme["button_forrground"]) + elif cls == "Label": + widget.configure(bg=theme["background_color"], fg=theme["foreground_color"]) + +#toggle func +def toggle_theme(): + global is_dark_mode + is_dark_mode = not is_dark_mode + theme = "dark" if is_dark_mode else "light" + apply_theme(theme) + +#conversion logic +def convert_currency(): + #definig them + from_curr = entry_from.get().upper().strip() + to_curr = entry_to.get().upper().strip() + amount = entry_amount.get().strip() + + if from_curr in ["", "eg: USD"] or to_curr in ["", "eg: INR"] or amount in ["", "eg: 250.00"]: + error_label.config(text="Please fill all fields with valid values.") + return + + try: + amount = float(amount) + except ValueError: + error_label.config(text="Invalid amount. Please enter a valid number.") + return + + #api url + url = f"https://api.frankfurter.app/latest?amount={amount}&from={from_curr}&to={to_curr}" + + try: + response = requests.get(url) + data = response.json() + + print(data) + + converted = data["rates"].get(to_curr) + if converted: + result_label.config(text=f"{amount} {from_curr} = {round(converted, 2)} {to_curr}") + error_label.config(text="") + else: + error_label.config(text="Conversion failed. Check currency codes.") + except Exception as e: + error_label.config(text="An error occurred. Check your internet connection and try again.") + + +#label+entry func +def labeled_entry(labe_text, placeholder): + label = tk.Label(root, text=labe_text, font=FONT_LABEL) + label.pack(pady=(10,2)) + entry = tk.Entry(root, font=FONT_ENTRY, width=30, bd=2,relief="groove",fg='gray') + entry.insert(0, placeholder) + + def on_focus_in(event): + if entry.get() == placeholder: + entry.delete(0, tk.END) + entry.config(fg='black') + + def on_focus_out(event): + if not entry.get(): + entry.insert(0, placeholder) + entry.config(fg='gray') + + entry.bind("", on_focus_in) + entry.bind("", on_focus_out) + entry.pack() + return entry + +#Input fields: +entry_from = labeled_entry("From Currency Code (3 letters):", "eg: USD") +entry_to = labeled_entry("To Currency Code (3 letters):", "eg: INR") +entry_amount = labeled_entry("Amount:", "e.g. 250.00") + +#convrtion button +convert_button = tk.Button(root, text="Convert", command=convert_currency, font=FONT_LABEL, width=15) +convert_button.pack(pady=15) + +#result label: +result_label = tk.Label(root, text="", font=FONT_RESULT) +result_label.pack(pady=10) + +#error label: +error_label = tk.Label(root, text="", fg="red", font=("Helvetica", 10, "italic")) +error_label.pack(pady=(5, 0)) + +#toggling button +toggle_button = tk.Button(root, text="Toggle Theme", command=toggle_theme, font=("Helvetica", 9, "bold")) +toggle_button.pack(pady=5) + +apply_theme("light") + +root.mainloop() From dd4f570750be153866744c1038eed00762117e1c Mon Sep 17 00:00:00 2001 From: Y4shu Date: Sun, 15 Jun 2025 22:33:56 +0530 Subject: [PATCH 2/3] Fixed the README.md image display --- .../API-key_free_Currency_Converter/README.md | 4 ++-- .../assets/{Dark Mode.png => dark_mode.png} | Bin .../assets/{Light Mode.png => light_mode.png} | Bin 3 files changed, 2 insertions(+), 2 deletions(-) rename Beginner_Projects/API-key_free_Currency_Converter/assets/{Dark Mode.png => dark_mode.png} (100%) rename Beginner_Projects/API-key_free_Currency_Converter/assets/{Light Mode.png => light_mode.png} (100%) diff --git a/Beginner_Projects/API-key_free_Currency_Converter/README.md b/Beginner_Projects/API-key_free_Currency_Converter/README.md index d589f51a1c..c049e52396 100644 --- a/Beginner_Projects/API-key_free_Currency_Converter/README.md +++ b/Beginner_Projects/API-key_free_Currency_Converter/README.md @@ -27,8 +27,8 @@ A simple, elegant desktop application that converts currencies using real-time e ## 🖼️ App Preview > Example: -> ![screenshot](assets/Light Mode.png) -> ![screenshot](assets/Dark Mode.png) +> ![screenshot](assets/light_mode.png) +> ![screenshot](assets/dark_mode.png) --- diff --git a/Beginner_Projects/API-key_free_Currency_Converter/assets/Dark Mode.png b/Beginner_Projects/API-key_free_Currency_Converter/assets/dark_mode.png similarity index 100% rename from Beginner_Projects/API-key_free_Currency_Converter/assets/Dark Mode.png rename to Beginner_Projects/API-key_free_Currency_Converter/assets/dark_mode.png diff --git a/Beginner_Projects/API-key_free_Currency_Converter/assets/Light Mode.png b/Beginner_Projects/API-key_free_Currency_Converter/assets/light_mode.png similarity index 100% rename from Beginner_Projects/API-key_free_Currency_Converter/assets/Light Mode.png rename to Beginner_Projects/API-key_free_Currency_Converter/assets/light_mode.png From 9d810054d528f0f7bfc6d41e13dcd76ba0586505 Mon Sep 17 00:00:00 2001 From: Y4shu Date: Wed, 2 Jul 2025 00:33:19 +0530 Subject: [PATCH 3/3] Made changes acc to CodeRabbit --- .gitignore | 9 ++- .../.env.example | 0 .../README.md | 50 +++++++----- .../assets/dark_mode.png | Bin .../assets/light_mode.png | Bin .../currency_converter.py | 73 +++++++++++++----- .../run_converter.bat | 2 + 7 files changed, 93 insertions(+), 41 deletions(-) create mode 100644 Beginner_Projects/Currency-Converter-with toggletheme/.env.example rename Beginner_Projects/{API-key_free_Currency_Converter => Currency-Converter-with toggletheme}/README.md (60%) rename Beginner_Projects/{API-key_free_Currency_Converter => Currency-Converter-with toggletheme}/assets/dark_mode.png (100%) rename Beginner_Projects/{API-key_free_Currency_Converter => Currency-Converter-with toggletheme}/assets/light_mode.png (100%) rename Beginner_Projects/{API-key_free_Currency_Converter => Currency-Converter-with toggletheme}/currency_converter.py (53%) create mode 100644 Beginner_Projects/Currency-Converter-with toggletheme/run_converter.bat diff --git a/.gitignore b/.gitignore index fbd7baccd7..af8bd227a5 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,11 @@ aiml kaggle.json # Ignore macOS system files -.DS_Store \ No newline at end of file +.DS_Store + +#For the Currency converter project of SSoC S4 +Beginner_Projects/Currency-Converter-with toggletheme/.env +Beginner_Projects/Currency-Converter-with toggletheme/venv/ +#(also some general python ignorances) +__pycache__/ +*.pyc \ No newline at end of file diff --git a/Beginner_Projects/Currency-Converter-with toggletheme/.env.example b/Beginner_Projects/Currency-Converter-with toggletheme/.env.example new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Beginner_Projects/API-key_free_Currency_Converter/README.md b/Beginner_Projects/Currency-Converter-with toggletheme/README.md similarity index 60% rename from Beginner_Projects/API-key_free_Currency_Converter/README.md rename to Beginner_Projects/Currency-Converter-with toggletheme/README.md index c049e52396..6820ddda0a 100644 --- a/Beginner_Projects/API-key_free_Currency_Converter/README.md +++ b/Beginner_Projects/Currency-Converter-with toggletheme/README.md @@ -20,7 +20,6 @@ A simple, elegant desktop application that converts currencies using real-time e - 🌗 Toggle between **light and dark themes** - ✅ Validates user input with helpful error messages - 💡 Beginner-friendly GUI design using Tkinter -- 📶 No API key required — uses [Frankfurter API](https://frankfurter.app/) --- @@ -40,18 +39,30 @@ A simple, elegant desktop application that converts currencies using real-time e cd PyVerse/Beginner_Projects/API-key_free_Currency_Converter ``` -2. **Install dependencies** - -Make sure Python 3.6+ is Installed - -(Only `requests` is needed) +2. **Create a Virtual Environment** + ```bash + python -m venv venv + source venv/Scripts/activate ----> for ac use: venv/bin/activate + ``` +3. **Install dependencies** + - Make sure Python 3.6+ is Installed + - (Only `requests` is needed) ```bash pip install requests ``` - -Tkinter is usually pre-installed with Python. If not: - -On Windows: Install Python from the official website - -On Linux: sudo apt-get install python3-tk - -On Mac: Already included with Python + - Tkinter is usually pre-installed with Python. If not: + - On Windows: Install Python from the official website + - On Linux: sudo apt-get install python3-tk + - On Mac: Already included with Python + +4. **Set your API-Key** + - Create a file called `.env` in the project folder + - Add your CurrencyFreaks key: + ```ini + API_KEY=your_key_here + ``` -3. **Run the application** +5. **Run the application** ```bash currency_converter.py ``` @@ -60,22 +71,21 @@ A simple, elegant desktop application that converts currencies using real-time e ## 🔐 API Access Notes -This app currently uses the **[Frankfurter API](https://www.frankfurter.app/)**, which is free and does **not** require an API key. -If this changes in the future, follow these steps: +This app currently uses the **[CurrencyFreaks API](https://www.currencyfreaks.com/)** +Follow these steps: -1. **Check the official docs:** [frankfurter.app/docs](https://www.frankfurter.app/docs) -2. **If an API key is required**: - - Register for one on their website - - Update the API call in your code: - ```python - url = f"https://api.frankfurter.app/latest?amount={amount}&from={from_curr}&to={to_curr}&apikey=YOUR_API_KEY" - ``` +1. **Check the official docs:** +2. **API key is required**: + - Register for one on their website. Copy your API Key + - Create a file named `.env` in the project folder. (if it dooesn't alr exist) + - Add your CurrencyFreaks key: + ```ini + API_KEY=your_key_here + ``` - For security: - - Store the key in a `.env` file using the `python-dotenv` package - Never commit API keys to GitHub 3. **Alternative APIs you can switch to**: - - [CurrencyFreaks](https://currencyfreaks.com/) - [Open Exchange Rates](https://openexchangerates.org/) --- diff --git a/Beginner_Projects/API-key_free_Currency_Converter/assets/dark_mode.png b/Beginner_Projects/Currency-Converter-with toggletheme/assets/dark_mode.png similarity index 100% rename from Beginner_Projects/API-key_free_Currency_Converter/assets/dark_mode.png rename to Beginner_Projects/Currency-Converter-with toggletheme/assets/dark_mode.png diff --git a/Beginner_Projects/API-key_free_Currency_Converter/assets/light_mode.png b/Beginner_Projects/Currency-Converter-with toggletheme/assets/light_mode.png similarity index 100% rename from Beginner_Projects/API-key_free_Currency_Converter/assets/light_mode.png rename to Beginner_Projects/Currency-Converter-with toggletheme/assets/light_mode.png diff --git a/Beginner_Projects/API-key_free_Currency_Converter/currency_converter.py b/Beginner_Projects/Currency-Converter-with toggletheme/currency_converter.py similarity index 53% rename from Beginner_Projects/API-key_free_Currency_Converter/currency_converter.py rename to Beginner_Projects/Currency-Converter-with toggletheme/currency_converter.py index 999f425c12..3667deac0a 100644 --- a/Beginner_Projects/API-key_free_Currency_Converter/currency_converter.py +++ b/Beginner_Projects/Currency-Converter-with toggletheme/currency_converter.py @@ -1,6 +1,17 @@ import tkinter as tk import requests # type: ignore from tkinter import messagebox +from dotenv import load_dotenv +import os + +load_dotenv() +API_KEY =os.getenv("API_KEY") + + +#Adding placeholders to avoid hardcoding +PLACEHOLDER_FROM = "eg: USD" +PLACEHOLDER_TO ="eg: INR" +PLACEHOLDER_AMOUNT = "eg: 250.00" #keeping the intial theme as light is_dark_mode = False @@ -12,14 +23,14 @@ "foreground_color": "#333333", "entry_bg": "#F0F0F0", "button_background": "#4CAF50", - "button_forrground": "#F0F0F0" + "button_foreground": "#F0F0F0" #fixed typo }, "dark":{ "background_color": "#2C2C2C", "foreground_color": "#EEEEEE", "entry_bg": "#292929", "button_background": "#FFB300", - "button_forrground": "#F0F7FA" + "button_foreground": "#F0F7FA" #fixed typo } } @@ -42,10 +53,10 @@ def apply_theme(theme_name): if cls == "Entry": widget.configure(bg=theme["entry_bg"], fg=theme["foreground_color"]) elif cls == "Button": - if widget['text'] == "Switch Theme": + if widget['text'] == "Toggle Theme": widget.configure(bg="#888", fg="#F0F0F0") else: - widget.configure(bg=theme["button_background"], fg=theme["button_forrground"]) + widget.configure(bg=theme["button_background"], fg=theme["button_foreground"]) elif cls == "Label": widget.configure(bg=theme["background_color"], fg=theme["foreground_color"]) @@ -57,13 +68,14 @@ def toggle_theme(): apply_theme(theme) #conversion logic +#modified this so that error message resets after a success and hadles the edge cases better def convert_currency(): #definig them from_curr = entry_from.get().upper().strip() to_curr = entry_to.get().upper().strip() amount = entry_amount.get().strip() - if from_curr in ["", "eg: USD"] or to_curr in ["", "eg: INR"] or amount in ["", "eg: 250.00"]: + if from_curr in ["", PLACEHOLDER_FROM] or to_curr in ["", PLACEHOLDER_TO] or amount in ["", PLACEHOLDER_AMOUNT]: error_label.config(text="Please fill all fields with valid values.") return @@ -74,22 +86,39 @@ def convert_currency(): return #api url - url = f"https://api.frankfurter.app/latest?amount={amount}&from={from_curr}&to={to_curr}" + url = f"https://api.currencyfreaks.com/latest?apikey={API_KEY}&symbols={from_curr},{to_curr}" try: response = requests.get(url) + response.raise_for_status() data = response.json() - print(data) + base_currency = data.get("base", "") + rates = data.get("rates",{}) + + #taking care of base case and falling back to usd incase either from or t_curr is the base currrency. + rate_from = float(rates.get(from_curr)) if from_curr !=base_currency else 1.0 + rate_to = float(rates.get(to_curr)) if to_curr != base_currency else 1.0 - converted = data["rates"].get(to_curr) - if converted: - result_label.config(text=f"{amount} {from_curr} = {round(converted, 2)} {to_curr}") - error_label.config(text="") - else: - error_label.config(text="Conversion failed. Check currency codes.") - except Exception as e: - error_label.config(text="An error occurred. Check your internet connection and try again.") + if not rate_from or not rate_to: + error_label.config(text="Invalid currency codes or Unvailable rate. \n Please try again.") + return + + #since it used usd as base we convert using usd as base + usd_amount = amount/rate_from #converted to usd + converted = round(usd_amount * rate_to, 2) #converted to to_curr + + result_label.config(text=f"{amount} {from_curr} = {converted} {to_curr}") + error_label.config(text="")#error cleared after a success + + except requests.RequestException: + error_label.config(text="Network error. Check your internet or API key.") + except ValueError: + error_label.config(text="Error processing the exchange rate.") + #here since the earlier one (frankfurt) changed their documents (inr isn't included anymore) i had to ended switching over currencyfreaks. + #however to access the converstion i would have to buy the starter plan so to avoid that i removed the base case. But since it's possible + #that some currencies might be the base so to counter that i used the above logic that runs independent of what the base currency is and will work + #even in the case of the from_curr and to_curr beign one of the base currencies. #label+entry func @@ -115,17 +144,18 @@ def on_focus_out(event): return entry #Input fields: -entry_from = labeled_entry("From Currency Code (3 letters):", "eg: USD") -entry_to = labeled_entry("To Currency Code (3 letters):", "eg: INR") -entry_amount = labeled_entry("Amount:", "e.g. 250.00") +#modified for placeholder +entry_from = labeled_entry("From Currency Code (3 letters):", PLACEHOLDER_FROM) +entry_to = labeled_entry("To Currency Code (3 letters):", PLACEHOLDER_TO) +entry_amount = labeled_entry("Amount:", PLACEHOLDER_AMOUNT) -#convrtion button +#convertion button convert_button = tk.Button(root, text="Convert", command=convert_currency, font=FONT_LABEL, width=15) convert_button.pack(pady=15) #result label: result_label = tk.Label(root, text="", font=FONT_RESULT) -result_label.pack(pady=10) +result_label.pack(pady=15) #error label: error_label = tk.Label(root, text="", fg="red", font=("Helvetica", 10, "italic")) @@ -137,4 +167,7 @@ def on_focus_out(event): apply_theme("light") +#to start the conversion (instead onf clicking on convert just simply pressing enter): +root.bind("", lambda event:convert_currency()) + root.mainloop() diff --git a/Beginner_Projects/Currency-Converter-with toggletheme/run_converter.bat b/Beginner_Projects/Currency-Converter-with toggletheme/run_converter.bat new file mode 100644 index 0000000000..9ffecfcf9d --- /dev/null +++ b/Beginner_Projects/Currency-Converter-with toggletheme/run_converter.bat @@ -0,0 +1,2 @@ +@echo off +start "" "%~dp0venv\Scripts\pythonw.exe" "%~dp0currency_converter.py"