feat: capture coauthors and per-item width/height/tagged_users
Two additions to the metadata sidecars, following up on the 2026-09-01 collab/dedup investigation already documented here: - coauthors added to the post-level JSON's include list -- a direct, native signal for collab detection instead of inferring it from the filename/directory identity mismatch also documented that day. - width, height, width_original, height_original and tagged_users get their own per-file sidecar (event: "file", one JSON per downloaded media item, named "<filename>.json"), since a carousel's items can each have different dimensions and tags -- data the existing post-level JSON has no way to represent. owner is deliberately left out, same reasoning as audio_user's existing exclusion. Verified against a live re-fetch of an already-archived carousel: correct per-item data came back, zero media re-downloaded (skip-archive still applies; only the new sidecars are new files). 3 new tests. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011qAds5qr7nZRq5R4yAuxUk
This commit is contained in:
@@ -232,6 +232,37 @@ class PostUrl(unittest.TestCase):
|
||||
self.assertNotIn(str(staging / subcategory), cmd)
|
||||
|
||||
|
||||
class MetadataFields(unittest.TestCase):
|
||||
"""Extra fields captured from the raw API response, verified against two
|
||||
saved real examples on 2026-09-01 (see docs/gallery-dl.md)."""
|
||||
|
||||
def test_post_level_json_captures_coauthors(self):
|
||||
config = gdl.build_config("1M", [6.0, 10.0], [3.0, 6.0])
|
||||
pps = config["extractor"]["instagram"]["posts"]["postprocessors"]
|
||||
post_json = next(pp for pp in pps if pp.get("filename", "").endswith(".json"))
|
||||
self.assertIn("coauthors", post_json["include"])
|
||||
|
||||
def test_per_item_dimensions_and_tags_get_their_own_sidecar(self):
|
||||
config = gdl.build_config("1M", [6.0, 10.0], [3.0, 6.0])
|
||||
pps = config["extractor"]["instagram"]["posts"]["postprocessors"]
|
||||
# No "filename" of its own -- unlike the other two, which are keyed
|
||||
# by POST_STEM -- because it must vary per carousel item, not per post.
|
||||
media_pp = next(pp for pp in pps if "filename" not in pp)
|
||||
for field in ("width", "height", "width_original", "height_original",
|
||||
"tagged_users", "shortcode", "num"):
|
||||
self.assertIn(field, media_pp["include"])
|
||||
# `owner` is a full user object (profile pic URLs, privacy flags) for
|
||||
# whoever posted that item -- deliberately excluded, same reasoning
|
||||
# as `audio_user` on the post-level json.
|
||||
self.assertNotIn("owner", media_pp["include"])
|
||||
|
||||
def test_reels_get_the_same_capture_as_posts(self):
|
||||
config = gdl.build_config("1M", [6.0, 10.0], [3.0, 6.0])
|
||||
posts_pps = config["extractor"]["instagram"]["posts"]["postprocessors"]
|
||||
reels_pps = config["extractor"]["instagram"]["reels"]["postprocessors"]
|
||||
self.assertEqual(posts_pps, reels_pps)
|
||||
|
||||
|
||||
class UrlsFile(unittest.TestCase):
|
||||
def test_reads_every_form_a_person_might_paste(self):
|
||||
with tempfile.TemporaryDirectory() as d:
|
||||
|
||||
Reference in New Issue
Block a user