rahul7star commited on
Commit
15b177f
·
verified ·
1 Parent(s): 09581d8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +137 -241
app.py CHANGED
@@ -1,296 +1,192 @@
1
  import os
2
- import math
3
- import random
4
  import tempfile
5
- import gradio as gr
6
  from huggingface_hub import HfApi, hf_hub_download
7
-
8
- # ======================================================
9
- # CONFIG
10
- # ======================================================
11
- DEFAULT_REPO = "rahul7star/WAN22-Feb-2026"
12
- FREE_REPO = "rahul7star/ohamlab"
13
- FREE_IMAGE_DIR = "showcase/image"
14
 
15
  HF_TOKEN = os.getenv("HF_TOKEN")
16
- APP_PASSWORD = os.getenv("APP_PASSWORD")
17
-
18
- if not HF_TOKEN:
19
- raise RuntimeError("HF_TOKEN not set")
20
- if not APP_PASSWORD:
21
- raise RuntimeError("APP_PASSWORD not set")
22
-
23
- api = HfApi()
24
- PAGE_SIZE = 6
25
-
26
- tmp_dir = tempfile.mkdtemp()
27
- images_cache = {} # (repo, date) -> list[(img, prompt)]
28
- prompt_cache = {} # folder_path -> prompt text
29
-
30
- # ======================================================
31
- # PROMPT LOADER (NEW)
32
- # ======================================================
33
- def load_prompt_from_folder(repo, folder):
34
- """
35
- Tries to find prompt text inside the same upload folder.
36
- Cached for performance.
37
- """
38
- key = (repo, folder)
39
- if key in prompt_cache:
40
- return prompt_cache[key]
41
-
42
- files = api.list_repo_files(repo, token=HF_TOKEN)
43
- prompt = ""
44
-
45
- for f in files:
46
- if not f.startswith(folder + "/"):
47
- continue
48
-
49
- name = os.path.basename(f).lower()
50
 
51
- if name in ("prompt.txt", "caption.txt"):
52
- try:
53
- path = hf_hub_download(repo, f, token=HF_TOKEN)
54
- with open(path, "r", encoding="utf-8", errors="ignore") as fp:
55
- prompt = fp.read().strip()
56
- except Exception as e:
57
- print("[PROMPT ERROR]", e)
58
- break
59
 
60
- prompt_cache[key] = prompt
61
- return prompt
62
 
63
 
64
- # ======================================================
65
- # FREE PREVIEW
66
- # ======================================================
67
- def load_free_images():
68
- tmp = tempfile.mkdtemp()
69
- files = api.list_repo_files(FREE_REPO, token=HF_TOKEN)
70
 
71
- imgs = [
72
- f for f in files
73
- if f.startswith(FREE_IMAGE_DIR)
74
- and f.lower().endswith((".png", ".jpg", ".jpeg", ".webp"))
75
- ]
 
76
 
77
- random.shuffle(imgs)
78
- imgs = imgs[:5]
79
 
80
- out = []
81
- for f in imgs:
82
- try:
83
- out.append(hf_hub_download(FREE_REPO, f, token=HF_TOKEN, local_dir=tmp))
84
- except Exception:
85
- pass
 
 
 
86
 
87
- return out
88
 
 
 
 
 
 
 
89
 
90
- FREE_IMAGES = load_free_images()
91
 
92
- # ======================================================
93
- # HELPERS
94
- # ======================================================
95
- def clear_cache():
96
- images_cache.clear()
97
- prompt_cache.clear()
98
- print("[CACHE] cleared")
99
 
100
 
101
- def list_date_folders(repo, last_n=20):
102
- files = api.list_repo_files(repo, token=HF_TOKEN)
103
- dates = sorted(
104
- {f.split("/")[0] for f in files if "/" in f},
105
- reverse=True
 
106
  )
107
- return dates[:last_n]
108
 
109
 
110
- def download_images(repo, date):
111
- key = (repo, date)
112
- if key in images_cache:
113
- return images_cache[key]
114
 
115
- files = api.list_repo_files(repo, token=HF_TOKEN)
116
- results = []
 
117
 
118
- for f in files:
119
- if not f.startswith(date + "/"):
120
- continue
121
- if not f.lower().endswith((".png", ".jpg", ".jpeg", ".webp")):
122
  continue
