Python

The first thing I decided to learn was Python programming. The reason the choice landed on Python was mainly due to the vast number of recurses out there for beginners and experienced programmers. This made it easy to get started with beginner tutorials online, and then slowly progress with more advanced stuff. Below are some Python projects I have made.

Network Device Scanner

Discover active devices on your local network with this Python script! Utilizing Scapy, this tool sends an ARP request over the network to identify connected devices within a specified IP range. It broadcasts to all devices, collects responses, and displays each device's IP address and hostname (when available via reverse DNS lookup). This script is ideal for quickly checking connected devices, monitoring network status, or learning about ARP scanning techniques.

Download the full script from GitHub here.


    import scapy.all as scapy
    import socket

    # Create an ARP request.
    request = scapy.ARP() 
    request.pdst = '192.168.86.1/24'

    # Create an Ethernet broadcast.
    broadcast = scapy.Ether()
    broadcast.dst = 'ff:ff:ff:ff:ff:ff'

    # Combine ARP request with Ethernet broadcast.
    request_broadcast = broadcast / request

    # Send the request and capture the responses.
    clients = scapy.srp(request_broadcast, timeout=10, verbose=1)[0]

    # Iterate over each client and print only IP and hostname.
    for element in clients:
        ip = element[1].psrc
        try:
            # Try to get the hostname using reverse DNS lookup.
            hostname = socket.gethostbyaddr(ip)[0]
        except socket.herror:
            # If the hostname could not be resolved, default to 'Unknown'.
            hostname = "Unknown"
        
        # Print the IP and hostname of active devices on the network.
        print(f"{ip}	{hostname}")
  

Convert Decimal to Binary

Easily convert any number between 0 and 255 to binary with this interactive Python script! Simply input a decimal number, and the program validates it to ensure it's within the allowed range. Once validated, the script calculates the binary equivalent by breaking down the number into its binary components using the powers of two. The result is displayed as a list of 1's and 0's, representing the binary format of your chosen decimal number. This tool is perfect for learning binary conversions or for quick and accurate calculations!

Download the full script from GitHub here.


    # setting a non-valid number as the default value.
    num = -1

    # Using a while loop to aske the user for the number they want to convert.
    # This while loop will keep asking the userfor a number until the user enter a valid number.
    while num < 0 or num > 255:
        # Asking the user for the number they want to convert.
        num = int(input("Enter a number between 0 and 255 to convert to binary: "))
        # Checking if the input from the user is a valid number.
        if num > 0 and num < 255:
            print(" ")
        else:
            print("Not a valid number. Please enter a number between 0 and 255.")

    # Creating the standard binary list used to convert the users number.
    help_list = [128, 64, 32, 16, 8, 4, 2, 1]

    # Creating an empty list to be filled in, creating the binary number
    binary_list = [0, 0, 0, 0, 0, 0, 0, 0]

    # Creating a for loop the will convert the numeric number into a binary represented by a list.
    for i in range(8):
        if num >= help_list[i]:
            num = num - help_list[i]
            binary_list[i] = 1

    # Printing the result.
    print(binary_list)
  

Text to Morse Code Converter

Translate any text to Morse code with this convenient Python script! The program uses a predefined dictionary to map letters, numbers, and common punctuation symbols to their Morse code equivalents. Simply enter a sentence, and the script will convert each character to Morse code and display the result as a list. This tool is ideal for learning Morse code or experimenting with text encoding for communications.

Download the full script from GitHub here.


    # First a dictionary is created to translate a regular string into morse code.
    Translator = {
    "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": "_ _..", " ": "/", "0": "_ _ _ _ _", "1": "._ _ _ _", "2": ".._ _ _", "3": "..._ _", "4": "...._", "5": ".....", "6": "_....", "7": "_ _...", "8": "_ _ _..", "9": "_ _ _ _.", ".": "._._._", ",": "_ _.._ _", "?": ".._ _.."
    }

    # Asking the user for the string to translate.
    string = input("Write the sentence you want translated into morse code: ").upper()

    # Creating an empty list to add the translated letters to.
    Morse = []

    # Looping through each letter in the string, translating the letter into morse code.
    for i in range(len(string)):
        letter = Translator[string[i]]
        Morse.append(letter)

    # Printing the translated string.
    print(Morse)
  

