diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fff4da8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,63 @@ +# Python cache files +__pycache__/ +*.py[cod] +*$py.class + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +*.manifest +*.spec + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Virtual environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# IDE files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS files +.DS_Store +Thumbs.db + +# Temporary files +*.tmp +*.temp +/tmp/ \ No newline at end of file diff --git a/week1_projects/copilot/URL_Shortener/README.md b/week1_projects/copilot/URL_Shortener/README.md new file mode 100644 index 0000000..b89a784 --- /dev/null +++ b/week1_projects/copilot/URL_Shortener/README.md @@ -0,0 +1,155 @@ +# šŸ”— URL Shortener (Offline) + +A simple, beginner-friendly Python project that creates short codes for long URLs and stores them locally. This tool works completely offline - no internet connection required once it's running! + +## šŸ“‹ What This Project Does + +- **Shorten URLs**: Takes long website links and creates short, memorable codes +- **Expand URLs**: Retrieves original URLs using short codes +- **Local Storage**: Saves all mappings in a JSON file (`url_mappings.json`) +- **Statistics**: Tracks usage and provides insights +- **Offline Operation**: Works without internet connectivity + +## šŸŽÆ Features + +- āœ… Generate 6-character alphanumeric short codes (e.g., `abc123`) +- āœ… Validate URL formats before shortening +- āœ… Prevent duplicate URLs (returns existing short code) +- āœ… Track access count for each shortened URL +- āœ… List all shortened URLs with metadata +- āœ… Display usage statistics +- āœ… User-friendly command-line interface +- āœ… Persistent data storage in JSON format + +## šŸš€ How to Run + +1. **Prerequisites**: Make sure you have Python 3.6+ installed +2. **Download**: Save the `URL_Shortener.py` file to your computer +3. **Run**: Open terminal/command prompt and navigate to the file location +4. **Execute**: Run the command: + ```bash + python URL_Shortener.py + ``` + +## šŸ’” How to Use + +The program presents a menu with 5 options: + +### 1. Shorten a URL +``` +Enter the URL to shorten: https://www.example.com/very/long/path +āœ… URL shortened successfully! +šŸ”— Short code: aBc123 +``` + +### 2. Expand a short code +``` +Enter the short code: aBc123 +āœ… URL retrieved successfully! +🌐 Original URL: https://www.example.com/very/long/path +``` + +### 3. List all URLs +Shows all shortened URLs with creation dates and access counts. + +### 4. Show statistics +Displays total URLs shortened and access statistics. + +### 5. Exit +Closes the program safely. + +## šŸ“ Example Usage + +### Input/Output Examples: + +**Shortening a URL:** +``` +Input: https://github.com/NeuroByte-Society/weekend_projects +Output: Short code generated → K7m2Np +``` + +**Expanding a code:** +``` +Input: K7m2Np +Output: https://github.com/NeuroByte-Society/weekend_projects +``` + +**Invalid URL handling:** +``` +Input: not-a-valid-url +Output: āŒ Error: Invalid URL format. Please include http://, https://, or a valid domain. +``` + +## šŸ—‚ļø Data Storage + +The program creates a `url_mappings.json` file that stores: +- Short code mappings +- Original URLs +- Creation timestamps +- Access count for each URL + +Example JSON structure: +```json +{ + "K7m2Np": { + "url": "https://github.com/NeuroByte-Society/weekend_projects", + "created_at": "2024-01-15T10:30:45", + "access_count": 3 + } +} +``` + +## šŸ› ļø Technical Details + +**Language**: Python 3.6+ +**Dependencies**: Only built-in Python modules: +- `json` - For data storage +- `random` & `string` - For generating short codes +- `os` - For file operations +- `datetime` - For timestamps + +**Key Functions**: +- `generate_short_code()` - Creates unique 6-character codes +- `shorten_url()` - Maps long URLs to short codes +- `expand_url()` - Retrieves original URLs +- `is_valid_url()` - Validates URL format + +## šŸŽ“ What I Learned + +- **File I/O**: Reading from and writing to JSON files +- **Data Validation**: Checking URL formats and handling edge cases +- **User Interface**: Creating an interactive command-line menu +- **Data Structures**: Using dictionaries for efficient key-value mapping +- **Error Handling**: Managing invalid inputs gracefully +- **Code Organization**: Structuring code with classes and methods + +## šŸ”§ Possible Enhancements + +- Custom short code length options +- URL expiration dates +- Import/export functionality +- Basic analytics dashboard +- QR code generation for short URLs +- Bulk URL processing + +## šŸ“ File Structure + +``` +URL_Shortener/ +ā”œā”€ā”€ URL_Shortener.py # Main program file +ā”œā”€ā”€ README.md # This documentation +└── url_mappings.json # Generated data file (created when first URL is shortened) +``` + +## 🚨 Notes + +- The `url_mappings.json` file is created automatically when you shorten your first URL +- All data is stored locally - no data is sent to external servers +- Short codes are case-sensitive +- The program performs basic URL validation but doesn't verify if URLs actually exist + +--- + +**Project by**: @copilot for NeuroByte Society Weekend Projects +**Difficulty**: Beginner-friendly +**Estimated time**: 2-3 hours \ No newline at end of file diff --git a/week1_projects/copilot/URL_Shortener/URL_Shortener.py b/week1_projects/copilot/URL_Shortener/URL_Shortener.py new file mode 100644 index 0000000..fe555b2 --- /dev/null +++ b/week1_projects/copilot/URL_Shortener/URL_Shortener.py @@ -0,0 +1,170 @@ +import json +import random +import string +import os +from datetime import datetime + +class URLShortener: + def __init__(self, data_file="url_mappings.json"): + """Initialize the URL Shortener with a data file.""" + self.data_file = data_file + self.url_mappings = self.load_mappings() + + def load_mappings(self): + """Load existing URL mappings from the JSON file.""" + if os.path.exists(self.data_file): + try: + with open(self.data_file, 'r') as file: + return json.load(file) + except (json.JSONDecodeError, FileNotFoundError): + return {} + return {} + + def save_mappings(self): + """Save URL mappings to the JSON file.""" + with open(self.data_file, 'w') as file: + json.dump(self.url_mappings, file, indent=2) + + def generate_short_code(self, length=6): + """Generate a random short code.""" + characters = string.ascii_letters + string.digits + while True: + short_code = ''.join(random.choice(characters) for _ in range(length)) + # Ensure the code doesn't already exist + if short_code not in self.url_mappings: + return short_code + + def is_valid_url(self, url): + """Basic URL validation.""" + url = url.strip() + if not url: + return False + + # Basic check for common URL patterns + valid_prefixes = ['http://', 'https://', 'ftp://', 'www.'] + has_valid_prefix = any(url.lower().startswith(prefix) for prefix in valid_prefixes) + + # Check if it contains a dot (basic domain check) + has_dot = '.' in url + + return has_valid_prefix or has_dot + + def shorten_url(self, long_url): + """Shorten a long URL and return the short code.""" + long_url = long_url.strip() + + if not self.is_valid_url(long_url): + return None, "Invalid URL format. Please include http://, https://, or a valid domain." + + # Check if URL already exists + for short_code, data in self.url_mappings.items(): + if data['url'] == long_url: + return short_code, f"URL already shortened! Short code: {short_code}" + + # Generate new short code + short_code = self.generate_short_code() + + # Store the mapping with metadata + self.url_mappings[short_code] = { + 'url': long_url, + 'created_at': datetime.now().isoformat(), + 'access_count': 0 + } + + # Save to file + self.save_mappings() + + return short_code, "URL shortened successfully!" + + def expand_url(self, short_code): + """Expand a short code back to the original URL.""" + short_code = short_code.strip() + + if short_code in self.url_mappings: + # Increment access count + self.url_mappings[short_code]['access_count'] += 1 + self.save_mappings() + + return self.url_mappings[short_code]['url'], "URL retrieved successfully!" + else: + return None, f"Short code '{short_code}' not found." + + def list_all_urls(self): + """List all shortened URLs.""" + if not self.url_mappings: + return "No URLs have been shortened yet." + + result = "\n=== All Shortened URLs ===\n" + for short_code, data in self.url_mappings.items(): + result += f"Short Code: {short_code}\n" + result += f"Original URL: {data['url']}\n" + result += f"Created: {data['created_at'][:19]}\n" + result += f"Access Count: {data['access_count']}\n" + result += "-" * 40 + "\n" + + return result + + def get_stats(self): + """Get statistics about the URL shortener.""" + total_urls = len(self.url_mappings) + total_accesses = sum(data['access_count'] for data in self.url_mappings.values()) + + return f""" +=== URL Shortener Statistics === +Total URLs shortened: {total_urls} +Total accesses: {total_accesses} +Average accesses per URL: {total_accesses / total_urls if total_urls > 0 else 0:.1f} +""" + +def main(): + """Main function to run the URL Shortener CLI.""" + shortener = URLShortener() + + print("šŸ”— Welcome to the Offline URL Shortener!") + print("=" * 40) + + while True: + print("\nChoose an option:") + print("1. Shorten a URL") + print("2. Expand a short code") + print("3. List all URLs") + print("4. Show statistics") + print("5. Exit") + + choice = input("\nEnter your choice (1-5): ").strip() + + if choice == '1': + long_url = input("Enter the URL to shorten: ") + short_code, message = shortener.shorten_url(long_url) + + if short_code: + print(f"\nāœ… {message}") + print(f"šŸ”— Short code: {short_code}") + else: + print(f"\nāŒ Error: {message}") + + elif choice == '2': + short_code = input("Enter the short code: ") + original_url, message = shortener.expand_url(short_code) + + if original_url: + print(f"\nāœ… {message}") + print(f"🌐 Original URL: {original_url}") + else: + print(f"\nāŒ Error: {message}") + + elif choice == '3': + print(shortener.list_all_urls()) + + elif choice == '4': + print(shortener.get_stats()) + + elif choice == '5': + print("\nšŸ‘‹ Thank you for using the URL Shortener!") + break + + else: + print("\nāŒ Invalid choice. Please enter a number between 1 and 5.") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/week1_projects/copilot/URL_Shortener/url_mappings.json b/week1_projects/copilot/URL_Shortener/url_mappings.json new file mode 100644 index 0000000..fd6edbd --- /dev/null +++ b/week1_projects/copilot/URL_Shortener/url_mappings.json @@ -0,0 +1,17 @@ +{ + "MkSHJI": { + "url": "https://github.com/NeuroByte-Society/weekend_projects", + "created_at": "2025-08-20T17:34:00.891582", + "access_count": 1 + }, + "9RQgeU": { + "url": "https://example.com", + "created_at": "2025-08-20T17:35:22.534711", + "access_count": 0 + }, + "4j8X1K": { + "url": "https://example.com/very/long/path/to/some/resource", + "created_at": "2025-08-20T17:36:26.558257", + "access_count": 1 + } +} \ No newline at end of file