├── .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 |
--------------------------------------------------------------------------------