Automated Email Sender

Easily send automated emails with this Python script! By inputting your email credentials, recipient email, subject, and message content, this program allows you to send emails securely via Gmail's SMTP server. After setting your Gmail address and an app-specific password, the script will format your email, establish a secure connection, and send the message directly to the recipient. Ideal for automating notifications, reminders, or sending custom messages programmatically, this tool simplifies the email-sending process in Python.

Download the full script from GitHub here.


    from email.message import EmailMessage
    import ssl
    import smtplib

    # Input the Email address of the sender, this would typically be your own Email address.
    sender = ""
    # Here past the password generated from your Google account as instructed to in the "read me" file.
    password = ""

    # Input the Email address of the receiver.
    receiver = ""

    # Here write the subject of the Email. This will appear in the Subject field of the Email.
    subject = ""
    # Here you write the Email itself.
    body = """

    """

    email = EmailMessage()
    email["From"] = sender
    email["To"] = receiver
    email["subject"] = subject
    email.set_content(body)

    context = ssl.create_default_context()

    with smtplib.SMTP_SSL("smtp.gmail.com", 465, context=context) as smtp:
        smtp.login(sender, password)
        smtp.sendmail(sender, receiver, email.as_string())
  

Hangman Game

Play a classic game of Hangman with this interactive Python script! This program randomly selects a word from a provided list, allowing players to guess letters one at a time to reveal the hidden word. Players have a limited number of lives, and each incorrect guess decreases their chances. Unique features include automatic handling of spaces or hyphens in the word and a fun visual animation indicating remaining lives. This game is perfect for challenging yourself with word puzzles or for adding an enjoyable coding project to your repertoire.

Download the full script from GitHub here.


    import random
    import string

    # Here I import the list of words from the file words.py
    from Words import words
    from Animation import animation

    # Here I define a fuction that will go into the long list of word in the "words.py" file and randomly pick one
    def get_word(words):
        word = random.choice(words)

        return word.upper()

    def hangman():
        word = get_word(words) # Here I assign the selected word from the get_word fuction to the word in the game
        word_letters = set(word) # Here I break the selected word into seperate letters and put them into a list
        alphabet = set(string.ascii_uppercase)
        used_letters = set() # Here I create an empty list to store the letters the user has guesses during the game

        # Here I check if the word chosen by the computer contains either a "-" or a " ". If thats the case I have the computer 'guess' for those. That way they are automatically put into the solution, and the user only have to guess letters, and not symbols
        if "-" in word:
                auto_guess = "-"
                used_letters.add(auto_guess)
                word_letters.remove(auto_guess)
        elif " " in word:
            auto_guess = " "
            used_letters.add(auto_guess)
            word_letters.remove(auto_guess)

        # Here I set the amount of lives I want to give the user playing the game
        lives = 11

        while len(word_letters) > 0 and lives > 0:

            animation(lives)

            # Here I break the list containing the guessed letters up into a string where each letter is seperated by a space
            print("Letters already gussed: ", " ".join(used_letters))

            # Here I print the progress of the user
            word_list = [letter if letter in used_letters else "_" for letter in word]
            print("Current word: ", " ".join(word_list))

            # Now I ask the user to guess a letters
            user_letter = input("Guess a letter: ").upper()
            if user_letter in alphabet - used_letters:
                used_letters.add(user_letter)
                if user_letter in word_letters:
                    word_letters.remove(user_letter)
                else:
                    lives = lives - 1
            elif user_letter in used_letters:
                print("You have already guessed this letter, please try another letter.")
            else:
                print("Invalid character. Please enter a valid character")

        if lives == 0:
            animation(lives)
            print("The word was " + word + ".")
        else:
            print("You guessed the word", word, "!!!!!")

    # Here I call an instance of the game for the player to play
    hangman()
  

Sudoku Solver