123
 
124
- folder = os.path.dirname(f)
125
- dst = os.path.join(tmp_dir, repo.replace("/", "_"), f)
126
- os.makedirs(os.path.dirname(dst), exist_ok=True)
127
-
128
- try:
129
- img_path = hf_hub_download(
130
- repo,
131
- f,
132
- token=HF_TOKEN,
133
- local_dir=os.path.dirname(dst),
134
- )
135
- prompt = load_prompt_from_folder(repo, folder)
136
- results.append((img_path, prompt))
137
- print("[DOWNLOAD]", f)
138
- except Exception as e:
139
- print("[DOWNLOAD ERROR]", f, e)
140
-
141
- images_cache[key] = results
142
- print(f"[INFO] {repo} {date}: {len(results)} images")
143
- return results
144
-
145
-
146
- # ======================================================
147
- # PAGINATION
148
- # ======================================================
149
- def render_page(repo, date, page):
150
- items = download_images(repo, date)
151
- total_pages = max(1, math.ceil(len(items) / PAGE_SIZE))
152
-
153
- page = max(0, min(int(page), total_pages - 1))
154
- start = page * PAGE_SIZE
155
- end = start + PAGE_SIZE
156
-
157
- return (
158
- items[start:end],
159
- page,
160
- f"Page {page+1} / {total_pages}",
161
- )
162
 
 
 
 
 
 
 
163
 
164
- def nav(delta, repo, date, page):
165
- return render_page(repo, date, page + delta)
166
 
 
167
 
168
- def change_date(repo, date):
169
- clear_cache()
170
- return render_page(repo, date, 0)
171
 
 
 
 
172
 
173
- def change_repo(repo):
174
- clear_cache()
175
- dates = list_date_folders(repo)
176
- first = dates[0] if dates else ""
177
- imgs, page, info = render_page(repo, first, 0)
178
- return dates, imgs, page, first, info
179
 
 
180
 
181
- # ======================================================
182
- # AUTH
183
- # ======================================================
184
- def check_password(pwd):
185
- if pwd != APP_PASSWORD:
186
- return (
187
- gr.update(visible=True),
188
- gr.update(visible=False),
189
- [],
190
- 0,
191
- "",
192
- "❌ Wrong password",
193
- )
194
 
195
- dates = list_date_folders(DEFAULT_REPO)
196
- latest = dates[0]
197
 
198
- imgs, page, info = render_page(DEFAULT_REPO, latest, 0)
199
 
200
- return (
201
- gr.update(visible=False),
202
- gr.update(visible=True),
203
- imgs,
204
- page,
205
- latest,
206
- info,
207
- )
208
 
209
 
210
- # ======================================================
211
- # CSS (UNCHANGED)
212
- # ======================================================
213
- css = """
214
- footer, .gradio-footer { display:none!important; }
215
- #ohamlab-footer {
216
- position:fixed;
217
- bottom:0;
218
- width:100%;
219
- background:#f8f9fb;
220
- font-size:12px;
221
- padding:8px;
222
- border-top:1px solid #e5e7eb;
223
- text-align:center;
224
  }
225
- """
226
 
227
- # ======================================================
228
- # UI
229
- # ======================================================
230
- with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
231
- gr.Markdown("# 🔐 OhamLab Image Showcase (PRO)")
232
-
233
- with gr.Column(visible=True) as login_box:
234
- pwd = gr.Textbox(type="password", label="Password")
235
- login_btn = gr.Button("Unlock")
236
-
237
- gr.Markdown("### 🎁 Free Preview")
238
- with gr.Row():
239
- for img in FREE_IMAGES:
240
- gr.Image(img, show_label=False)
241
-
242
- with gr.Column(visible=False) as app:
243
- repo_state = gr.State(DEFAULT_REPO)
244
- date_state = gr.State("")
245
- page_state = gr.State(0)
246
-
247
- repo_input = gr.Textbox(value=DEFAULT_REPO, label="Base HuggingFace Repo")
248
- date_dropdown = gr.Dropdown(label="Select Date")
249
- manual_date = gr.Textbox(label="Or enter date (YYYY-MM-DD)")
250
-
251
- gallery = gr.Gallery(columns=3, height="auto", show_label=False)
252
- page_info = gr.Markdown()
253
-
254
- with gr.Row():
255
- prev_btn = gr.Button("⬅ Previous")
256
- next_btn = gr.Button("Next ➡")
257
-
258
- login_btn.click(
259
- check_password,
260
- inputs=pwd,
261
- outputs=[login_box, app, gallery, page_state, date_state, page_info],
262
  )
