"""Abuse guards shared by the demo server (ece) and the HF Space: - one shloka per request (block bulk paste / bulk download) - a per-IP daily render quota Pure-stdlib, in-memory (resets on process restart — fine for a public demo).""" import threading, datetime DAILY_LIMIT = 10 # renders per IP per day MAX_AKSHARAS = 100 # one verse: longest common vṛtta (sragdharā) is 84 syllables; >100 = multiple shlokas _lock = threading.Lock() _counts = {} # ip -> [date_iso, count] def _n_aksharas(s): """Count Devanagari/Kannada akṣaras (independent vowels + non-virāma-killed consonants).""" n = 0; L = len(s) for i, c in enumerate(s): o = ord(c) indep = (0x0905 <= o <= 0x0914) or (0x0C85 <= o <= 0x0C94) cons = (0x0915 <= o <= 0x0939) or (0x0C95 <= o <= 0x0CB9) if indep: n += 1 elif cons: nxt = s[i+1] if i+1 < L else "" if nxt not in ("्", "್"): n += 1 return n def client_ip(request): """Real visitor IP — prefer Cloudflare's header (tunnel), then X-Forwarded-For, then peer.""" try: h = getattr(request, "headers", {}) or {} get = h.get if hasattr(h, "get") else (lambda k, d=None: d) ip = get("cf-connecting-ip") or (get("x-forwarded-for", "") or "").split(",")[0].strip() if not ip and getattr(request, "client", None): ip = request.client.host return ip or "unknown" except Exception: return "unknown" def validate_one_shloka(text): """Return an error message if the input is not a single shloka, else None.""" t = (text or "").replace("।।", "॥") if t.count("॥") >= 2: return "Please enter just one shloka at a time 🙏" if _n_aksharas(text) > MAX_AKSHARAS: return "That looks longer than one shloka — please paste a single verse 🙏" return None def check_and_count(ip): """True if under today's limit (and records the use); False if the daily quota is exhausted.""" today = datetime.date.today().isoformat() with _lock: rec = _counts.get(ip) if not rec or rec[0] != today: rec = [today, 0]; _counts[ip] = rec if rec[1] >= DAILY_LIMIT: return False rec[1] += 1 return True