├── .github └── dependabot.yml ├── .gitignore ├── LICENSE ├── README.md ├── addLogo └── addLogo.py ├── addWatermarkPDF └── addWatermarkPDF.py ├── codeDestroyer ├── codeDestroyer.py └── helloWorld.c ├── combinePDF └── combinePDF.py ├── encryptDecryptPDF └── encryptDecryptPDF.py ├── fillGap ├── fillGap.py └── test │ ├── spam01.txt │ ├── spam02.txt │ ├── spam04.txt │ ├── spam05.txt │ ├── spam06.txt │ ├── spam07.txt │ ├── spam09.txt │ ├── spam12.txt │ ├── spam35.txt │ ├── spam56.txt │ └── spam98.txt ├── phoneAndEmailExtractor ├── emails.txt ├── phoneAndEmail.py └── phoneNumbers.txt ├── requirements.txt └── searchSize └── searchSize.py /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: pip 4 | directory: "/" 5 | schedule: 6 | interval: monthly 7 | time: "08:30" 8 | timezone: Asia/Kolkata 9 | open-pull-requests-limit: 10 10 | ignore: 11 | - dependency-name: pypdf3 12 | versions: 13 | - 1.0.2 14 | - dependency-name: pyperclip 15 | versions: 16 | - 1.8.1 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | # Compiled source 107 | *.com 108 | *.class 109 | *.dll 110 | *.exe 111 | *.o 112 | *.so 113 | *.pyc 114 | *.pyo 115 | 116 | # Packages 117 | *.7z 118 | *.dmg 119 | *.gz 120 | *.iso 121 | *.jar 122 | *.rar 123 | *.tar 124 | *.zip 125 | *.msi 126 | 127 | # Logs and databases 128 | *.sql 129 | *.sqlite 130 | 131 | # OS generated files 132 | .DS_Store 133 | .DS_Store? 134 | ._* 135 | .Spotlight-V100 136 | .Trashes 137 | ehthumbs.db 138 | Thumbs.db 139 | desktop.ini 140 | 141 | # IDE files 142 | .vscode 143 | .idea 144 | .iml 145 | *.sublime-workspace 146 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Pushkar Patel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

JFF-Python-Scripts

2 | 3 |

A collection of Python Scripts made for fun, while exploring Python 🐍