263
 
264
- repo_input.change(
265
- change_repo,
266
- inputs=repo_input,
267
- outputs=[date_dropdown, gallery, page_state, date_state, page_info],
268
- ).then(lambda r: r, inputs=repo_input, outputs=repo_state)
269
 
270
- date_dropdown.change(
271
- lambda r, d: change_date(r, d),
272
- inputs=[repo_state, date_dropdown],
273
- outputs=[gallery, page_state, page_info],
274
- ).then(lambda d: d, inputs=date_dropdown, outputs=date_state)
275
 
276
- manual_date.submit(
277
- lambda r, d: change_date(r, d),
278
- inputs=[repo_state, manual_date],
279
- outputs=[gallery, page_state, page_info],
280
- ).then(lambda d: d, inputs=manual_date, outputs=date_state)
281
 
 
 
 
 
 
 
 
 
282
  prev_btn.click(
283
  lambda r, d, p: nav(-1, r, d, p),
284
- inputs=[repo_state, date_state, page_state],
285
- outputs=[gallery, page_state, page_info],
286
  )
287
 
288
  next_btn.click(
289
  lambda r, d, p: nav(1, r, d, p),
290
- inputs=[repo_state, date_state, page_state],
291
- outputs=[gallery, page_state, page_info],
292
  )
293
 
294
- gr.HTML("<div id='ohamlab-footer'>© OhamLab Copyright</div>")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295
 
296
  demo.launch()
 
1
  import os
 
 
2
  import tempfile
3
+ from functools import lru_cache
4
  from huggingface_hub import HfApi, hf_hub_download
5
+ import gradio as gr
 
 
 
 
 
 
6
 
7
  HF_TOKEN = os.getenv("HF_TOKEN")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
 
9
+ DEFAULT_REPO = "rahul7star/WAN22-Feb-2026"
10
+ IMAGES_PER_PAGE = 6
 
 
 
 
 
 
11
 
12
+ api = HfApi(token=HF_TOKEN)
 
13
 
14
 
15
+ # -------------------------------------------------
16
+ # Helpers
17
+ # -------------------------------------------------
 
 
 
18
 
19
+ def list_date_folders(repo_id):
20
+ files = api.list_repo_files(repo_id=repo_id)
21
+ return sorted(
22
+ {f.split("/")[0] for f in files if "/" in f},
23
+ reverse=True
24
+ )
25
 
 
 
26
 
27
+ def list_image_folders(repo_id, date):
28
+ files = api.list_repo_files(repo_id=repo_id)
29
+ return sorted(
30
+ {
31
+ "/".join(f.split("/")[:2])
32
+ for f in files
33
+ if f.startswith(date + "/") and f.count("/") >= 1
34
+ }
35
+ )
36
 
 
37
 
38
+ def find_image_file(repo_id, folder):
39
+ files = api.list_repo_files(repo_id=repo_id)
40
+ for f in files:
41
+ if f.startswith(folder) and f.lower().endswith((".png", ".jpg", ".jpeg", ".webp")):
42
+ return f
43
+ return None
44
 
 
45
 
46
+ def find_summary_file(repo_id, folder):
47
+ files = api.list_repo_files(repo_id=repo_id)
48
+ for f in files:
49
+ if f.startswith(folder) and f.endswith("summary.txt"):
50
+ return f
51
+ return None
 
52
 
53
 
54
+ def download_file(repo_id, path):
55
+ return hf_hub_download(
56
+ repo_id=repo_id,
57
+ filename=path,
58
+ token=HF_TOKEN,
59
+ cache_dir=tempfile.mkdtemp()
60
  )
 
61
 
62
 
63
+ # -------------------------------------------------
64
+ # Cache (refreshed per repo + date)
65
+ # -------------------------------------------------
 
66
 
67
+ @lru_cache(maxsize=32)
68
+ def load_date(repo_id, date):
69
+ items = []
70
 
