v7: file storage limits - 1MB per file, 50MB total, FIFO eviction
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
31
chat.py
31
chat.py
@@ -25,16 +25,29 @@ import html
|
||||
import urllib.parse
|
||||
|
||||
PORT = 9999
|
||||
VERSION = "6"
|
||||
VERSION = "7"
|
||||
TUNNEL_TARGET = ("185.208.174.152", 22)
|
||||
MAX_UPLOAD = 10 * 1024 * 1024 # 10 MB
|
||||
MAX_FILE_SIZE = 1 * 1024 * 1024 # 1 MB per file
|
||||
MAX_TOTAL_STORAGE = 50 * 1024 * 1024 # 50 MB total
|
||||
|
||||
# ── Server ──────────────────────────────────────────────────────────────
|
||||
|
||||
clients: dict[asyncio.StreamWriter, str] = {} # TCP clients
|
||||
sse_queues: list[asyncio.Queue] = [] # web clients
|
||||
history: list[dict] = []
|
||||
uploaded_files: dict[str, bytes] = {} # file_id -> raw bytes
|
||||
uploaded_files: dict[str, bytes] = {} # file_id -> raw bytes (insertion order)
|
||||
total_file_bytes = 0
|
||||
|
||||
|
||||
def store_file(file_id: str, data: bytes):
|
||||
"""Store a file, evicting oldest files if total storage exceeds limit."""
|
||||
global total_file_bytes
|
||||
uploaded_files[file_id] = data
|
||||
total_file_bytes += len(data)
|
||||
while total_file_bytes > MAX_TOTAL_STORAGE and uploaded_files:
|
||||
oldest_id = next(iter(uploaded_files))
|
||||
total_file_bytes -= len(uploaded_files.pop(oldest_id))
|
||||
|
||||
|
||||
|
||||
async def broadcast(msg: dict):
|
||||
@@ -481,9 +494,9 @@ async def handle_http(reader, writer, first_line):
|
||||
if file_entry and file_entry[0]:
|
||||
filename = file_entry[0]
|
||||
file_data = file_entry[1]
|
||||
if len(file_data) <= MAX_UPLOAD:
|
||||
if len(file_data) <= MAX_FILE_SIZE:
|
||||
file_id = hashlib.sha256(file_data + str(time.time()).encode()).hexdigest()[:16]
|
||||
uploaded_files[file_id] = file_data
|
||||
store_file(file_id, file_data)
|
||||
await broadcast({
|
||||
"ts": time.time(), "user": name,
|
||||
"text": f"[file: {filename}]",
|
||||
@@ -577,8 +590,10 @@ async def handle(reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
|
||||
pkt = json.loads(line)
|
||||
if pkt.get("type") == "file":
|
||||
file_data = base64.b64decode(pkt["data"])
|
||||
if len(file_data) > MAX_FILE_SIZE:
|
||||
continue
|
||||
file_id = hashlib.sha256(file_data + str(time.time()).encode()).hexdigest()[:16]
|
||||
uploaded_files[file_id] = file_data
|
||||
store_file(file_id, file_data)
|
||||
await broadcast({
|
||||
"ts": time.time(), "user": name,
|
||||
"text": f"[file: {pkt['filename']}]",
|
||||
@@ -693,8 +708,8 @@ class ChatClient:
|
||||
self.messages.append((f" *** file not found: {filepath}", CP_SYSTEM))
|
||||
return
|
||||
size = os.path.getsize(filepath)
|
||||
if size > MAX_UPLOAD:
|
||||
self.messages.append((f" *** file too large ({size} bytes, max {MAX_UPLOAD})", CP_SYSTEM))
|
||||
if size > MAX_FILE_SIZE:
|
||||
self.messages.append((f" *** file too large ({size} bytes, max {MAX_FILE_SIZE})", CP_SYSTEM))
|
||||
return
|
||||
with open(filepath, "rb") as f:
|
||||
data = f.read()
|
||||
|
||||
Reference in New Issue
Block a user