Solve any 9x9 Sudoku puzzle with this efficient Python script! Designed to fill in empty spaces with valid numbers, the script ensures that each number placement follows Sudoku rules by checking rows, columns, and 3x3 sub-grids. Using a backtracking algorithm, it explores potential solutions and outputs the completed board if a solution is found. This script is perfect for puzzle enthusiasts, coders interested in algorithms, or anyone looking to automate Sudoku solving.

Download the full script from GitHub here.


    # This function checkes to see if the chosen number is a valid or not.
    def valid_num(board, row, col, num):
        # Checking the row for the same number.
        for i in range(9):
            if board[row][i] == num:
                return False
            
        # Checking the column for the same number.
        for i in range(9):
            if board[i][col] == num:
                return False
            
        # Finding the the 3x3 square in witch the number belongs.
        square_col = col - col % 3
        square_row = row - row % 3

        # Now checking if the square for the same number.
        for i in range(3):
            for j in range(3):
                if board[square_row + i][square_col + j] == num:
                    return False
                
        # If all these check passes then the number is valid.
        return True

    # This function will search for a solution to the sudoku, and return it when found.
    def solve(board, row, col):
        # Checking to see if we have reached the end, and all fields have been assigned a value between 1 and 9.
        if col == 9:
            if row == 8:
                return True
            row += 1
            col = 0

        if board[row][col] > 0:
            return solve(board, row, col + 1)
        
        for num in range(1, 10):
            if valid_num(board, row, col, num):
                board[row][col] = num
                if solve(board, row, col + 1):
                    return True
            board[row][col] = 0

        return False

    def run_solve():
        if solve(board, 0, 0):
            for i in range(9):
                for j in range(9):
                    print(board[i][j], end=" ")
                print()
        else:
            print("No solution found.")

    board = [[1, 0, 8, 5, 3, 0, 6, 0, 0],
            [0, 2, 0, 0, 0, 1, 0, 0, 0],
            [0, 4, 0, 0, 0, 0, 0, 0, 8],
            [8, 0, 5, 0, 0, 3, 0, 0, 9],
            [0, 0, 4, 0, 0, 0, 0, 0, 0],
            [0, 0, 0, 0, 9, 0, 2, 0, 0],
            [3, 0, 9, 0, 0, 5, 0, 0, 2],
            [0, 0, 0, 6, 0, 0, 0, 7, 0],
            [0, 1, 0, 0, 0, 0, 0, 0, 0]]
  

Automated Backup and Google Drive Management Script

This script provides a seamless solution for creating and managing backups of your local files, storing them securely on Google Drive, and automatically organizing your cloud storage. Key features include:

  • Automatic File Archiving: It archives selected files and folders into a single zip file, labeled with the current date for easy tracking.
  • Google Drive Integration: The script securely uploads the archived zip files to a designated folder on Google Drive, ensuring that your data is always accessible in the cloud.
  • Smart File Management: To keep your Google Drive organized, the script maintains a maximum of five recent backup files in the specified folder, automatically deleting older ones as new backups are uploaded.
  • Effortless Cleanup: Once the file is uploaded, the script removes the local zip archive, helping to free up space on your device.

Ideal for users looking for a hands-free, reliable way to back up important files regularly, this script handles data validation and refreshes authentication automatically. With minimal setup, you can enjoy peace of mind, knowing that your files are protected and accessible whenever needed.

