Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -15,8 +15,8 @@ from huggingface_hub import HfApi
|
|
| 15 |
# -------------------------
|
| 16 |
DATASET_REPO_ID = os.environ.get("DATASET_REPO_ID") # Space secret
|
| 17 |
HF_TOKEN = os.environ["HF_TOKEN"] # Space secret
|
|
|
|
| 18 |
|
| 19 |
-
KEYS_PATH = "keys.csv"
|
| 20 |
SENT_PATH = "sent.csv"
|
| 21 |
|
| 22 |
# Maximum keys per order = quantity * KEYS_PER_QUANTITY
|
|
@@ -29,7 +29,6 @@ _lock = threading.Lock()
|
|
| 29 |
# Simple cache to reduce Hub reads
|
| 30 |
_cache = {
|
| 31 |
"ts": 0.0,
|
| 32 |
-
"keys": None, # type: ignore
|
| 33 |
"sent": None, # type: ignore
|
| 34 |
}
|
| 35 |
CACHE_TTL_SEC = 10.0
|
|
@@ -61,29 +60,6 @@ def _upload_csv(repo_id: str, path_in_repo: str, content: str, commit_message: s
|
|
| 61 |
token=HF_TOKEN,
|
| 62 |
)
|
| 63 |
|
| 64 |
-
def _parse_keys(csv_text: str) -> list:
|
| 65 |
-
keys = []
|
| 66 |
-
reader = csv.DictReader(io.StringIO(csv_text))
|
| 67 |
-
for r in reader:
|
| 68 |
-
if r["key"].strip():
|
| 69 |
-
keys.append({
|
| 70 |
-
"key": r["key"].strip(),
|
| 71 |
-
"sent": (r.get("sent") or "").strip(),
|
| 72 |
-
})
|
| 73 |
-
return keys
|
| 74 |
-
|
| 75 |
-
def _serialize_keys(keys: list) -> str:
|
| 76 |
-
out = io.StringIO()
|
| 77 |
-
fieldnames = ["key", "sent"]
|
| 78 |
-
w = csv.DictWriter(out, fieldnames=fieldnames)
|
| 79 |
-
w.writeheader()
|
| 80 |
-
for k in keys:
|
| 81 |
-
w.writerow({
|
| 82 |
-
"key": k["key"],
|
| 83 |
-
"sent": k.get("sent", ""),
|
| 84 |
-
})
|
| 85 |
-
return out.getvalue()
|
| 86 |
-
|
| 87 |
def _parse_sent(csv_text: str) -> dict:
|
| 88 |
"""Parse sent.csv and return a dict keyed by order_number"""
|
| 89 |
sent = {}
|
|
@@ -120,19 +96,15 @@ def _serialize_sent(sent_dict: dict) -> str:
|
|
| 120 |
|
| 121 |
def load_state(force: bool = False):
|
| 122 |
now = time.time()
|
| 123 |
-
if (not force) and _cache["
|
| 124 |
-
return _cache["
|
| 125 |
|
| 126 |
-
keys_csv = _download_csv(DATASET_REPO_ID, KEYS_PATH)
|
| 127 |
sent_csv = _download_csv(DATASET_REPO_ID, SENT_PATH)
|
| 128 |
-
|
| 129 |
-
keys = _parse_keys(keys_csv)
|
| 130 |
sent = _parse_sent(sent_csv)
|
| 131 |
|
| 132 |
_cache["ts"] = now
|
| 133 |
-
_cache["keys"] = keys
|
| 134 |
_cache["sent"] = sent
|
| 135 |
-
return
|
| 136 |
|
| 137 |
# -------------------------
|
| 138 |
# Core API
|
|
@@ -154,7 +126,7 @@ def claim_c_key(
|
|
| 154 |
return "", "Please provide an order number."
|
| 155 |
|
| 156 |
with _lock:
|
| 157 |
-
|
| 158 |
|
| 159 |
# Check if order exists in sent.csv
|
| 160 |
if order_number not in sent:
|
|
@@ -172,21 +144,12 @@ def claim_c_key(
|
|
| 172 |
if keys_already_sent >= max_keys:
|
| 173 |
return "", f"Key limit reached for order {order_number} ({keys_already_sent}/{max_keys} keys sent)."
|
| 174 |
|
| 175 |
-
# Find available keys
|
| 176 |
-
available_keys = [k for k in keys if not k["sent"]]
|
| 177 |
-
|
| 178 |
-
if len(available_keys) < 1:
|
| 179 |
-
return "", "No available keys remaining."
|
| 180 |
-
|
| 181 |
-
# Send the next available key
|
| 182 |
-
key_to_send = available_keys[0]
|
| 183 |
-
|
| 184 |
# Create ephemeral OpenAI key using the Realtime API (expires in 1 hour)
|
| 185 |
try:
|
| 186 |
response = requests.post(
|
| 187 |
"https://api.openai.com/v1/realtime/client_secrets",
|
| 188 |
headers={
|
| 189 |
-
"Authorization": f"Bearer {
|
| 190 |
"Content-Type": "application/json"
|
| 191 |
},
|
| 192 |
json={
|
|
@@ -209,9 +172,6 @@ def claim_c_key(
|
|
| 209 |
except Exception as e:
|
| 210 |
return "", f"Failed to create ephemeral key: {str(e)}"
|
| 211 |
|
| 212 |
-
# Mark key as sent
|
| 213 |
-
key_to_send["sent"] = _utc_now_iso()
|
| 214 |
-
|
| 215 |
# Update sent.csv - store the ephemeral key
|
| 216 |
existing_keys = sent[order_number]["keys_sent"]
|
| 217 |
if existing_keys:
|
|
@@ -220,17 +180,9 @@ def claim_c_key(
|
|
| 220 |
sent[order_number]["keys_sent"] = ephemeral_key
|
| 221 |
sent[order_number]["quantity_keys_sent"] += 1
|
| 222 |
|
| 223 |
-
# Save changes
|
| 224 |
-
updated_keys_csv = _serialize_keys(keys)
|
| 225 |
updated_sent_csv = _serialize_sent(sent)
|
| 226 |
|
| 227 |
-
_upload_csv(
|
| 228 |
-
DATASET_REPO_ID,
|
| 229 |
-
KEYS_PATH,
|
| 230 |
-
updated_keys_csv,
|
| 231 |
-
commit_message=f"Key sent for order {order_number} at {_utc_now_iso()}",
|
| 232 |
-
)
|
| 233 |
-
|
| 234 |
_upload_csv(
|
| 235 |
DATASET_REPO_ID,
|
| 236 |
SENT_PATH,
|
|
@@ -264,4 +216,3 @@ with gr.Blocks(title="API") as demo:
|
|
| 264 |
|
| 265 |
demo.queue()
|
| 266 |
demo.launch()
|
| 267 |
-
|
|
|
|
| 15 |
# -------------------------
|
| 16 |
DATASET_REPO_ID = os.environ.get("DATASET_REPO_ID") # Space secret
|
| 17 |
HF_TOKEN = os.environ["HF_TOKEN"] # Space secret
|
| 18 |
+
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"] # Space secret
|
| 19 |
|
|
|
|
| 20 |
SENT_PATH = "sent.csv"
|
| 21 |
|
| 22 |
# Maximum keys per order = quantity * KEYS_PER_QUANTITY
|
|
|
|
| 29 |
# Simple cache to reduce Hub reads
|
| 30 |
_cache = {
|
| 31 |
"ts": 0.0,
|
|
|
|
| 32 |
"sent": None, # type: ignore
|
| 33 |
}
|
| 34 |
CACHE_TTL_SEC = 10.0
|
|
|
|
| 60 |
token=HF_TOKEN,
|
| 61 |
)
|
| 62 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
def _parse_sent(csv_text: str) -> dict:
|
| 64 |
"""Parse sent.csv and return a dict keyed by order_number"""
|
| 65 |
sent = {}
|
|
|
|
| 96 |
|
| 97 |
def load_state(force: bool = False):
|
| 98 |
now = time.time()
|
| 99 |
+
if (not force) and _cache["sent"] is not None and (now - _cache["ts"] < CACHE_TTL_SEC):
|
| 100 |
+
return _cache["sent"]
|
| 101 |
|
|
|
|
| 102 |
sent_csv = _download_csv(DATASET_REPO_ID, SENT_PATH)
|
|
|
|
|
|
|
| 103 |
sent = _parse_sent(sent_csv)
|
| 104 |
|
| 105 |
_cache["ts"] = now
|
|
|
|
| 106 |
_cache["sent"] = sent
|
| 107 |
+
return sent
|
| 108 |
|
| 109 |
# -------------------------
|
| 110 |
# Core API
|
|
|
|
| 126 |
return "", "Please provide an order number."
|
| 127 |
|
| 128 |
with _lock:
|
| 129 |
+
sent = load_state(force=True)
|
| 130 |
|
| 131 |
# Check if order exists in sent.csv
|
| 132 |
if order_number not in sent:
|
|
|
|
| 144 |
if keys_already_sent >= max_keys:
|
| 145 |
return "", f"Key limit reached for order {order_number} ({keys_already_sent}/{max_keys} keys sent)."
|
| 146 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
# Create ephemeral OpenAI key using the Realtime API (expires in 1 hour)
|
| 148 |
try:
|
| 149 |
response = requests.post(
|
| 150 |
"https://api.openai.com/v1/realtime/client_secrets",
|
| 151 |
headers={
|
| 152 |
+
"Authorization": f"Bearer {OPENAI_API_KEY}",
|
| 153 |
"Content-Type": "application/json"
|
| 154 |
},
|
| 155 |
json={
|
|
|
|
| 172 |
except Exception as e:
|
| 173 |
return "", f"Failed to create ephemeral key: {str(e)}"
|
| 174 |
|
|
|
|
|
|
|
|
|
|
| 175 |
# Update sent.csv - store the ephemeral key
|
| 176 |
existing_keys = sent[order_number]["keys_sent"]
|
| 177 |
if existing_keys:
|
|
|
|
| 180 |
sent[order_number]["keys_sent"] = ephemeral_key
|
| 181 |
sent[order_number]["quantity_keys_sent"] += 1
|
| 182 |
|
| 183 |
+
# Save changes
|
|
|
|
| 184 |
updated_sent_csv = _serialize_sent(sent)
|
| 185 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
_upload_csv(
|
| 187 |
DATASET_REPO_ID,
|
| 188 |
SENT_PATH,
|
|
|
|
| 216 |
|
| 217 |
demo.queue()
|
| 218 |
demo.launch()
|
|
|