Price: £3
Price: £9
Price: £7
Price:
Pen that can shoot water with pressure
Price: £3.99
Your own customized website
Price: £20
Fully customized
Price: £10
Price: £2.99
Sab Private Server
Price: £1.20/month
Price: £2
# ================================================================
# PART A — IMPORTS, GLOBALS, SIMPLE STORAGE (FIXED)
# ================================================================
import socket
import pickle
import tkinter as tk
from tkinter import filedialog, messagebox
import os
from PIL import Image, ImageTk
# ----------------------------
# Basic UI colors
# ----------------------------
BG = "#111111"
TXT = "white"
BTN = "#222222"
BTN_HOVER = "#4444aa"
# ----------------------------
# In-memory chat history
# ----------------------------
chat_history = []
# ----------------------------
# Data folders
# ----------------------------
os.makedirs("feed", exist_ok=True)
os.makedirs("pfp", exist_ok=True)
# ----------------------------
# USER DATABASE FIX (IMPORTANT)
# ----------------------------
USER_DB_FILE = "users.pkl"
# Try loading saved users
try:
with open(USER_DB_FILE, "rb") as f:
user_db = pickle.load(f)
# If corrupted, replace
if not isinstance(user_db, dict):
user_db = {}
except:
user_db = {} # Start fresh if file missing or unreadable
def save_users():
with open(USER_DB_FILE, "wb") as f:
pickle.dump(user_db, f)
# ----------------------------
# Networking (LAN)
# ----------------------------
PORT = 5050
def get_local_ip():
"""Returns LAN WiFi IP."""
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
except:
ip = "127.0.0.1"
finally:
s.close()
return ip
LOCAL_IP = get_local_ip()
IS_SERVER = False
server_socket = None
client_socket = None
clients = [] # connected clients (server only)
# ================================================================
# PART B — NON-BLOCKING LAN SERVER (NO THREADS)
# ================================================================
def start_server():
"""Start server if no one else is using the port."""
global server_socket, IS_SERVER
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setblocking(False)
try:
server_socket.bind((LOCAL_IP, PORT))
server_socket.listen(5)
IS_SERVER = True
print(f"[SERVER] Running at {LOCAL_IP}:{PORT}")
except:
print("[SERVER] Another device is already the server.")
server_socket = None
IS_SERVER = False
def server_check_messages(root):
"""Accept clients + receive messages using non-blocking mode."""
global clients, chat_history
if IS_SERVER:
# --------------------------
# Accept new clients
# --------------------------
try:
conn, addr = server_socket.accept()
conn.setblocking(False)
clients.append(conn)
print("[SERVER] Client joined:", addr)
except BlockingIOError:
pass
# --------------------------
# Receive messages
# --------------------------
dead = []
for conn in clients:
try:
data = conn.recv(4096)
if data:
msg = pickle.loads(data)
chat_history.append(msg)
update_chat_windows(msg)
# broadcast to all clients
for c in clients:
if c != conn:
try:
c.sendall(pickle.dumps(msg))
except:
dead.append(c)
except BlockingIOError:
pass
except:
dead.append(conn)
# Remove dead sockets
for c in dead:
if c in clients:
clients.remove(c)
# schedule again
root.after(100, lambda: server_check_messages(root))
# ================================================================
# PART C — NON-BLOCKING LAN CLIENT
# ================================================================
def connect_to_server():
"""Try connecting to server (another device)."""
global client_socket, IS_SERVER
if IS_SERVER:
print("[CLIENT] This device IS the server.")
return
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.setblocking(False)
try:
client_socket.connect((LOCAL_IP, PORT))
except BlockingIOError:
pass
except:
print("[CLIENT] No server found.")
client_socket = None
return
print("[CLIENT] Connected to server!")
def client_check_messages(root):
"""Receive server messages without blocking."""
global client_socket, chat_history
if client_socket is not None:
try:
data = client_socket.recv(4096)
if data:
msg = pickle.loads(data)
chat_history.append(msg)
update_chat_windows(msg)
except BlockingIOError:
pass
except:
client_socket = None
root.after(100, lambda: client_check_messages(root))
# ================================================================
# PART D — LOGIN + REGISTER (NO SEPARATE REGISTER WINDOW)
# ================================================================
CURRENT_USER = None
USER_DB_FILE = "users.pkl"
# Load or create user database
try:
with open(USER_DB_FILE, "rb") as f:
user_db = pickle.load(f)
except:
user_db = {} # empty database
def save_users():
with open(USER_DB_FILE, "wb") as f:
pickle.dump(user_db, f)
def open_login_window(root):
login = tk.Toplevel(root)
login.title("Login / Register")
login.geometry("420x330")
login.configure(bg=BG)
login.resizable(False, False)
tk.Label(
login,
text="Login / Register",
fg="white",
bg=BG,
font=("Segoe UI", 26, "bold")
).pack(pady=15)
# Username
tk.Label(
login,
text="Username:",
fg="white",
bg=BG,
font=("Segoe UI", 14)
).pack()
user_entry = tk.Entry(login, font=("Segoe UI", 14))
user_entry.pack(pady=5)
# Password
tk.Label(
login,
text="Password:",
fg="white",
bg=BG,
font=("Segoe UI", 14)
).pack()
pass_entry = tk.Entry(login, font=("Segoe UI", 14), show="*")
pass_entry.pack(pady=5)
# ----------------------------
# LOGIN FUNCTION
# ----------------------------
def do_login():
global CURRENT_USER
username = user_entry.get().strip()
password = pass_entry.get().strip()
if username not in user_db:
messagebox.showerror("Login Failed", "Account does not exist!")
return
if user_db[username] != password:
messagebox.showerror("Login Failed", "Incorrect password.")
return
CURRENT_USER = username
login.destroy()
open_dashboard(root)
# ----------------------------
# REGISTER FUNCTION
# ----------------------------
def do_register():
username = user_entry.get().strip()
password = pass_entry.get().strip()
if not username or not password:
messagebox.showerror("Error", "Enter username and password.")
return
if username in user_db:
messagebox.showerror("Register Failed", "Username already exists!")
return
# Create new account
user_db[username] = password
save_users()
messagebox.showinfo("Success", "Account created! Now login.")
# ----------------------------
# Buttons
# ----------------------------
tk.Button(
login,
text="Login",
bg=BTN,
fg="white",
activebackground=BTN_HOVER,
width=14,
height=2,
command=do_login
).pack(pady=10)
tk.Button(
login,
text="Register",
bg=BTN,
fg="white",
activebackground=BTN_HOVER,
width=14,
height=2,
command=do_register
).pack()
# ================================================================
# PART E — DASHBOARD (ALL BUTTONS RESTORED)
# ================================================================
def open_dashboard(root):
dash = tk.Toplevel(root)
dash.title("Dashboard")
dash.geometry("950x550")
dash.configure(bg=BG)
dash.resizable(True, True)
tk.Label(
dash,
text=f"Welcome, {CURRENT_USER}",
fg="white",
bg=BG,
font=("Segoe UI", 28, "bold")
).pack(pady=25)
container = tk.Frame(dash, bg=BG)
container.pack()
left = tk.Frame(container, bg=BG)
right = tk.Frame(container, bg=BG)
left.grid(row=0, column=0, padx=60)
right.grid(row=0, column=1, padx=60)
# LEFT BUTTONS
tk.Button(left, text="Global Chat", width=22, height=2,
bg=BTN, fg="white", activebackground=BTN_HOVER,
command=lambda: open_chat_window(dash)).pack(pady=6)
tk.Button(left, text="Open Feed", width=22, height=2,
bg=BTN, fg="white", activebackground=BTN_HOVER,
command=open_feed_window).pack(pady=6)
tk.Button(left, text="Upload Media", width=22, height=2,
bg=BTN, fg="white", activebackground=BTN_HOVER,
command=open_upload_window).pack(pady=6)
tk.Button(left, text="Snake Game", width=22, height=2,
bg=BTN, fg="white", activebackground=BTN_HOVER,
command=open_snake_game).pack(pady=6)
# RIGHT BUTTONS
tk.Button(right, text="Change Profile Picture", width=22, height=2,
bg=BTN, fg="white", activebackground=BTN_HOVER,
command=open_pfp_window).pack(pady=6)
tk.Button(right, text="Minecraft Website", width=22, height=2,
bg=BTN, fg="white", activebackground=BTN_HOVER,
command=lambda: os.system("start https://example.com")).pack(pady=6)
tk.Button(right, text="Credits (Made by Hadi)", width=22, height=2,
bg=BTN, fg="white", activebackground=BTN_HOVER,
command=lambda: messagebox.showinfo("Credits", "Made by Hadi ❤️")).pack(pady=6)
tk.Button(right, text="Logout", width=22, height=2,
bg=BTN, fg="white", activebackground=BTN_HOVER,
command=lambda: (dash.destroy(), open_login_window(root))).pack(pady=6)
tk.Button(right, text="Exit Program", width=22, height=2,
bg=BTN, fg="white", activebackground=BTN_HOVER,
command=root.destroy).pack(pady=6)
# ================================================================
# PART F — CHAT WINDOW (REAL-TIME, NO THREADS)
# ================================================================
open_chat_windows = [] # stores all open text widgets
def update_chat_windows(msg):
"""Update EVERY chat window instantly when new message arrives."""
for log in open_chat_windows:
log.config(state="normal")
log.insert("end", f"{msg['user']}: {msg['text']}\n")
log.config(state="disabled")
log.see("end")
def open_chat_window(root):
chat_win = tk.Toplevel(root)
chat_win.title("Global Chat")
chat_win.geometry("650x550")
chat_win.configure(bg=BG)
chat_win.resizable(True, True)
tk.Label(
chat_win,
text="Global Chat",
fg="white",
bg=BG,
font=("Segoe UI", 22, "bold")
).pack(pady=10)
# SCROLLABLE CHAT LOG
frame = tk.Frame(chat_win, bg=BG)
frame.pack(fill="both", expand=True, padx=10, pady=10)
scrollbar = tk.Scrollbar(frame)
scrollbar.pack(side="right", fill="y")
log = tk.Text(
frame,
bg="#000000",
fg="white",
font=("Segoe UI", 12),
wrap="word",
state="disabled",
yscrollcommand=scrollbar.set
)
log.pack(side="left", fill="both", expand=True)
scrollbar.config(command=log.yview)
open_chat_windows.append(log)
# LOAD HISTORY
log.config(state="normal")
for msg in chat_history:
log.insert("end", f"{msg['user']}: {msg['text']}\n")
log.config(state="disabled")
log.see("end")
entry = tk.Entry(
chat_win,
font=("Segoe UI", 14),
bg="#222",
fg="white",
relief="flat",
insertbackground="white"
)
entry.pack(fill="x", padx=10, pady=10)
def send_msg(event=None):
text = entry.get().strip()
if not text:
return
msg = {"user": CURRENT_USER, "text": text}
chat_history.append(msg)
update_chat_windows(msg)
# Client → send to server
if client_socket:
try: client_socket.sendall(pickle.dumps(msg))
except: pass
# Server → broadcast
if IS_SERVER:
for c in clients:
try: c.sendall(pickle.dumps(msg))
except: pass
entry.delete(0, tk.END)
entry.bind("