vivekchakraverty Claude Opus 4.8 commited on
Commit
e935ba7
·
1 Parent(s): 4b8e533

Add one-click extension .zip download button in the Space UI

Browse files

Zip the bundled extension/ folder at startup (top-level extension/ dir, ready to "Load
unpacked") and expose it via a gr.DownloadButton in the YouTube-access panel; allow the
temp dir in launch() so Gradio can serve it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Files changed (2) hide show
  1. README.md +7 -5
  2. app.py +25 -1
README.md CHANGED
@@ -71,11 +71,13 @@ Paste the values into the app's **"YouTube access — cookies / proxy"** panel:
71
  ### Easiest: the PO Token Grabber extension (one click)
72
 
73
  This repo ships a tiny Chrome/Edge extension in [`extension/`](extension/) that reads the
74
- PO token + visitor data for you. Download that folder, load it unpacked
75
- (`chrome://extensions` Developer mode Load unpacked), open a YouTube video and press
76
- play, then click the extension **while on the YouTube tab** to capture the values. Open
77
- this Space in another tab and hit **⤵ Fill the Space tab** to inject them straight into
78
- the fields below (or use the Copy buttons and paste). See
 
 
79
  [`extension/README.md`](extension/README.md). (It's unpublished/sideloaded and may need
80
  updates when YouTube changes; the manual steps below always work as a fallback.)
81
 
 
71
  ### Easiest: the PO Token Grabber extension (one click)
72
 
73
  This repo ships a tiny Chrome/Edge extension in [`extension/`](extension/) that reads the
74
+ PO token + visitor data for you. Grab it with the **⬇️ Download the PO Token Grabber
75
+ extension (.zip)** button in the app's *YouTube access* panel (or from
76
+ [`extension/`](extension/)), unzip it, and load it unpacked (`chrome://extensions`
77
+ Developer mode Load unpacked). Open a YouTube video and press play, then click the
78
+ extension **while on the YouTube tab** to capture the values. Open this Space in another
79
+ tab and hit **⤵ Fill the Space tab** to inject them straight into the fields below (or use
80
+ the Copy buttons and paste). See
81
  [`extension/README.md`](extension/README.md). (It's unpublished/sideloaded and may need
82
  updates when YouTube changes; the manual steps below always work as a fallback.)
83
 
app.py CHANGED
@@ -26,6 +26,25 @@ from pipeline import (
26
  tutorial as tutorial_mod,
27
  )
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  LLM_CHOICES = [
30
  "deepseek-ai/DeepSeek-V3",
31
  "meta-llama/Llama-3.3-70B-Instruct",
@@ -291,6 +310,11 @@ def build_ui():
291
  "- An operator can instead set Space secrets `YT_COOKIES` / `YT_PROXY` / "
292
  "`YT_POT` / `YT_VISITOR_DATA` as shared defaults."
293
  )
 
 
 
 
 
294
  cookies_text = gr.Textbox(
295
  label="YouTube cookies (cookies.txt contents or base64)", lines=4,
296
  placeholder="# Netscape HTTP Cookie File … (or a base64 blob)")
@@ -350,4 +374,4 @@ def build_ui():
350
 
351
 
352
  if __name__ == "__main__":
353
- build_ui().queue().launch()
 
26
  tutorial as tutorial_mod,
27
  )
28
 
29
+ APP_DIR = os.path.dirname(os.path.abspath(__file__))
30
+ EXTENSION_DIR = os.path.join(APP_DIR, "extension")
31
+
32
+
33
+ def _build_extension_zip() -> str | None:
34
+ """Zip the bundled browser extension for one-click download; return the .zip path.
35
+
36
+ Produces an archive whose top-level folder is ``extension/`` so it unzips to a
37
+ ready-to-"Load unpacked" directory. Returns None if the folder isn't present.
38
+ """
39
+ if not os.path.isdir(EXTENSION_DIR):
40
+ return None
41
+ out_base = os.path.join(tempfile.gettempdir(), "tutorialmaker-extension")
42
+ try:
43
+ return shutil.make_archive(out_base, "zip", root_dir=APP_DIR, base_dir="extension")
44
+ except Exception:
45
+ return None
46
+
47
+
48
  LLM_CHOICES = [
49
  "deepseek-ai/DeepSeek-V3",
50
  "meta-llama/Llama-3.3-70B-Instruct",
 
310
  "- An operator can instead set Space secrets `YT_COOKIES` / `YT_PROXY` / "
311
  "`YT_POT` / `YT_VISITOR_DATA` as shared defaults."
312
  )
313
+ _ext_zip = _build_extension_zip()
314
+ if _ext_zip:
315
+ gr.DownloadButton(
316
+ "⬇️ Download the PO Token Grabber extension (.zip)",
317
+ value=_ext_zip, size="sm")
318
  cookies_text = gr.Textbox(
319
  label="YouTube cookies (cookies.txt contents or base64)", lines=4,
320
  placeholder="# Netscape HTTP Cookie File … (or a base64 blob)")
 
374
 
375
 
376
  if __name__ == "__main__":
377
+ build_ui().queue().launch(allowed_paths=[tempfile.gettempdir()])