diff --git a/app.py b/app.py index a0efbb6..2f2dfe4 100644 --- a/app.py +++ b/app.py @@ -278,6 +278,28 @@ def api_card(): "type": bl.get("type"), "prepaid": bl.get("prepaid")}, "flags": (["prepaid-risk"] if (bl.get("type")=="prepaid" or bl.get("prepaid") is True) else []) + (["luhn-invalid"] if not ok else [])}) +# ---------- SMS ABUSE GUARD ---------- +def sms_guard(): + """Return None if allowed, else a JSON-able reason string.""" + con = db(); now = int(time.time()) + ip = request.headers.get("X-Real-IP") or request.remote_addr or "?" + # balance: refuse if house SMSPool balance below $5 + st, b = sms_api("balance") + bal = jf(b) or {} + try: bal = float(bal.get("balance", 0)) + except Exception: bal = 0 + if bal < 5: return f"house balance too low (${bal:.2f}) — rentals paused" + # per-IP: max 1 active rental, 3/hour, 8/day + row = con.execute("SELECT COUNT(*) c FROM sms_rentals WHERE status='active' AND purchase_id IN (SELECT purchase_id FROM sms_rentals WHERE created > ?)", (now-86400*7,)).fetchone() + # active count overall (any IP) cap 3 concurrent + act = con.execute("SELECT COUNT(*) c FROM sms_rentals WHERE status='active' AND expires > ?", (now,)).fetchone()["c"] + if act >= 3: return "too many active rentals right now — try again later" + h = con.execute("SELECT COUNT(*) c FROM sms_rentals WHERE created > ?", (now-3600,)).fetchone()["c"] + if h >= 6: return "hourly rental cap reached" + d = con.execute("SELECT COUNT(*) c FROM sms_rentals WHERE created > ?", (now-86400,)).fetchone()["c"] + if d >= 15: return "daily rental cap reached" + return None + # ---------- 3. SMS RENTALS ---------- SMSP = "https://api.smspool.net" SERVICES = [("google","Google"),("discord","Discord"),("telegram","Telegram"),("whatsapp","WhatsApp"),("other","Other/Any")] @@ -296,18 +318,22 @@ def sms(): if request.method == "POST": act = request.form.get("act") if act == "rent": - svc, ctry = request.form["service"], request.form["country"] - st, b = sms_api("purchase/sms", service=svc, country=ctry) - d = jf(b) or {} - if d.get("success") == 1: - con = db() - now = int(time.time()) - con.execute("INSERT INTO sms_rentals(phone,service,country,purchase_id,cost,status,created,expires) VALUES(?,?,?,?,?,?,?,?)", - (d.get("number"), svc, ctry, str(d.get("purchase_id")), d.get("cost",0), "active", now, now+1800)) - con.commit() - msg = f'
RENTED Your number: +{d.get("number")} · expires in 30 min · order #{d.get("purchase_id")}
' + guard = sms_guard() + if guard: + msg = f'
PAUSED {guard}
' else: - msg = f'
RENT FAILED
{b[:400]}
' + svc, ctry = request.form["service"], request.form["country"] + st, b = sms_api("purchase/sms", service=svc, country=ctry) + d = jf(b) or {} + if d.get("success") == 1: + con = db() + now = int(time.time()) + con.execute("INSERT INTO sms_rentals(phone,service,country,purchase_id,cost,status,created,expires) VALUES(?,?,?,?,?,?,?,?)", + (d.get("number"), svc, ctry, str(d.get("purchase_id")), d.get("cost",0), "active", now, now+1800)) + con.commit() + msg = f'
RENTED Your number: +{d.get("number")} · expires in 30 min · order #{d.get("purchase_id")}
' + else: + msg = f'
RENT FAILED
{b[:400]}
' elif act == "check": pid = request.form["pid"] st, b = sms_api("sms/check", orderid=pid) @@ -360,12 +386,14 @@ if(d.sms||d.code){{toast('CODE: '+(d.sms||d.code));document.title='✉ CODE '+(d @app.route("/api/sms/rent", methods=["POST"]) def api_sms_rent(): - st, b = sms_api("purchase/sms", service=request.form["service"], country=request.form["country"]) + guard = sms_guard() + if guard: return jsonify({"success": 0, "message": guard, "paused": True}) + st, b = sms_api("purchase/sms", service=param("service"), country=param("country")) d = jf(b) or {} if d.get("success") == 1: con = db(); now = int(time.time()) con.execute("INSERT INTO sms_rentals(phone,service,country,purchase_id,cost,status,created,expires) VALUES(?,?,?,?,?,?,?,?)", - (d.get("number"), request.form["service"], request.form["country"], str(d.get("purchase_id")), d.get("cost",0), "active", now, now+1800)) + (d.get("number"), param("service"), param("country"), str(d.get("purchase_id")), d.get("cost",0), "active", now, now+1800)) con.commit() return jsonify(d) @@ -381,7 +409,9 @@ def api_sms_cancel(): @app.route("/api/sms/history") def api_sms_history(): - con = db() + con = db(); now = int(time.time()) + con.execute("UPDATE sms_rentals SET status='expired' WHERE status='active' AND expires < ?", (now,)) + con.commit() rows = con.execute("SELECT * FROM sms_rentals ORDER BY id DESC LIMIT 50").fetchall() return jsonify([dict(r) for r in rows])