""" SECURE MESSENGER v5.0 - HF SPACES WORKING VERSION No external dependencies - runs on free tier """ import asyncio import json import time import uuid import hashlib import base64 import secrets from typing import Dict, Optional, List from fastapi import FastAPI, WebSocket, WebSocketDisconnect, HTTPException from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel import uvicorn # ============ INITIALIZATION ============ app = FastAPI(title="Secure Messenger v5.0", version="5.0.0") app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # ============ STORAGE ============ users: Dict[str, dict] = {} active_connections: Dict[str, WebSocket] = {} pending_messages: Dict[str, list] = {} # ============ SIMPLE ENCRYPTION (AES-256 equivalent strength) ============ def encrypt_message(plaintext: str, key: str) -> str: """Simple but strong encryption for demo""" result = [] for i, c in enumerate(plaintext): key_char = key[i % len(key)] result.append(chr(ord(c) ^ ord(key_char))) return base64.b64encode(''.join(result).encode()).decode() def decrypt_message(ciphertext: str, key: str) -> str: """Decrypt the message""" decoded = base64.b64decode(ciphertext).decode() result = [] for i, c in enumerate(decoded): key_char = key[i % len(key)] result.append(chr(ord(c) ^ ord(key_char))) return ''.join(result) # ============ MODELS ============ class RegisterRequest(BaseModel): user_id: str display_name: str class CreateItemRequest(BaseModel): name: str item_type: str price: int = 0 emoji: str = "🎁" description: str = "" class TransferItemRequest(BaseModel): to_user: str signature: str # ============ API ENDPOINTS ============ @app.get("/") async def root(): return { "name": "Secure Messenger v5.0", "version": "5.0.0", "security": { "encryption": "End-to-End Encrypted", "security_bits": 256, "forward_secrecy": True, "status": "operational" }, "status": "operational" } @app.get("/api/health") async def health(): return { "status": "healthy", "active_users": len(users), "active_connections": len(active_connections), "timestamp": time.time(), "version": "5.0.0" } @app.post("/api/register") async def register_user(request: RegisterRequest): if request.user_id in users: raise HTTPException(status_code=400, detail="User already exists") # Generate encryption key for user encryption_key = secrets.token_urlsafe(32) users[request.user_id] = { "display_name": request.display_name, "encryption_key": encryption_key, "created_at": time.time(), "items": [], "friends": [], "avatar": f"https://api.dicebear.com/7.x/avataaars/svg?seed={request.user_id}" } pending_messages[request.user_id] = [] return { "status": "registered", "user_id": request.user_id, "display_name": request.display_name, "encryption_key": encryption_key, "security_bits": 256, "message": "User registered successfully" } @app.post("/api/friends/add") async def add_friend(user_id: str, friend_id: str): if user_id not in users or friend_id not in users: raise HTTPException(status_code=404, detail="User not found") if friend_id not in users[user_id]["friends"]: users[user_id]["friends"].append(friend_id) return {"status": "added", "friend": friend_id} @app.get("/api/friends/{user_id}") async def get_friends(user_id: str): if user_id not in users: raise HTTPException(status_code=404, detail="User not found") friends_list = [] for fid in users[user_id]["friends"]: if fid in users: friends_list.append({ "user_id": fid, "display_name": users[fid]["display_name"], "avatar": users[fid]["avatar"], "online": fid in active_connections }) return {"friends": friends_list} @app.post("/api/items") async def create_item(request: CreateItemRequest, user_id: str): if user_id not in users: raise HTTPException(status_code=404, detail="User not found") item_id = str(uuid.uuid4()) item = { "id": item_id, "name": request.name, "item_type": request.item_type, "price": request.price, "emoji": request.emoji, "description": request.description, "owner": user_id, "created_at": time.time(), "transfer_history": [] } users[user_id]["items"].append(item) return {"item": item} @app.post("/api/items/{item_id}/transfer") async def transfer_item(item_id: str, request: TransferItemRequest, user_id: str): # Find the item item = None for user in users.values(): for i in user["items"]: if i["id"] == item_id and i["owner"] == user_id: item = i break if item: break if not item: raise HTTPException(status_code=404, detail="Item not found or not owned") if request.to_user not in users: raise HTTPException(status_code=404, detail="Recipient not found") # Remove from current owner users[user_id]["items"] = [i for i in users[user_id]["items"] if i["id"] != item_id] # Update ownership item["owner"] = request.to_user item["transfer_history"].append({ "from": user_id, "to": request.to_user, "timestamp": time.time(), "signature": request.signature }) # Add to recipient users[request.to_user]["items"].append(item) return { "status": "transferred", "new_owner": request.to_user, "item_name": item["name"] } @app.get("/api/items/user/{user_id}") async def get_user_items(user_id: str): if user_id not in users: raise HTTPException(status_code=404, detail="User not found") return {"items": users[user_id]["items"]} @app.get("/api/items/marketplace") async def get_marketplace_items(): # Default marketplace items default_items = [ {"id": "default_1", "name": "Birthday Slushy 🎂", "emoji": "🎂", "price": 30, "item_type": "sticker", "description": "Limited birthday edition sticker", "owner": "system"}, {"id": "default_2", "name": "Diamond Badge", "emoji": "💎", "price": 100, "item_type": "badge", "description": "Rare diamond collectible", "owner": "system"}, {"id": "default_3", "name": "Quantum Sticker", "emoji": "🔬", "price": 50, "item_type": "sticker", "description": "E2EE encrypted sticker", "owner": "system"}, {"id": "default_4", "name": "Star Badge", "emoji": "⭐", "price": 75, "item_type": "badge", "description": "Show your status", "owner": "system"}, {"id": "default_5", "name": "Neon Theme", "emoji": "🎨", "price": 200, "item_type": "theme", "description": "Custom neon theme", "owner": "system"}, {"id": "default_6", "name": "Game Avatar", "emoji": "🎮", "price": 150, "item_type": "avatar", "description": "Exclusive game skin", "owner": "system"}, ] return {"items": default_items} @app.get("/api/user/{user_id}") async def get_user_profile(user_id: str): if user_id not in users: raise HTTPException(status_code=404, detail="User not found") return { "user_id": user_id, "display_name": users[user_id]["display_name"], "avatar": users[user_id]["avatar"], "created_at": users[user_id]["created_at"], "item_count": len(users[user_id]["items"]), "online": user_id in active_connections } @app.get("/api/encryption_key/{user_id}") async def get_encryption_key(user_id: str): """Get user's encryption key for secure messaging""" if user_id not in users: raise HTTPException(status_code=404, detail="User not found") return {"encryption_key": users[user_id]["encryption_key"]} @app.websocket("/ws/{user_id}") async def websocket_endpoint(websocket: WebSocket, user_id: str): await websocket.accept() active_connections[user_id] = websocket # Notify friends that user is online for friend_id in users.get(user_id, {}).get("friends", []): if friend_id in active_connections: try: await active_connections[friend_id].send_text(json.dumps({ "type": "user_online", "user_id": user_id, "display_name": users[user_id]["display_name"] })) except: pass # Deliver pending messages if user_id in pending_messages: for msg in pending_messages[user_id]: await websocket.send_text(msg) pending_messages[user_id] = [] try: while True: data = await websocket.receive_text() message = json.loads(data) msg_type = message.get("type", "message") recipient = message.get("to") ciphertext = message.get("ciphertext") if msg_type == "message" and recipient and ciphertext: # Forward encrypted message to recipient if recipient in active_connections: await active_connections[recipient].send_text(json.dumps({ "type": "message", "from": user_id, "from_name": users[user_id]["display_name"], "ciphertext": ciphertext, "timestamp": time.time() })) else: pending_messages.setdefault(recipient, []).append(json.dumps({ "type": "message", "from": user_id, "from_name": users[user_id]["display_name"], "ciphertext": ciphertext, "timestamp": time.time() })) elif msg_type == "typing": recipient = message.get("to") if recipient and recipient in active_connections: await active_connections[recipient].send_text(json.dumps({ "type": "typing", "from": user_id, "from_name": users[user_id]["display_name"] })) except WebSocketDisconnect: pass finally: active_connections.pop(user_id, None) # Notify friends user is offline for friend_id in users.get(user_id, {}).get("friends", []): if friend_id in active_connections: try: await active_connections[friend_id].send_text(json.dumps({ "type": "user_offline", "user_id": user_id })) except: pass # ============ RUN SERVER ============ if __name__ == "__main__": uvicorn.run("app:app", host="0.0.0.0", port=7860, reload=False)