125 lines
3.7 KiB
Python
125 lines
3.7 KiB
Python
|
|
from flask import Blueprint, request, jsonify
|
||
|
|
from datetime import datetime, timezone
|
||
|
|
import time
|
||
|
|
|
||
|
|
from models.state import (
|
||
|
|
messages,
|
||
|
|
room_users,
|
||
|
|
kicked_users,
|
||
|
|
room_owners,
|
||
|
|
banned_ips,
|
||
|
|
banned_usernames,
|
||
|
|
user_ips,
|
||
|
|
nuked_rooms,
|
||
|
|
)
|
||
|
|
|
||
|
|
chat_bp = Blueprint("chat", __name__)
|
||
|
|
|
||
|
|
|
||
|
|
@chat_bp.route("/chat", methods=["GET", "POST"])
|
||
|
|
def general_chat():
|
||
|
|
if request.method == "POST":
|
||
|
|
new_message = request.json.get("message")
|
||
|
|
if new_message:
|
||
|
|
messages.setdefault("global", []).append(
|
||
|
|
{"text": new_message, "timestamp": datetime.now(timezone.utc).isoformat()}
|
||
|
|
)
|
||
|
|
if len(messages["global"]) > 100:
|
||
|
|
messages["global"] = messages["global"][-100:]
|
||
|
|
return jsonify(messages.get("global", []))
|
||
|
|
|
||
|
|
|
||
|
|
@chat_bp.route("/chat/<room>", methods=["GET", "POST"])
|
||
|
|
def chat_room(room):
|
||
|
|
room = room.strip()
|
||
|
|
|
||
|
|
if request.method == "POST":
|
||
|
|
data = request.json
|
||
|
|
username = data.get("username")
|
||
|
|
text = data.get("text")
|
||
|
|
audio = data.get("audio")
|
||
|
|
user_ip = request.remote_addr
|
||
|
|
|
||
|
|
if (
|
||
|
|
user_ip in banned_ips
|
||
|
|
or username in banned_usernames
|
||
|
|
or (username in user_ips and user_ips[username] in banned_ips)
|
||
|
|
):
|
||
|
|
return jsonify({"error": "banned"}), 403
|
||
|
|
|
||
|
|
message = {
|
||
|
|
"username": username,
|
||
|
|
"text": text,
|
||
|
|
"audio": audio,
|
||
|
|
"timestamp": datetime.now(timezone.utc).isoformat(),
|
||
|
|
}
|
||
|
|
messages.setdefault(room, []).append(message)
|
||
|
|
if len(messages[room]) > 100:
|
||
|
|
messages[room] = messages[room][-100:]
|
||
|
|
|
||
|
|
since = request.args.get("since")
|
||
|
|
room_messages = messages.setdefault(room, [])
|
||
|
|
|
||
|
|
if since:
|
||
|
|
try:
|
||
|
|
since_time = datetime.fromisoformat(since)
|
||
|
|
new_msgs = [
|
||
|
|
m
|
||
|
|
for m in room_messages
|
||
|
|
if datetime.fromisoformat(m["timestamp"]) > since_time
|
||
|
|
]
|
||
|
|
return jsonify(new_msgs)
|
||
|
|
except ValueError:
|
||
|
|
pass # Ignore bad timestamp
|
||
|
|
|
||
|
|
return jsonify(room_messages)
|
||
|
|
|
||
|
|
|
||
|
|
@chat_bp.route("/chat/<room>/users", methods=["GET", "POST"])
|
||
|
|
def room_user_list(room):
|
||
|
|
room = room.strip()
|
||
|
|
|
||
|
|
# Check if room is temporarily locked (nuked)
|
||
|
|
if room in nuked_rooms:
|
||
|
|
if time.time() < nuked_rooms[room]:
|
||
|
|
return jsonify({"error": "Room is unavailable"}), 403
|
||
|
|
else:
|
||
|
|
nuked_rooms.pop(room, None)
|
||
|
|
|
||
|
|
if request.method == "POST":
|
||
|
|
data = request.json
|
||
|
|
username = data.get("username")
|
||
|
|
if not username:
|
||
|
|
return jsonify({"error": "No username"}), 400
|
||
|
|
|
||
|
|
if username in kicked_users.get(room, set()):
|
||
|
|
return jsonify({"error": "Kicked from room"}), 403
|
||
|
|
|
||
|
|
room_users.setdefault(room, {})
|
||
|
|
if room not in room_owners and username not in room_users[room]:
|
||
|
|
room_owners[room] = username # First user becomes the owner
|
||
|
|
|
||
|
|
room_users[room][username] = datetime.now(timezone.utc).isoformat()
|
||
|
|
|
||
|
|
users = room_users.get(room, {})
|
||
|
|
response = {"users": list(users.keys())}
|
||
|
|
if room in room_owners:
|
||
|
|
response["owner"] = room_owners[room]
|
||
|
|
return jsonify(response)
|
||
|
|
|
||
|
|
|
||
|
|
@chat_bp.route("/chat/<room>/kick", methods=["POST"])
|
||
|
|
def kick_user(room):
|
||
|
|
data = request.json
|
||
|
|
owner = data.get("owner")
|
||
|
|
target = data.get("target")
|
||
|
|
|
||
|
|
if not owner or not target:
|
||
|
|
return jsonify({"error": "Missing owner or target"}), 400
|
||
|
|
if room_owners.get(room) != owner:
|
||
|
|
return jsonify({"error": "Not authorized"}), 403
|
||
|
|
|
||
|
|
kicked_users.setdefault(room, set()).add(target)
|
||
|
|
room_users.get(room, {}).pop(target, None)
|
||
|
|
return jsonify({"kicked": target})
|