Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions Website Blocker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Website Blocker


## Overview

This project is a Python-based website blocker that restricts access to selected websites during specified working hours. It modifies the system's hosts file to redirect targeted domains to the local machine, effectively preventing access.

The script supports both Unix-based systems and Windows by dynamically detecting the operating system and selecting the appropriate hosts file.



## Features
* Cross-platform support (Linux, macOS, Windows)
* Time-based website blocking
* Interactive selection of popular websites
* Support for custom user-defined domains
* Automatic cleanup of hosts file on exit
* Error handling for insufficient permissions
* Modular, object-oriented design



## How It Works

The program modifies the system's hosts file by adding entries that redirect selected domains (e.g., facebook.com) to 127.0.0.1. This prevents the browser from reaching the actual website.

During non-working hours, the script restores the hosts file by removing those entries.

This could be very useful for system administrators, parents, or anyone looking to improve productivity by limiting access to distracting websites during certain hours.


![simple-diagram](pictures/class-diagram.png)



## Requirements

Python 3.x
Administrator/root privileges (required to modify the hosts file)


## Usage


1. Run the script

On Linux/macOS:
```bash
sudo python3 web_blocker.py
```

On Windows (run terminal as Administrator):
```bash
python web_blocker.py
```


2. Select websites
You will be prompted to:
* Choose from a list of common websites
* Or enter custom domains


3. Set working hours
Enter:
* Start hour (0–23)
* End hour (0–23)

If invalid input is provided, default values (8–16) will be used.



## Example

If you select:
* facebook.com
* youtube.com

The script will add entries like to the hosts file:
```bash
127.0.0.1 facebook.com
127.0.0.1 www.facebook.com
```

## Important Notes
* The script must be run with administrator/root privileges.
* Modifying the hosts file affects system-wide network behavior.
* The program automatically restores the hosts file when it is stopped using Ctrl+C.


## Improvements Over Original Implementation
* Refactored into an object-oriented design
* Added cross-platform compatibility
* Introduced interactive user input
* Improved timing responsiveness
* Added safe cleanup on exit
* Improved error handling and reliability



## Future Improvements
* Command-line arguments support
* Configuration file for persistent settings
* Logging system
* Unit testing


## License

This project is part of a public repository intended for educational and practical use.
169 changes: 169 additions & 0 deletions Website Blocker/cross-platform-web_blocker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import time
import platform
import signal
import sys
from datetime import datetime

# Flake8 and mypy check - clean code, type hints, and comments for clarity


class WebsiteBlocker:
def __init__(self,
websites: list,
start_hour: int = 8,
end_hour: int = 16) -> None:
self.websites = websites
self.start_hour = start_hour
self.end_hour = end_hour
self.redirect = "127.0.0.1"
self.hosts_path = self.get_hosts_path()

# ----------------------------
# OS handling
# ----------------------------
def get_hosts_path(self) -> str:
if platform.system() == "Windows":
return r"C:\Windows\System32\drivers\etc\hosts"
return "/etc/hosts"

# ----------------------------
# Time logic
# ----------------------------
def is_working_hours(self) -> bool:
now = datetime.now()
return self.start_hour <= now.hour < self.end_hour

# ----------------------------
# Blocking logic
# ----------------------------
def block_websites(self) -> None:
try:
with open(self.hosts_path, "r+") as file:
content = file.read()

for site in self.websites:
entry = f"{self.redirect} {site}"
if entry not in content:
file.write(entry + "\n")

except PermissionError:
print("❌ Please run the script as administrator/root")
sys.exit(1)

# ----------------------------
# Unblocking logic
# ----------------------------
def unblock_websites(self) -> None:
with open(self.hosts_path, "r+") as file:
lines = file.readlines()
file.seek(0)

for line in lines:
if not any(site in line for site in self.websites):
file.write(line)

file.truncate()

# ----------------------------
# Cleanup on exit
# ----------------------------
def cleanup(self, signum=None, frame=None) -> None:
print("\n🧹 Cleaning up hosts file...")
self.unblock_websites()
sys.exit(0)

# ----------------------------
# Main loop
# ----------------------------
def run(self) -> None:
print("🚀 Website Blocker running...")