4 | 5 | ### Inspiration 💡 6 | 7 | Many of the programs in this repository are inspired from the projects given in [Automate the Boring Stuff with Python](https://automatetheboringstuff.com/) by [Al Sweigart](https://github.com/asweigart) and some other are born out of redundant curiosity of a boring mind during lazy afternoons. 8 | 9 | This repository would contain python scripts, some of which might come of use occasionally. The purpose of creating this is to explore the various modules and implementations of the language through creating programs that are as much fun to use as they are to make. 10 | 11 | ## How to Use? 😀 12 | 13 | - Clone the repository `$ git clone https://github.com/thepushkarp/JFF-Python-Scripts.git` 14 | - Create a virtual environment ([click here](https://packaging.python.org/guides/installing-using-pip-and-virtual-environments/) to learn about Virtual Environment) 15 | 16 | ```sh 17 | virtualenv env 18 | ``` 19 | 20 | - Activate virtual environment (On macOS and Linux) 21 | 22 | ```sh 23 | source env/bin/activate 24 | ``` 25 | 26 | - Activate virtual environment (On Windows) 27 | 28 | ```sh 29 | .\env\Scripts\activate 30 | ``` 31 | 32 | - Install requirements 33 | 34 | ```sh 35 | pip3 install -r requirements.txt 36 | ``` 37 | 38 | - Run and explore the scripts! 39 | 40 | __NOTE: All the scripts are written in Python 3. So, make sure to use the appropriate version of pip and python.__ 41 | 42 | ## Contents 📄 43 | 44 | - [Code Destroyer](#Code-Destroyer) 45 | - [Extract Phone Number and Email](#Extract-Phone-Number-and-Email) 46 | - [Search files based on size](#Search-files-based-on-size) 47 | - [Fill gaps in naming](#Fill-gaps-in-naming) 48 | - [Combine PDF files](#Combine-PDF-files) 49 | - [Add Watermark to PDF](#Add-Watermark-to-PDF) 50 | - [Encrypt or Decrypt a PDF](#Encrypt-or-Decrypt-a-PDF) 51 | - [Add Logo to Images](#Add-Logo-to-Images) 52 | 53 | ### Code Destroyer 54 | 55 | Code Destroyer, inspired by a [tweet](https://twitter.com/benbjohnson/status/533848879423578112?lang=en) by Ben Johnson, replaces semicolon ";" (U+003B) in files with a Greek Question Mark ";" (U+037E), that looks alike, but shows syntax errors (since it is a different character) leaving the programmer scratching their heads in confusion. ;-) 56 | 57 | #### Usage: 58 | 59 | Put the file to be destroyed in the same folder as this script and run: 60 | 61 | ```py3 62 | python3 codeDestroyer.py 63 | ``` 64 | 65 | Enter the full filename (like helloWorld.c) in the prompt that follows. 66 | 67 | __Disclaimer: Do not use this to prank on someone's hard-work. You know how frustating that feels.__ 68 | 69 | ### Extract Phone Number and Email 70 | 71 | Takes in the text from your clipboard and saves the Phone Numbers and Email Addresses found in it to .txt files. It searches for Indian Mobile Phone Numbers, Toll-Free Numbers, Telephone Numbers and Emails using Regular Expressions. 72 | 73 | _Useful if you have a large text data (like a website) and you are searching for phone numbers of emails in that text._ 74 | 75 | #### Usage: 76 | 77 | ```py3 78 | python3 phoneAndEmail.py 79 | ``` 80 | 81 | Two files, `emails.txt` and `phoneNumbers.txt` would be created in the same directory containing the emails and phone numbers from the copied text. 82 | 83 | ### Search files based on size 84 | 85 | Lets you search through a folder based on file size. Asks user for folder path and size. Files and subfolders inside the folder, greater than or equal to the input size would be displayed. 86 | 87 | _Useful if you want to find large files and folders taking up space and wish to delete them._ 88 | 89 | #### Usage: 90 | 91 | ```py3 92 | python3 searchSize.py 93 | ``` 94 | 95 | When prompted, enter the minimum size (in bytes) and the folder where files are to be searched. If the path entered is correct, the files, above and equal the size entered would be displayed. 96 | 97 | ### Fill gaps in naming 98 | 99 | Finds all files with a given prefix, such as spam001.txt, spam002.txt, and so on, in a single folder and locates any gaps in the numbering (such as if there is a spam001.txt and spam003.txt but no spam002.txt) and reanames all the files to close this gap. 100 | 101 | _Useful if you have a number of files with same prefix and numbering after it and by some case, there is irregularity in numbering (like after deleting unnecessary images from a camera) and you wish to get a ragular naming in those files._ 102 | 103 | #### Usage: 104 | 105 | ```py3 106 | python3 fillGap.py 107 | ``` 108 | 109 | Enter the file prefix, extesion name and taret folder in the prompt that appears. The files would be named in 110 | order, closing gaps, if any. 111 | 112 | ### Combine PDF files 113 | 114 | Combines all the PDFs in the current working directory into 115 | a single PDF. The program also prompts user if they want to include the cover page of all the PDFs that are being merged. 116 | 117 | It is recommended to rename files so that they are lexographically in the same order as they are to be combined and put them in the same directory as the script. 118 | The combined PDF would be saved as the name of the first file in the lexographic order prepended with 'combined'. 119 | 120 | _Useful if you have many PDF and you want to read them all one after the another (like all the PDFs of a professor's slides that you wish to read before exams). You won't need to go from one PDF to another after using this and would also have the option of adding or removing the coverpage of each PDF._ 121 | 122 | __Ensure that none of the PDFs are encrypted.__ 123 | 124 | #### Usage: 125 | 126 | ```py3 127 | python3 combinePDF.py 128 | ``` 129 | 130 | Choose whether you want to include the cover page of each individual PDF by entering `y` or `n`. 131 | 132 | ### Add Watermark to PDF 133 | 134 | Add watermark to every page of a PDF document. 135 | 136 | The watermark file should be a PDF too. If you want to make an image or text as a watermark, put them in a word file and stylize as per you want it to appear as the watermark and then export the file as PDF. This file would be the watermark file. 137 | 138 | _The usefullness of this script is straightforward - To add watermark to PDF files to prove its originality, make it harder to copy, and add authorship._ 139 | 140 | __Ensure that none of the PDFs are encrypted.__ 141 | 142 | #### Usage: 143 | 144 | ```py3 145 | python3 addWatermarkPDF.py 146 | ``` 147 | 148 | Enter the filenames of the PDF to be watermarked and then of the watermark PDF. 149 | 150 | ### Encrypt or Decrypt a PDF 151 | 152 | Encrypt an unencrypted PDF file with a password or decrypt a password-protected PDF and save as an unencrypted file. 153 | 154 | _The usefullness of this script too is pretty straightforward - To add or remove privacy to PDF files._ 155 | 156 | #### Usage: 157 | 158 | ```py3 159 | python3 encryptDecryptPDF.py 160 | ``` 161 | 162 | Choose whether you want to encrypt or decrypt a PDF and then enter the name of the file. You would be prompted to enter the password either to encrypt the PDF or decrypt it, as selected earlier. 163 | 164 | ### Add Logo to Images 165 | 166 | Adds logo to the lower-right corner of all the pngs, jpgs and jpegs in the directory. The size of logo is approximately 1/10 th of the size of the image and has a padding of 1/25 th to the right and bottom of the logo is added. 167 | 168 | _Useful to add logos to images to prove their originality, make them harder to copy, and add authorship._ 169 | 170 | #### Usage: 171 | 172 | ```py3 173 | python3 addLogo.py 174 | ``` 175 | 176 | Enter the location of the logo file in the prompt that follows. All the images with added logo would be saved in the 'withLogo' directory. 177 | 178 | 179 | ## License 180 | 181 | [MIT License](LICENSE) 182 | 183 | --- 184 | 185 | File Templates taken from [awesome-bashrc](https://github.com/aashutoshrathi/awesome-bashrc) and [HackerRank-Test-Case-Generator](https://github.com/aashutoshrathi/HackerRank-Test-Case-Generator/). 186 | 187 |

