Update app.py

This commit is contained in:
2026-05-05 20:18:54 +02:00
parent 4df8f5c9c8
commit 6072d297a6
+40 -12
View File
@@ -93,8 +93,14 @@ if missing:
KNOWN_EXTERNAL_USERS = {}
RATE_LIMIT = defaultdict(list)
METRICS = defaultdict(int)
CACHE_FILE = "/app/cache/known_users.json"
CACHE_DIRTY = False
# ============================================================
# CACHE HANDLING
# ============================================================
def load_cache():
global KNOWN_EXTERNAL_USERS
@@ -107,13 +113,24 @@ def load_cache():
KNOWN_EXTERNAL_USERS = {}
def save_cache():
global CACHE_DIRTY
if not CACHE_DIRTY:
return
try:
os.makedirs(os.path.dirname(CACHE_FILE), exist_ok=True)
with open(CACHE_FILE, "w") as f:
json.dump(KNOWN_EXTERNAL_USERS, f)
CACHE_DIRTY = False
except Exception as e:
logger.error(f"Failed to save cache: {e}")
def periodic_cache_save():
while True:
save_cache()
time.sleep(30)
# ============================================================
# HELPERS
# ============================================================
@@ -134,14 +151,14 @@ def is_known_user(user_id):
if time.time() - ts > config.cache_ttl:
del KNOWN_EXTERNAL_USERS[user_id]
save_cache()
return False
return True
def remember_user(user_id):
global CACHE_DIRTY
KNOWN_EXTERNAL_USERS[user_id] = time.time()
save_cache()
CACHE_DIRTY = True
def is_local_room(room_id):
try:
@@ -153,21 +170,19 @@ def get_role(user_id):
return "admin" if user_id in config.admin_users else "user"
# ============================================================
# RATE LIMIT
# RATE LIMIT (IMPROVED)
# ============================================================
def is_rate_limited(domain):
def is_rate_limited(domain, sender):
key = f"{domain}:{sender}"
now = time.time()
RATE_LIMIT[domain] = [
t for t in RATE_LIMIT[domain]
if now - t < 60
]
RATE_LIMIT[key] = [t for t in RATE_LIMIT[key] if now - t < 60]
if len(RATE_LIMIT[domain]) >= config.rate_limit_per_minute:
if len(RATE_LIMIT[key]) >= config.rate_limit_per_minute:
return True
RATE_LIMIT[domain].append(now)
RATE_LIMIT[key].append(now)
return False
# ============================================================
@@ -290,7 +305,15 @@ def is_likely_dm_event(event):
@app.route("/healthz")
def health():
return {"status": "ok"}
return {
"status": "ok",
"known_users": len(KNOWN_EXTERNAL_USERS),
"metrics": dict(METRICS)
}
@app.route("/metrics")
def metrics():
return dict(METRICS)
@app.route('/_matrix/client/v3/createRoom', methods=['POST'])
def create_room():
@@ -309,6 +332,7 @@ def create_room():
)
if not allowed:
METRICS["create_room_blocked"] += 1
log_event(
"create_room_blocked",
actor=user_id,
@@ -319,6 +343,7 @@ def create_room():
return Response(json.dumps({"errcode": "M_FORBIDDEN"}), status=403)
if is_dm:
METRICS["create_room_allowed"] += 1
log_event(
"create_room_allowed",
actor=user_id,
@@ -346,7 +371,7 @@ def invite(room_id, event_id):
domain = extract_domain(sender)
if is_rate_limited(domain):
if is_rate_limited(domain, sender):
return Response(status=429)
if domain in config.domain_whitelist:
@@ -365,6 +390,7 @@ def invite(room_id, event_id):
if is_user_in_local_rooms(sender):
remember_user(sender)
else:
METRICS["invite_blocked"] += 1
log_event(
"invite_blocked",
actor=sender,
@@ -374,6 +400,7 @@ def invite(room_id, event_id):
return Response(status=403)
remember_user(sender)
METRICS["invite_allowed"] += 1
return forward_request(
"PUT",
@@ -421,5 +448,6 @@ if __name__ == '__main__':
seed_known_users()
threading.Thread(target=periodic_seed, daemon=True).start()
threading.Thread(target=periodic_cache_save, daemon=True).start()
app.run(host='0.0.0.0', port=5000)