# Handle Ctrl + C safely -> Delete /etc/hosts or
# "C:\Windows\System32\drivers\etc\hosts" entries after

signal.signal(signal.SIGINT, self.cleanup)

while True:
if self.is_working_hours():
print("🔒 Blocking websites...")
self.block_websites()
else:
print("🔓 Unblocking websites...")
print("⏰ Outside of working hours. Websites are accessible.")
self.unblock_websites()

time.sleep(5) # responsive check


# ----------------------------
# User input for websites
# ----------------------------
def get_user_websites() -> list:
options = {
"1": "facebook.com",
"2": "youtube.com",
"3": "instagram.com",
"4": "twitter.com",
"5": "gmail.com",
"6": "\033[33mCustom: Enter your own domains\033[0m",
}

print("- Select websites to block (comma separated):")
for key, value in options.items():
print(f"{key}) {value}")

print()
selected = []
choices = input("Your choice: ").split(",")
# Process selected options
for choice in choices:
choice = choice.strip()
if choice in options and choice != "6":
selected.append(options[choice])
selected.append("www." + options[choice])
elif choice == "6":
custom_sites = input("Enter custom domains (comma separated): ")
for site in custom_sites.split(","):
site = site.strip()
if site:
selected.append(site)
selected.append("www." + site)
else:
print(
f"\n\033[91mInvalid option: {choice}\n\
Please select from the list.\033[0m"
)
return []

return selected

return selected


# ----------------------------
# Entry point
# ----------------------------
if __name__ == "__main__":

print("\n\033[33mRun this script as administrator/root for \
it to work properly.\033[0m\n")

websites: list = []
while len(websites) == 0:
websites = get_user_websites()

if not websites:
print("No websites selected. Exiting.")
sys.exit(0)

try:
start = int(input("Enter the starting hour (0-23) for blocking \
(default 8): "))
end = int(input("Enter the ending hour (0-23) for blocking \
(default 16): "))
except ValueError:
print("Invalid input for hours. Using default values (8-16).")
start, end = 8, 16

blocker = WebsiteBlocker(websites, start, end)
blocker.run()
22 changes: 22 additions & 0 deletions Website Blocker/description.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
* I implemented my contribution by refactoring the original website blocker script into a modular, object-oriented design that improves structure, reliability, and usability.

* First, I introduced a WebsiteBlocker class to encapsulate the core functionality of the application. This class separates responsibilities into clear methods:

* is_working_hours() determines whether blocking should be active based on the current time
* block_websites() adds entries to the hosts file
* unblock_websites() safely restores the hosts file
* run() manages the main execution loop
* cleanup() ensures that any changes to the hosts file are reverted when the program is interrupted

To support multiple operating systems, I implemented a helper method get_hosts_path() that dynamically selects the correct hosts file path depending on whether the script is running on Windows or a Unix-based system. This builds on the cross-platform idea introduced in PR #563, but integrates it into a cleaner and more structured design.

I improved reliability by adding proper error handling when accessing the hosts file. Specifically, I handle PermissionError to prevent the program from crashing and instead provide a clear message to the user about running the script with administrator or root privileges.

I also enhanced the usability of the script by adding an interactive interface that allows users to select commonly blocked websites or input custom domains without modifying the source code. This makes the tool more practical for real-world usage.

Additionally, I improved the responsiveness of the script by replacing long fixed delays with shorter intervals (time.sleep(5)), allowing the program to react more quickly to changes in working hours.

Finally, I implemented a cleanup mechanism using signal handling (SIGINT) so that when the user stops the program (e.g., using Ctrl+C), any modifications made to the hosts file are automatically reverted. This addresses a key limitation in the original implementation, where stopping the script could leave the system in a blocked state.

Overall, my contribution significantly enhances the structure, reliability, and usability of the website blocker while maintaining the core functionality of blocking distracting websites during working hours.

61 changes: 0 additions & 61 deletions Website Blocker/mac/Website_Blocker.py

This file was deleted.

Binary file added Website Blocker/pictures/class-diagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 0 additions & 12 deletions Website Blocker/read.me

This file was deleted.