71
+ for folder in list_image_folders(repo_id, date):
72
+ img_path = find_image_file(repo_id, folder)
73
+ if not img_path:
 
74
  continue
75
 
76
+ local_img = download_file(repo_id, img_path)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
 
78
+ summary_path = find_summary_file(repo_id, folder)
79
+ summary_text = ""
80
+ if summary_path:
81
+ local_summary = download_file(repo_id, summary_path)
82
+ with open(local_summary, "r", encoding="utf-8") as f:
83
+ summary_text = f.read().strip()
84
 
85
+ items.append((local_img, summary_text))
 
86
 
87
+ return items
88
 
 
 
 
89
 
90
+ def render_page(repo_id, date, page):
91
+ all_items = load_date(repo_id, date)
92
+ total_pages = max(1, (len(all_items) + IMAGES_PER_PAGE - 1) // IMAGES_PER_PAGE)
93
 
94
+ page = max(0, min(page, total_pages - 1))
95
+ start = page * IMAGES_PER_PAGE
96
+ end = start + IMAGES_PER_PAGE
 
 
 
97
 
98
+ return all_items[start:end], page, total_pages
99
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
+ def nav(delta, repo_id, date, page):
102
+ return (*render_page(repo_id, date, page + delta),)
103
 
 
104
 
105
+ def refresh(repo_id, date):
106
+ load_date.cache_clear()
107
+ return render_page(repo_id, date, 0)
 
 
 
 
 
108
 
109
 
110
+ # -------------------------------------------------
111
+ # UI
112
+ # -------------------------------------------------
113
+
114
+ with gr.Blocks(css="""
115
+ footer {visibility: hidden;}
116
+ #copyright {
117
+ text-align: center;
118
+ font-size: 12px;
119
+ color: #888;
120
+ margin-top: 12px;
 
 
 
121
  }
122
+ """) as demo:
123
 
124
+ gr.Markdown("## 📸 Image Browser (Private HF Repo)")
125
+
126
+ with gr.Row():
127
+ repo_input = gr.Textbox(
128
+ value=DEFAULT_REPO,
129
+ label="Repository ID"
130
+ )
131
+ date_dd = gr.Dropdown(
132
+ choices=list_date_folders(DEFAULT_REPO),
133
+ label="Date"
134
+ )
135
+
136
+ gallery = gr.Gallery(
137
+ label="Images",
138
+ columns=3,
139
+ height="auto",
140
+ show_label=True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  )
142
 
143
+ page_state = gr.State(0)
144
+ page_info = gr.Markdown()
 
 
 
145
 
146
+ with gr.Row():
147
+ prev_btn = gr.Button("⬅ Prev")
148
+ next_btn = gr.Button("Next ➡")
149
+ refresh_btn = gr.Button("🔄 Refresh")
 
150
 
151
+ gr.HTML("<div id='copyright'>© OhamLab</div>")
 
 
 
 
152
 
153
+ # Initial load
154
+ demo.load(
155
+ lambda r, d: render_page(r, d, 0),
156
+ inputs=[repo_input, date_dd],
157
+ outputs=[gallery, page_state, page_info]
158
+ )
159
+
160
+ # Navigation
161
  prev_btn.click(
162
  lambda r, d, p: nav(-1, r, d, p),
163
+ inputs=[repo_input, date_dd, page_state],
164
+ outputs=[gallery, page_state, page_info]
165
  )
166
 
167
  next_btn.click(
168
  lambda r, d, p: nav(1, r, d, p),
169
+ inputs=[repo_input, date_dd, page_state],
170
+ outputs=[gallery, page_state, page_info]
171
  )
172
 
173
+ refresh_btn.click(
174
+ refresh,
175
+ inputs=[repo_input, date_dd],
176
+ outputs=[gallery, page_state, page_info]
177
+ )
178
+
179
+ # Change date or repo → refresh cache
180
+ date_dd.change(
181
+ refresh,
182
+ inputs=[repo_input, date_dd],
183
+ outputs=[gallery, page_state, page_info]
184
+ )
185
+
186
+ repo_input.change(
187
+ lambda r: gr.Dropdown(choices=list_date_folders(r)),
188
+ inputs=repo_input,
189
+ outputs=date_dd
190
+ )
191
 
192
  demo.launch()