clementBE commited on
Commit
1dccfaf
Β·
verified Β·
1 Parent(s): 46b8c81

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +42 -10
app.py CHANGED
@@ -266,11 +266,12 @@ def flickr_api_call(method, **params):
266
  return data
267
 
268
 
269
- def flickr_search(search_text, max_images=50, min_width=0, min_height=0):
 
270
  if not FLICKR_API_KEY:
271
  raise RuntimeError("No FLICKR_API_KEY found. Add it under Space Settings β†’ Secrets.")
272
  search_text = search_text.strip()
273
- if not search_text:
274
  raise ValueError("No Flickr search term was found.")
275
 
276
  max_images = min(int(max_images), MAX_IMAGES_HARD_LIMIT)
@@ -280,8 +281,10 @@ def flickr_search(search_text, max_images=50, min_width=0, min_height=0):
280
 
281
  while len(results) < max_images:
282
  data = flickr_api_call(
283
- "flickr.photos.search",
284
- text=search_text, safe_search="1", per_page=per_page, page=page,
 
 
285
  extras="description,license,date_upload,date_taken,owner_name,tags,views,"
286
  "url_sq,url_t,url_s,url_q,url_m,url_n,url_z,url_c,url_l,url_o,"
287
  "o_dims,original_format",
@@ -416,6 +419,25 @@ def flickr_photo_candidate(url):
416
  return flickr_photo_via_html(username, photo_id, page_url)
417
 
418
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
419
  # ============================================================
420
  # GENERIC HTML
421
  # ============================================================
@@ -699,7 +721,7 @@ def empty_result(message):
699
  return [], message, [], pd.DataFrame(), pd.DataFrame(), None, None, None
700
 
701
 
702
- def find_images(url, max_images, min_width, min_height, remove_duplicates):
703
  url = clean_url(url)
704
  if not url:
705
  return empty_result("❌ Please enter a URL.")
@@ -715,10 +737,16 @@ def find_images(url, max_images, min_width, min_height, remove_duplicates):
715
 
716
  # ---- Find candidates ----
717
  try:
718
- photo = flickr_photo_candidate(url) if is_flickr_url(url) else None
719
- if photo:
720
- mode_message = "Flickr photo page mode" + (" (API)" if FLICKR_API_KEY else " (HTML)")
721
- candidates = [photo]
 
 
 
 
 
 
722
  elif is_flickr_url(url) and FLICKR_API_KEY and extract_flickr_search_text(url):
723
  mode_message = "Flickr API search mode"
724
  candidates = flickr_search(
@@ -880,6 +908,10 @@ with gr.Blocks(title=APP_TITLE) as demo:
880
  min_width = gr.Number(value=0, minimum=0, maximum=10000, step=100, label="Minimum width (px)")
881
  min_height = gr.Number(value=0, minimum=0, maximum=10000, step=100, label="Minimum height (px)")
882
  remove_duplicates = gr.Checkbox(value=True, label="Remove duplicates")
 
 
 
 
883
 
884
  with gr.Row():
885
  find_button = gr.Button("πŸ”Ž Find & Analyze Images", variant="primary")
@@ -913,7 +945,7 @@ with gr.Blocks(title=APP_TITLE) as demo:
913
 
914
  find_button.click(
915
  fn=find_images,
916
- inputs=[url_input, max_images, min_width, min_height, remove_duplicates],
917
  outputs=[gallery, status, image_state, metadata_table, weekly_table,
918
  weekly_plot, xlsx_file, csv_file],
919
  )
 
266
  return data
267
 
268
 
269
+ def flickr_search(search_text, max_images=50, min_width=0, min_height=0,
270
+ method="flickr.photos.search", extra_params=None):
271
  if not FLICKR_API_KEY:
272
  raise RuntimeError("No FLICKR_API_KEY found. Add it under Space Settings β†’ Secrets.")
273
  search_text = search_text.strip()
274
+ if method == "flickr.photos.search" and not search_text:
275
  raise ValueError("No Flickr search term was found.")
276
 
277
  max_images = min(int(max_images), MAX_IMAGES_HARD_LIMIT)
 
281
 
282
  while len(results) < max_images:
283
  data = flickr_api_call(
284
+ method,
285
+ **({"text": search_text} if method == "flickr.photos.search" else {}),
286
+ **(extra_params or {}),
287
+ safe_search="1", per_page=per_page, page=page,
288
  extras="description,license,date_upload,date_taken,owner_name,tags,views,"
289
  "url_sq,url_t,url_s,url_q,url_m,url_n,url_z,url_c,url_l,url_o,"
290
  "o_dims,original_format",
 
419
  return flickr_photo_via_html(username, photo_id, page_url)
420
 
421
 
422
+ def flickr_photo_and_stream(url, max_images, min_width, min_height, include_stream=True):
423
+ """Photo page -> the photo itself, then the same photographer's older public photos."""
424
+ first = flickr_photo_candidate(url)
425
+ if not first:
426
+ return None
427
+ if not (include_stream and FLICKR_API_KEY and max_images > 1):
428
+ return [first]
429
+ info = flickr_api_call("flickr.photos.getInfo", photo_id=first["photo_id"])["photo"]
430
+ stream = flickr_search(
431
+ "", max_images, min_width, min_height,
432
+ method="flickr.people.getPublicPhotos",
433
+ extra_params={
434
+ "user_id": info["owner"]["nsid"],
435
+ "max_upload_date": info["dates"]["posted"], # start at this photo, go older
436
+ },
437
+ )
438
+ return [first] + [s for s in stream if s["photo_id"] != first["photo_id"]]
439
+
440
+
441
  # ============================================================
442
  # GENERIC HTML
443
  # ============================================================
 
721
  return [], message, [], pd.DataFrame(), pd.DataFrame(), None, None, None
722
 
723
 
724
+ def find_images(url, max_images, min_width, min_height, remove_duplicates, include_stream=True):
725
  url = clean_url(url)
726
  if not url:
727
  return empty_result("❌ Please enter a URL.")
 
737
 
738
  # ---- Find candidates ----
739
  try:
740
+ photo_list = (
741
+ flickr_photo_and_stream(url, max_images, min_width, min_height, include_stream)
742
+ if is_flickr_url(url) else None
743
+ )
744
+ if photo_list:
745
+ mode_message = (
746
+ "Flickr photo page + photostream (API)" if FLICKR_API_KEY
747
+ else "Flickr photo page (HTML, single photo only: set FLICKR_API_KEY to get more)"
748
+ )
749
+ candidates = photo_list
750
  elif is_flickr_url(url) and FLICKR_API_KEY and extract_flickr_search_text(url):
751
  mode_message = "Flickr API search mode"
752
  candidates = flickr_search(
 
908
  min_width = gr.Number(value=0, minimum=0, maximum=10000, step=100, label="Minimum width (px)")
909
  min_height = gr.Number(value=0, minimum=0, maximum=10000, step=100, label="Minimum height (px)")
910
  remove_duplicates = gr.Checkbox(value=True, label="Remove duplicates")
911
+ include_stream = gr.Checkbox(
912
+ value=True,
913
+ label="Photo page: also download the photographer's other photos (needs API key)",
914
+ )
915
 
916
  with gr.Row():
917
  find_button = gr.Button("πŸ”Ž Find & Analyze Images", variant="primary")
 
945
 
946
  find_button.click(
947
  fn=find_images,
948
+ inputs=[url_input, max_images, min_width, min_height, remove_duplicates, include_stream],
949
  outputs=[gallery, status, image_state, metadata_table, weekly_table,
950
  weekly_plot, xlsx_file, csv_file],
951
  )