andevs's picture
Update app.py
8a06730 verified
Raw
History Blame Contribute Delete
11.4 kB
"""
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)