File size: 4,328 Bytes
579e534
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
"""
cache.py — lightweight SQLite cache for scraped Tenor results.

HF Spaces free tier gives you a persistent disk mounted at /data if you
enable "persistent storage", otherwise the filesystem resets on restart.
Either way this works fine — it just won't survive a restart without
persistent storage enabled. Path is overridable via TENOR_CACHE_PATH env var.
"""

import os
import json
import sqlite3
import time
import threading

DB_PATH = os.environ.get("TENOR_CACHE_PATH", "/data/tenor_cache.db")
# fall back to local dir if /data doesn't exist (no persistent storage enabled)
if not os.path.isdir(os.path.dirname(DB_PATH)):
    DB_PATH = os.environ.get("TENOR_CACHE_PATH_FALLBACK", "./tenor_cache.db")

_lock = threading.Lock()


def _connect():
    conn = sqlite3.connect(DB_PATH, check_same_thread=False)
    conn.row_factory = sqlite3.Row
    return conn


def init_db():
    with _lock:
        conn = _connect()
        conn.execute("""
            CREATE TABLE IF NOT EXISTS search_cache (
                query TEXT NOT NULL,
                page INTEGER NOT NULL DEFAULT 1,
                results_json TEXT NOT NULL,
                cached_at REAL NOT NULL,
                PRIMARY KEY (query, page)
            )
        """)
        conn.execute("""
            CREATE TABLE IF NOT EXISTS favorites (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                gif_url TEXT NOT NULL UNIQUE,
                mp4_url TEXT,
                title TEXT,
                tag TEXT,
                added_at REAL NOT NULL
            )
        """)
        conn.execute("""
            CREATE TABLE IF NOT EXISTS request_log (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                endpoint TEXT NOT NULL,
                query TEXT,
                api_key TEXT,
                ts REAL NOT NULL
            )
        """)
        conn.commit()
        conn.close()


def get_cached_search(query, page=1, max_age_seconds=3600):
    with _lock:
        conn = _connect()
        row = conn.execute(
            "SELECT results_json, cached_at FROM search_cache WHERE query = ? AND page = ?",
            (query.lower().strip(), page),
        ).fetchone()
        conn.close()
    if not row:
        return None
    if time.time() - row["cached_at"] > max_age_seconds:
        return None
    return json.loads(row["results_json"])


def set_cached_search(query, results, page=1):
    with _lock:
        conn = _connect()
        conn.execute(
            "INSERT OR REPLACE INTO search_cache (query, page, results_json, cached_at) VALUES (?, ?, ?, ?)",
            (query.lower().strip(), page, json.dumps(results), time.time()),
        )
        conn.commit()
        conn.close()


def add_favorite(gif_url, mp4_url=None, title="", tag=""):
    with _lock:
        conn = _connect()
        try:
            conn.execute(
                "INSERT OR IGNORE INTO favorites (gif_url, mp4_url, title, tag, added_at) VALUES (?, ?, ?, ?, ?)",
                (gif_url, mp4_url, title, tag, time.time()),
            )
            conn.commit()
        finally:
            conn.close()


def remove_favorite(favorite_id):
    with _lock:
        conn = _connect()
        conn.execute("DELETE FROM favorites WHERE id = ?", (favorite_id,))
        conn.commit()
        conn.close()


def list_favorites(tag=None):
    with _lock:
        conn = _connect()
        if tag:
            rows = conn.execute(
                "SELECT * FROM favorites WHERE tag = ? ORDER BY added_at DESC", (tag,)
            ).fetchall()
        else:
            rows = conn.execute(
                "SELECT * FROM favorites ORDER BY added_at DESC"
            ).fetchall()
        conn.close()
    return [dict(r) for r in rows]


def log_request(endpoint, query=None, api_key=None):
    with _lock:
        conn = _connect()
        conn.execute(
            "INSERT INTO request_log (endpoint, query, api_key, ts) VALUES (?, ?, ?, ?)",
            (endpoint, query, api_key, time.time()),
        )
        conn.commit()
        conn.close()


def clear_expired(max_age_seconds=86400):
    with _lock:
        conn = _connect()
        conn.execute(
            "DELETE FROM search_cache WHERE cached_at < ?",
            (time.time() - max_age_seconds,),
        )
        conn.commit()
        conn.close()