File size: 2,316 Bytes
68f10e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
"""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