Stranger-Chat / app.py
NihalGazi's picture
Update app.py
2d37f90 verified
import uuid
from flask import Flask, render_template, request
from flask_socketio import SocketIO, join_room, leave_room, emit
app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins="*")
# In-memory matchmaking state
PROFILES = {} # sid -> profile dict
WAITING = [] # list of sids waiting
ROOMS = {} # room_id -> (sid1, sid2)
@app.route("/", methods=["GET"])
def index():
return render_template("index.html")
@app.route("/chat", methods=["GET"])
def chat():
return render_template("chat.html")
@socketio.on("find")
def handle_find(profile):
sid = request.sid
PROFILES[sid] = profile
WAITING.append(sid)
emit("status", {"msg": "Finding partner..."}, room=sid)
try_match()
@socketio.on("disconnect")
def handle_disconnect(sid):
# `sid` is passed in by Socket.IO on disconnect
if sid in WAITING:
WAITING.remove(sid)
PROFILES.pop(sid, None)
# Remove from any room
for room, pair in list(ROOMS.items()):
if sid in pair:
other = pair[1] if pair[0] == sid else pair[0]
emit("status", {"msg": "Partner left."}, room=other)
leave_room(room, sid=other)
ROOMS.pop(room)
@socketio.on("subscribe")
def handle_subscribe(data):
room = data.get("room")
sid = request.sid
if room in ROOMS and sid in ROOMS[room]:
join_room(room)
emit("status", {"msg": f"Joined room {room}!"}, room=sid)
else:
emit("status", {"msg": "Invalid room or not in this room."}, room=sid)
@socketio.on("chat")
def handle_chat(data):
room = data.get("room")
msg = data.get("msg")
sid = data.get("sid") or request.sid
if room in ROOMS:
emit("chat", {"msg": msg, "sid": sid}, room=room)
@socketio.on("leave")
def handle_leave(data):
room = data.get("room")
sid = request.sid
emit("left", {}, room=sid)
if room in ROOMS:
other = next(s for s in ROOMS[room] if s != sid)
emit("status", {"msg": "Partner left."}, room=other)
leave_room(room, sid=other)
ROOMS.pop(room)
def try_match():
import random
random.shuffle(WAITING) # To ensure fairness
used = set()
pairs = []
# === FIRST: Try matching by interest ===
for i, sid1 in enumerate(WAITING):
if sid1 in used: continue
p1 = PROFILES.get(sid1)
if not p1: continue
for j in range(i + 1, len(WAITING)):
sid2 = WAITING[j]
if sid2 in used: continue
p2 = PROFILES.get(sid2)
if not p2: continue
# Gender filtering
if p1['looking'] != 'any' and p2['gender'].lower() != p1['looking'].lower():
continue
if p2['looking'] != 'any' and p1['gender'].lower() != p2['looking'].lower():
continue
# Interests matching
if set(p1['interests']) & set(p2['interests']):
pairs.append((sid1, sid2))
used.update([sid1, sid2])
break
# === SECOND: Fallback to random match (respect gender) ===
for i, sid1 in enumerate(WAITING):
if sid1 in used: continue
p1 = PROFILES.get(sid1)
if not p1: continue
for j in range(i + 1, len(WAITING)):
sid2 = WAITING[j]
if sid2 in used: continue
p2 = PROFILES.get(sid2)
if not p2: continue
# Gender filtering only
if p1['looking'] != 'any' and p2['gender'].lower() != p1['looking'].lower():
continue
if p2['looking'] != 'any' and p1['gender'].lower() != p2['looking'].lower():
continue
pairs.append((sid1, sid2))
used.update([sid1, sid2])
break
# === Finalize pairs and assign rooms ===
for sid1, sid2 in pairs:
for sid in (sid1, sid2):
if sid in WAITING:
WAITING.remove(sid)
room = str(uuid.uuid4())
ROOMS[room] = (sid1, sid2)
join_room(room, sid=sid1)
join_room(room, sid=sid2)
emit("matched", {
"room": room,
"my_id": PROFILES[sid1]["id"],
"my_sid": sid1,
"partner_id": PROFILES[sid2]["id"],
"partner_sid": sid2
}, room=sid1)
emit("matched", {
"room": room,
"my_id": PROFILES[sid2]["id"],
"my_sid": sid2,
"partner_id": PROFILES[sid1]["id"],
"partner_sid": sid1
}, room=sid2)
if __name__ == "__main__":
socketio.run(app, host="0.0.0.0", port=7860)