Download the full script from GitHub here.


    # Import the necessary libraries
    import os
    import os.path

    # Import the necessary packages
    import zipfile
    from datetime import datetime
    from googleapiclient.discovery import build
    from googleapiclient.errors import HttpError
    from googleapiclient.http import MediaFileUpload
    from google.oauth2.credentials import Credentials
    from google.auth.transport.requests import Request
    from google_auth_oauthlib.flow import InstalledAppFlow

    # Get the current date in YYYY-MM-DD format
    current_date = datetime.now().strftime("%Y-%m-%d")

    def validation():
        # Define the scopes
        SCOPES = ['https://www.googleapis.com/auth/drive']

        # Setting the credentials to None to check if the credentials are already present
        global creds
        creds = None

        # Checking if the token.json file is present
        if os.path.exists('token.json'):
            creds = Credentials.from_authorized_user_file('token.json', SCOPES)

        # Checking if the credentials are valid
        if not creds or not creds.valid:
            if creds and creds.expired and creds.refresh_token:
                creds.refresh(Request())
            else:
                flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
                creds = flow.run_local_server(port=0)

            with open('token.json', 'w') as token:
                token.write(creds.to_json())

    # Define the function to archive the files
    def archive_file(folder_path):
        # Get the path to the Documents folder
        documents_folder = os.path.join(os.path.expanduser("~"), "Documents")
        
        # Create the name of the zip file
        zip_filename = os.path.join(documents_folder, f"{current_date}.zip")
        
        # Create a zip file to store the backup
        with zipfile.ZipFile(zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
            # Walk through the folder and add the files to the zip file
            for root, dirs, files in os.walk(folder_path):
                for file in files:
                    # Getting the full paths to the files to be added to the zip file
                    file_path = os.path.join(root, file)
                    # Checking if the file is not the zip file itself
                    if file_path != f"{folder_path}{current_date}":
                        zipf.write(file_path, os.path.relpath(file_path, folder_path))

    # Define the function to upload the file to Google Drive
    def upload_file():

        validation()

        try:
            # Building the service
            service = build('drive', 'v3', credentials=creds)

            # Checking if the folder is already present
            response = service.files().list(
                q = "name = 'Back-up' and mimeType = 'application/vnd.google-apps.folder'",
                spaces = 'drive'
            ).execute()

            # If the folder is not present, create a new folder
            if not response['files']:
                file_metadata = {
                    'name': 'Back-up',
                    'mimeType': 'application/vnd.google-apps.folder'
                }

                file = service.files().create(body = file_metadata, fields = 'id').execute()

                folder_id = file.get('id')
            
            else:
                folder_id = response['files'][0].get('id')

            # Specify the file to upload
            file = f'{current_date}.zip'

            # Define the file metadata
            file_metadata = {
                'name': file,
                'parents': [folder_id]
            }

            # Upload the file
            media = MediaFileUpload(f'{os.path.expanduser("~")}/Documents/{file}', mimetype='application/octet-stream')
            upload_file = service.files().create(body=file_metadata, media_body=media, fields='id').execute()

        except HttpError as error:
            print(f'An error occurred: {error}')

    # Define the function to keep the number of files to a maximum of 5 in the Google Drive folder
    def keep_files():
        
        validation()

        try:
            # Building the service
            service = build('drive', 'v3', credentials=creds)

            # Checking if the folder is already present
            response = service.files().list(
                q = "name = 'Back-up' and mimeType = 'application/vnd.google-apps.folder'",
                spaces = 'drive'
            ).execute()

            folder_id = response['files'][0].get('id')

            # Get the list of files in the folder
            results = service.files().list(
                q = f"'{folder_id}' in parents",
                spaces = 'drive',
                fields = 'nextPageToken, files(id, name)',
                pageToken = None
            ).execute()

            # Get the list of files
            files = results.get('files', [])

            # Check if the number of files is greater than 5
            if len(files) > 5:
                # Sort the files by name
                files.sort(key = lambda x: x['name'])

                # Delete the oldest file
                service.files().delete(fileId = files[len(files) - 1]['id']).execute()

        except HttpError as error:
            print(f'An error occurred: {error}')

    # Define the function to delete the file after uploading
    def delete_file(zip_filename):
        # Delete the zip file
        os.remove(zip_filename)

    # Defining the folder to be archived
    folder_to_zip = f'{os.path.expanduser("~")}/Documents/BackupFolder'
    # Calling the function to archive the files
    archive_file(folder_to_zip)

    # Calling the function to upload the file to Google Drive
    upload_file()

    # Calling the function to keep the number of files to a maximum of 5 in the Google Drive folder
    keep_files()

    # Define the path to the zip file
    zip_file_path = os.path.join(os.path.expanduser("~"), "Documents", f"{datetime.now().strftime('%Y-%m-%d')}.zip")
    # Calling the function to delete the file after uploading
    delete_file(zip_file_path)