Made with ❤ by Pushkar Patel

188 | -------------------------------------------------------------------------------- /addLogo/addLogo.py: -------------------------------------------------------------------------------- 1 | """ 2 | addLogo.py - Adds logo to the lower-right corner of all the pngs, jpgs and 3 | jpegs in the directory. The size of logo is approximately 1/10 th of the size 4 | of the image and has a padding of 1/25 th to the right and bottom of the logo 5 | is added. 6 | 7 | Usage: run "python3 addLogo.py" and enter the name of the logo to be inserted. 8 | All the images with added logo would be saved in 'withLogo' directory. 9 | """ 10 | 11 | import os 12 | import sys 13 | from PIL import Image 14 | 15 | logoName = input('Enter the name of the logo image:\n') 16 | logoName = os.path.abspath(logoName) 17 | 18 | # If logo file does not ecists or is not a supported image file 19 | if not os.path.exists(logoName): 20 | print(f'The filename {logoName} does not exists.') 21 | sys.exit() 22 | elif not (logoName.lower().endswith('.png') or \ 23 | logoName.lower().endswith('.jpg') or logoName.lower().endswith('.jpeg')): 24 | print(f'The filename {logoName} is not a supported image file.') 25 | sys.exit() 26 | 27 | logoIm = Image.open(logoName).convert("RGBA") 28 | logoWidth, logoHeight = logoIm.size 29 | os.makedirs('withLogo', exist_ok = True) 30 | 31 | # Loop over all files in the working directory 32 | for fileName in os.listdir('.'): 33 | if not (fileName.lower().endswith('.png') or \ 34 | fileName.lower().endswith('.jpg') or \ 35 | fileName.lower().endswith('.jpeg')) or \ 36 | os.path.abspath(fileName) == logoName: 37 | continue # skip non-image files and the logo file itself 38 | 39 | im = Image.open(fileName) 40 | width, height = im.size 41 | 42 | # Resizes the largest dimention of logo to 1/10th of smallest dimension 43 | # of the image file and padding to 1/25th. 44 | if height < width: 45 | if logoWidth > logoHeight: 46 | logoHeight = int((logoHeight / logoWidth) * int(height/10)) 47 | logoWidth = int(height/10) 48 | else: 49 | logoWidth = int((logoWidth / logoHeight) * int(height/10)) 50 | logoHeight = int(height/10) 51 | pad = int(height/25) 52 | else: 53 | if logoWidth > logoHeight: 54 | logoHeight = int((logoHeight / logoWidth) * int(width/10)) 55 | logoWidth = int(width/10) 56 | else: 57 | logoWidth = int((logoWidth / logoHeight) * int(width/10)) 58 | logoHeight = int(width/10) 59 | pad = int(height/25) 60 | 61 | # Resize the logo 62 | logoIm = logoIm.resize((logoWidth, logoHeight), Image.ANTIALIAS) 63 | 64 | # Add logo 65 | print(f'\nAdding logo to {fileName}...') 66 | im.paste(logoIm, (width - logoWidth - pad, height - logoHeight - pad), \ 67 | logoIm) 68 | 69 | # Save the image with added logo 70 | im.save(os.path.join('withLogo', fileName), quality = 100) 71 | print(f'Saved {fileName} with added logo') 72 | -------------------------------------------------------------------------------- /addWatermarkPDF/addWatermarkPDF.py: -------------------------------------------------------------------------------- 1 | """ 2 | addWatermarkPDF.py - Add watermark to every page of a PDF document 3 | 4 | Usage: run "python3 addWatermarkPDF.py" and enter the filenames of 5 | the PDF to be watermarked and the watermark PDF. 6 | """ 7 | 8 | from os import path 9 | import sys 10 | import PyPDF3 11 | 12 | # PDF filenames 13 | baseFileName = input('Enter the name of the PDF file to be watermarked:\n') 14 | baseFileName = path.abspath(baseFileName) 15 | watermarkName = input('Enter the name of watermark PDF:\n') 16 | watermarkName = path.abspath(watermarkName) 17 | 18 | # Check if entered filenames are valid 19 | if not path.exists(baseFileName) or baseFileName[-4:].lower() != '.pdf': 20 | print(f'The filename {baseFileName} is not a PDF.') 21 | sys.exit() 22 | 23 | elif not path.exists(watermarkName) or watermarkName[-4:].lower() != '.pdf': 24 | print(f'The filename {watermarkName} is not a PDF.') 25 | sys.exit() 26 | 27 | else: 28 | print('Adding Watermark...') 29 | 30 | baseFile = open(baseFileName, 'rb') 31 | pdfReader = PyPDF3.PdfFileReader(baseFile) 32 | pdfWatermarkReader = PyPDF3.PdfFileReader(open(watermarkName, 'rb')) 33 | pdfWriter = PyPDF3.PdfFileWriter() 34 | 35 | # Merge watermark to each page of PDF 36 | for pageNum in range(pdfReader.numPages): 37 | pageObj = pdfReader.getPage(pageNum) 38 | pageObj.mergePage(pdfWatermarkReader.getPage(0)) 39 | pdfWriter.addPage(pageObj) 40 | 41 | # Save the resulting PDF to a file 42 | markedPdfFile = open('watermarked' + path.basename(baseFileName), 'wb') 43 | pdfWriter.write(markedPdfFile) 44 | baseFile.close() 45 | markedPdfFile.close() 46 | 47 | print(f'Watermarked file saved as watermarked{path.basename(baseFileName)}') 48 | -------------------------------------------------------------------------------- /codeDestroyer/codeDestroyer.py: -------------------------------------------------------------------------------- 1 | """ 2 | codeDestroyer.py - Replaces semicolon(;) in files with Greek 3 | Question Mark(;) that looks alike but shows syntax errors, 4 | (since it is a different character) leaving the programmer 5 | scratching their heads in confusion. ;-) 6 | 7 | Usage: Put the file in the same folder as this script and run 8 | "python3 codeDestroyer.py". Enter the full filename 9 | (like helloWorld.c) in the prompt that follows. 10 | """ 11 | 12 | import sys 13 | from os import path 14 | import re 15 | 16 | # Unicode symbols for semicolon and the Greek Question mark 17 | semicolon = u'\u003b' 18 | greekQmark = u'\u037e' 19 | 20 | # Name of file 21 | fileName = input('Enter the file name (like helloWorld.c):\n') 22 | fileName = path.abspath(fileName) 23 | if (not path.exists(fileName)) or path.islink(fileName): 24 | print(f'\n{fileName} is not a valid file.\ 25 | Please enter a valid filename.') 26 | sys.exit() 27 | else: 28 | # Open the file to be destroyed 29 | destroyFile = open(fileName, 'r+') 30 | 31 | # Replace the characters in contents 32 | contents = destroyFile.read() 33 | contents = re.sub(semicolon, greekQmark, contents) 34 | 35 | print(f'Destroying {fileName}...') 36 | # Overwrite on the original file 37 | destroyFile.seek(0, 0) 38 | destroyFile.write(contents) 39 | destroyFile.close() 40 | print(f'\n {fileName} destroyed successfully XD.') 41 | -------------------------------------------------------------------------------- /codeDestroyer/helloWorld.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(){ 4 | printf("Hello World!"); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /combinePDF/combinePDF.py: -------------------------------------------------------------------------------- 1 | """ 2 | combinePDF.py - Combines all the PDFs in the current working directory into 3 | a single PDF. 4 | 5 | Usage: run "python3 combinePDF.py" and choose whether you want to include the 6 | cover page of each individual PDF by entering y or n. 7 | """ 8 | 9 | import os 10 | import PyPDF3 11 | 12 | # Get all the PDF filenames 13 | pdfFiles = [] 14 | for filename in os.listdir('.'): 15 | if filename.endswith('.pdf'): 16 | pdfFiles.append(filename) 17 | pdfFiles.sort() 18 | 19 | pdfWriter = PyPDF3.PdfFileWriter() 20 | 21 | print('Combining PDFs...') 22 | 23 | # Loop through all the PDF files 24 | for filename in pdfFiles: 25 | pdfFileObj = open(filename, 'rb') 26 | pdfReader = PyPDF3.PdfFileReader(pdfFileObj) 27 | 28 | # Loop through the pages and add them 29 | start = 0 30 | if pdfReader.numPages > 1: 31 | ans = input(f'Do you want to include the cover page of {filename}? \ 32 | (y/n): ') 33 | start = 0 if ans.lower() == 'y' else 1 34 | for pageNum in range(start, pdfReader.numPages): 35 | pageObj = pdfReader.getPage(pageNum) 36 | pdfWriter.addPage(pageObj) 37 | 38 | # Save the resulting PDF to a file 39 | os.makedirs('combinedPDFs', exist_ok = True) 40 | pdfOutput = open(os.path.join('combinedPDFs', 'combined' + pdfFiles[0]), 'wb') 41 | pdfWriter.write(pdfOutput) 42 | pdfOutput.close() 43 | 44 | print(f'Combined PDF saved as combined{pdfFiles[0]}') 45 | -------------------------------------------------------------------------------- /encryptDecryptPDF/encryptDecryptPDF.py: -------------------------------------------------------------------------------- 1 | """ 2 | encryptDecryptPDF.py - A program that can encrypt an unencrypted PDF file 3 | with a password or decrypt an already password-protected PDF to an unencrypted 4 | PDF. 5 | 6 | Usage: run "python3 encryptDecryptPDF.py" and choose whether you want to 7 | encrypt or decrypt a PDF and then enter the name of the file. You would be 8 | prompted to enter the password either to encrypt the PDF or decrypt it, as 9 | selected earlier. 10 | """ 11 | 12 | from os import path 13 | import sys 14 | import PyPDF3 15 | 16 | # Encrypt 17 | def encrypt(): 18 | pdfName = input('Enter the name of PDF file to encrypt:\n') 19 | pdfName = path.abspath(pdfName) 20 | 21 | # Check if entered filename is valid 22 | if not path.exists(pdfName) or pdfName[-4:].lower() != '.pdf': 23 | print(f'The filename {pdfName} is not a PDF.') 24 | sys.exit() 25 | 26 | pdfFile = open(pdfName, 'rb') 27 | pdfReader = PyPDF3.PdfFileReader(pdfFile) 28 | pdfWriter = PyPDF3.PdfFileWriter() 29 | 30 | # Loop through the pages and add them to pdfWriter 31 | for pageNum in range(pdfReader.numPages): 32 | pdfWriter.addPage(pdfReader.getPage(pageNum)) 33 | 34 | # Password for encryption 35 | password = input('Enter a password to encrypt the PDF: \n') 36 | pdfWriter.encrypt(password) 37 | 38 | # Save the resulting PDF to a file 39 | encryptedPdf = open('encrypted' + path.basename(pdfName), 'wb') 40 | pdfWriter.write(encryptedPdf) 41 | encryptedPdf.close() 42 | print(f'File encrypted and saved as encrypted {path.basename(pdfName)}') 43 | 44 | # Decrypt 45 | def decrypt(): 46 | pdfName = input('Enter the name of PDF file to decrypt:\n') 47 | pdfName = path.abspath(pdfName) 48 | 49 | # Check if entered filename is valid 50 | if not path.exists(pdfName) or pdfName[-4:].lower() != '.pdf': 51 | print(f'The filename {pdfName} is not a PDF.') 52 | sys.exit() 53 | 54 | pdfFile = open(pdfName, 'rb') 55 | pdfReader = PyPDF3.PdfFileReader(pdfFile) 56 | 57 | # Password for decryption 58 | password = input('Enter the password to decrypt the PDF: \n') 59 | pdfReader.decrypt(password) 60 | pdfWriter = PyPDF3.PdfFileWriter() 61 | 62 | # Loop through the pages and add them to pdfWriter 63 | for pageNum in range(pdfReader.numPages): 64 | pdfWriter.addPage(pdfReader.getPage(pageNum)) 65 | 66 | # Save the resulting PDF to a file 67 | decryptedPdf = open('decrypted' + path.basename(pdfName), 'wb') 68 | pdfWriter.write(decryptedPdf) 69 | decryptedPdf.close() 70 | print(f'File decrypted and saved as decrypted{path.basename(pdfName)}') 71 | 72 | print('Enter the task to perform (1 or 2)\n1. Encrypt a PDF\n2. Decrypt a PDF') 73 | response = int(input()) 74 | 75 | if response == 1: 76 | encrypt() 77 | 78 | elif response ==2: 79 | decrypt() 80 | 81 | else: 82 | print('You entered a wrong response.') 83 | sys.exit() 84 | -------------------------------------------------------------------------------- /fillGap/fillGap.py: -------------------------------------------------------------------------------- 1 | """ 2 | fillGap.py - A program that finds all files with a given prefix, 3 | such as spam001.txt, spam002.txt, and so on, in a single folder 4 | and locates any gaps in the numbering (such as if there is a 5 | spam001.txt and spam003.txt but no spam002.txt) and reanames all the 6 | files to close this gap. 7 | 8 | Usage: run "python3 fillGap.py" and Enter the file prefix, estension 9 | and taret folder in the prompt that appears. The files would be named 10 | in order, closing gaps, if any. 11 | """ 12 | 13 | import os 14 | import sys 15 | import re 16 | from math import log 17 | import shutil 18 | 19 | # Input file/folder name and extension 20 | filename = input('Enter the name prefix for the files/folders\n') 21 | print('\nEnter the extension after the dot in filenames \ 22 | (like txt in spam01.txt)') 23 | print('Type \'folder\' (without the quotes) if the files are folders') 24 | ext = input() 25 | 26 | # Create filename regex 27 | if ext == 'folder': 28 | nameSeq = re.compile( 29 | r'^' + re.escape(filename) + r'\d*' + r'$' 30 | ) 31 | else: 32 | nameSeq = re.compile( 33 | r'^' + re.escape(filename) + r'\d*' + 34 | r'[.]' + re.escape(ext) + r'$' 35 | ) 36 | 37 | # Put matching file/folder names in a list 38 | path = input('\nEnter the path of folder containing the file/folder\n') 39 | path = os.path.abspath(path) 40 | print(path) 41 | if not os.path.isdir(path): 42 | print('The path entered is not a valid folder.') 43 | sys.exit() 44 | else: 45 | lst = [] 46 | for entry in os.listdir(path): 47 | found = nameSeq.search(entry) 48 | if found: 49 | lst.append(found[0]) 50 | 51 | # Sort list and take size of list as padding 52 | lst = sorted(lst) 53 | padding = int(log(len(lst))//log(10)) + 1 54 | 55 | print('Renamaming files/folders...') 56 | 57 | # Rename files/folders 58 | for i in range(len(lst)): 59 | if ext == 'folder': 60 | newName = filename + str(i).rjust(padding, '0') 61 | oldPath = os.path.join(path, lst[i]) 62 | newPath = os.path.join(path, newName) 63 | shutil.move(oldPath, newPath) 64 | else: 65 | newName = filename + str(i).rjust(padding, '0') + '.' + ext 66 | oldPath = os.path.join(path, lst[i]) 67 | newPath = os.path.join(path, newName) 68 | shutil.move(oldPath, newPath) 69 | print('The files are renamed with gaps closed.') 70 | -------------------------------------------------------------------------------- /fillGap/test/spam01.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepushkarp/JFF-Python-Scripts/e429687a6b1fea961c3a025c81a57ac386125570/fillGap/test/spam01.txt -------------------------------------------------------------------------------- /fillGap/test/spam02.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepushkarp/JFF-Python-Scripts/e429687a6b1fea961c3a025c81a57ac386125570/fillGap/test/spam02.txt -------------------------------------------------------------------------------- /fillGap/test/spam04.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepushkarp/JFF-Python-Scripts/e429687a6b1fea961c3a025c81a57ac386125570/fillGap/test/spam04.txt -------------------------------------------------------------------------------- /fillGap/test/spam05.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepushkarp/JFF-Python-Scripts/e429687a6b1fea961c3a025c81a57ac386125570/fillGap/test/spam05.txt -------------------------------------------------------------------------------- /fillGap/test/spam06.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepushkarp/JFF-Python-Scripts/e429687a6b1fea961c3a025c81a57ac386125570/fillGap/test/spam06.txt -------------------------------------------------------------------------------- /fillGap/test/spam07.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepushkarp/JFF-Python-Scripts/e429687a6b1fea961c3a025c81a57ac386125570/fillGap/test/spam07.txt -------------------------------------------------------------------------------- /fillGap/test/spam09.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepushkarp/JFF-Python-Scripts/e429687a6b1fea961c3a025c81a57ac386125570/fillGap/test/spam09.txt -------------------------------------------------------------------------------- /fillGap/test/spam12.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepushkarp/JFF-Python-Scripts/e429687a6b1fea961c3a025c81a57ac386125570/fillGap/test/spam12.txt -------------------------------------------------------------------------------- /fillGap/test/spam35.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepushkarp/JFF-Python-Scripts/e429687a6b1fea961c3a025c81a57ac386125570/fillGap/test/spam35.txt -------------------------------------------------------------------------------- /fillGap/test/spam56.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepushkarp/JFF-Python-Scripts/e429687a6b1fea961c3a025c81a57ac386125570/fillGap/test/spam56.txt -------------------------------------------------------------------------------- /fillGap/test/spam98.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thepushkarp/JFF-Python-Scripts/e429687a6b1fea961c3a025c81a57ac386125570/fillGap/test/spam98.txt -------------------------------------------------------------------------------- /phoneAndEmailExtractor/emails.txt: -------------------------------------------------------------------------------- 1 | Emails: 2 | No Emails Found 3 | -------------------------------------------------------------------------------- /phoneAndEmailExtractor/phoneAndEmail.py: -------------------------------------------------------------------------------- 1 | """ 2 | phoneAndEmail.py - Finds Indian phone numbers and email addresses 3 | from the clipboard and saves them to a file. 4 | 5 | Usage: Copy the text from where phone numbers and emails are to be 6 | extracted, to the clipboard and run "python3 phoneAndEmail.py". 7 | The phone numbers and emails from the text would be saved in 8 | phoneNumbers.txt and emails.txt files respectively. 9 | """ 10 | 11 | import re 12 | import pyperclip 13 | 14 | # Mobile phone number regex 15 | # Pata nahi log ek universal mobile number format kyu nahi follow 16 | # karte ¯\_(ツ)_/¯ The number could be in the form of AAA-BBB-CCCC, 17 | # AAAAA-BBBBB, AAAA-BBBBBB or AA-BBB-CCCCC, AAAAAAAAAA or maybe 18 | # something else (╯°□°)╯︵ ┻━┻. However, this regex checks for the 19 | # form of AAAA-BBBBBB and AAAAAAAAAA, as given on 20 | # https://en.wikipedia.org/wiki/Telephone_numbers_in_India#mobile_numbers 21 | mobileRegex = re.compile(r'''( 22 | (?: # prefixes 23 | (?: 24 | (?:\+|0{0,2}) # +/zeros before country code 25 | 91 # country code 26 | (?:[ -]?) # separator 27 | ) 28 | |(?:[0]{0,2}[ -]?) # zero and separator before number 29 | )? 30 | ([6-9]\d{3}) # first 4 digits 31 | (?:[ -]?) # separator 32 | (\d{6}) # last 6 digits 33 | )''',re.VERBOSE) 34 | 35 | # Toll-free/local-rate phone number regex 36 | tollFreeRegex = re.compile(r'''( 37 | (1|000) # 1 or 000 38 | (?:[ -]?) # separator 39 | (800|860) # toll-free/local-rate numbers 40 | (?:[ -]?) # separator 41 | (\d{3}) # next 3 digits 42 | (?:[ -]?) # separator 43 | (\d{3,4}) # last 3 or 4 digits 44 | )''',re.VERBOSE) 45 | 46 | # Telephone number Regex 47 | telRegex = re.compile(r'''( 48 | (?: # prefixes 49 | (?: 50 | (?:\+|0{0,2}) # +/zeros before country code 51 | 91 # country code 52 | (?:[ -]?) # separator 53 | ) 54 | |(?:[0]{0,2}[ -]?) # zero and separator before number 55 | )? 56 | (?: 57 | ( # Tier-1 cities 58 | ([1-8]\d{1}) # STD code 59 | (?:[ -]?) # separator 60 | ([2-7]\d{7}) # number 61 | ) 62 | |( # Tier-2 cities 63 | ([1-8]\d{2}) # STD code 64 | (?:[ -]?) # separator 65 | ([2-7]\d{6}) # number 66 | ) 67 | |( # Tier-3 cities 68 | ([1-8]\d{3}) # STD Code 69 | (?:[ -]?) # separator 70 | ([2-7]\d{5}) # number 71 | ) 72 | ) 73 | )''',re.VERBOSE) 74 | 75 | # Email regex 76 | emailRegex = re.compile(r'''( 77 | [a-zA-Z0-9._%+-]+ # username 78 | @ # @ symbol 79 | [a-zA-Z0-9.-]+ # domain name 80 | (\.[a-zA-Z]{2,4}) # dot-something 81 | )''', re.VERBOSE) 82 | 83 | # Find matches in clipboard text 84 | text = str(pyperclip.paste()) 85 | mobileMatches = [] 86 | tollFreeMatches = [] 87 | telMatches = [] 88 | emailMatches = [] 89 | 90 | for groups in mobileRegex.findall(text): 91 | mobNum = ''.join([groups[1], groups[2]]) 92 | mobileMatches.append(mobNum) 93 | 94 | for groups in tollFreeRegex.findall(text): 95 | tollFreeNum = ''.join([groups[1], groups[2], groups[3], groups[4]]) 96 | tollFreeMatches.append(tollFreeNum) 97 | 98 | for groups in telRegex.findall(text): 99 | if groups[1] != '': 100 | telNum = ''.join([groups[2], groups[3]]) 101 | if telNum not in mobileMatches: 102 | if telNum not in tollFreeMatches: 103 | telMatches.append('0'+ groups[1]) 104 | if groups[4] != '': 105 | telNum = ''.join([groups[5], groups[6]]) 106 | if telNum not in mobileMatches: 107 | if telNum not in tollFreeMatches: 108 | telMatches.append('0'+ groups[4]) 109 | if groups[7] != '': 110 | telNum = ''.join([groups[8], groups[9]]) 111 | if telNum not in mobileMatches: 112 | if telNum not in tollFreeMatches: 113 | telMatches.append('0'+ groups[7]) 114 | 115 | for groups in emailRegex.findall(text): 116 | emailMatches.append(groups[0]) 117 | 118 | # Save results in .txt files 119 | phoneNumbers = open('phoneNumbers.txt', 'w') 120 | 121 | phoneNumbers.write('Mobile Phone Numbers:\n') 122 | if mobileMatches == []: 123 | phoneNumbers.write('No Mobile Phone Numbers Found') 124 | else: 125 | phoneNumbers.write('\n'.join(mobileMatches)) 126 | phoneNumbers.write('\n\n') 127 | 128 | phoneNumbers.write('Toll-Free/LocalRate Phone Numbers:\n') 129 | if tollFreeMatches == []: 130 | phoneNumbers.write('No Toll-Free/Local-Rate Phone Numbers Found') 131 | else: 132 | phoneNumbers.write('\n'.join(tollFreeMatches)) 133 | phoneNumbers.write('\n\n') 134 | 135 | phoneNumbers.write('Telephone Numbers:\n') 136 | if telMatches == []: 137 | phoneNumbers.write('No Telephone Numbers Found') 138 | else: 139 | phoneNumbers.write('\n'.join(telMatches)) 140 | phoneNumbers.write('\n') 141 | 142 | emails = open('emails.txt', 'w') 143 | emails.write('Emails:\n') 144 | if emailMatches == []: 145 | emails.write('No Emails Found') 146 | else: 147 | emails.write('\n'.join(emailMatches)) 148 | emails.write('\n') 149 | 150 | phoneNumbers.close() 151 | emails.close() 152 | print('Phone Numbers and Emails saved to phoneNumbers.txt and emails.txt') 153 | -------------------------------------------------------------------------------- /phoneAndEmailExtractor/phoneNumbers.txt: -------------------------------------------------------------------------------- 1 | Mobile Phone Numbers: 2 | No Mobile Phone Numbers Found 3 | 4 | Toll-Free/LocalRate Phone Numbers: 5 | No Toll-Free/Local-Rate Phone Numbers Found 6 | 7 | Telephone Numbers: 8 | No Telephone Numbers Found 9 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pyperclip==1.8.2 2 | Pillow>=6.2.2 3 | PyPDF3==1.0.3 4 | -------------------------------------------------------------------------------- /searchSize/searchSize.py: -------------------------------------------------------------------------------- 1 | """ 2 | searchSize.py - Lets you search through a folder based on file size. 3 | Files and subfolders greater than or equal to the size entered, would 4 | be displayed. 5 | 6 | Usage: run "python3 searchSize.py". When prompted, enter the minimum 7 | size (in bytes) and the folder where files are to be searched. 8 | If the path entered is correct, the files, above and equal the size 9 | entered would be displayed. 10 | """ 11 | 12 | import os 13 | import sys 14 | 15 | # Dictionary to save large files/folders with path as key ad size as 16 | # value 17 | large = {} 18 | 19 | # Get size of folder and save path of files and folders greater than 20 | # input size to the dict. large 21 | def getSize(folPath): 22 | totalSize = 0 23 | for folderName, subfolders, fileNames in os.walk(folPath): 24 | for subfolder in subfolders: 25 | subfolderPath = os.path.join(folderName, subfolder) 26 | subfolderSize = getSize(subfolderPath) 27 | if subfolderSize >= size: 28 | large[subfolderPath] = subfolderSize 29 | totalSize += subfolderSize 30 | 31 | for fileName in fileNames: 32 | filePath = os.path.join(folderName, fileName) 33 | if not os.path.islink(filePath): # Skip if symbolic link 34 | fileSize = os.path.getsize(filePath) 35 | if fileSize >= size: 36 | large[filePath] = fileSize 37 | totalSize += fileSize 38 | return totalSize 39 | 40 | # Input minimum size 41 | size = int(input('Enter the minimum size (in bytes)\n')) 42 | 43 | # Input folder name 44 | folder = input('Enter the path of the folder to search\n') 45 | folder = os.path.abspath(folder) # Absolute path 46 | 47 | # Verify if folder name and path exists 48 | if not os.path.exists(folder): 49 | print('The folder path entered does not exists.') 50 | sys.exit() 51 | else: 52 | folderSize = getSize(folder) 53 | 54 | # If no files/folders found 55 | if large == {}: 56 | print(f'There are no files or folders with size greater than {size} \ 57 | bytes.') 58 | 59 | # Print paths with size 60 | else: 61 | print(f'The files and folders with size greater than {size} are:') 62 | for path in large.keys(): 63 | if os.path.isfile(path): 64 | print(f'The size of the file {path} is: {large[path]} bytes.') 65 | elif os.path.isdir(path): 66 | print(f'The size of the folder {path} is: {large[path]} bytes.') 67 | --------------------------------------------------------------------------------