1window.searchField = function(obj, fieldName, parentDepth = 0, results = [], parents = []) {
2 if (typeof obj !== "object" || obj === null) {
3 return results;
4 }
5
6 for (const key in obj) {
7 if (key === fieldName) {
8 let ancestorIndex = parents.length - parentDepth;
9 if (ancestorIndex >= 0) {
10 results.push(parents[ancestorIndex] || obj);
11 } else {
12 results.push(obj);
13 }
14 }
15 if (typeof obj[key] === "object" && obj[key] !== null) {
16 searchField(obj[key], fieldName, parentDepth, results, [...parents, obj]);
17 }
18 }
19 return results;
20}
21
22window.searchFieldMap = function(data, fieldName, parentDepth = 0) {
23 const results = [];
24
25 if (!(data instanceof Map)) {
26 return searchField(data, fieldName, parentDepth, results);
27 }
28
29 for (const [, value] of data) {
30 if (typeof value === "object" && value !== null) {
31 if (fieldName in value) {
32 results.push(value);
33 }
34 const nested = searchField(value, fieldName, parentDepth, []);
35 results.push(...nested);
36 }
37 }
38
39 return results;
40}
41
42window.getValue = function(value, fallback = "Not Available") {
43 if (value === null || value === undefined || value === "") return fallback;
44 return String(value);
45}
46
47window.formatBoolean = function(value) {
48 if (typeof value === "boolean") return value ? "Yes" : "No";
49 return "Not Available";
50}
51
52window.joinList = function(items, separator = " || ") {
53 if (!Array.isArray(items)) return "Not Available";
54 const filtered = items.filter(Boolean);
55 return filtered.length > 0 ? filtered.join(separator) : "Not Available";
56}
57
58window.moduleExport = function(exports) {
59 if (typeof module !== "undefined" && module.exports) {
60 module.exports = exports;
61 } else {
62 Object.assign(window, exports);
63 }
64}
65
66window.userCache = new Map();
67window.postDetailsCache = new Map();
68
69window.getCachedUser = function(user) {
70 if (!user) return null;
71
72 const userId = user.pk?.toString() || user.id?.toString();
73 if (!userId) return user;
74
75 if (user.username) {
76 userCache.set(userId, user);
77 return user;
78 }
79
80 if (userCache.has(userId)) {
81 return { ...user, ...userCache.get(userId) };
82 }
83
84 return user;
85}
86
87window.resolveRefs = function(obj, map, visited = new Set()) {
88 if (typeof obj !== "object" || obj === null) {
89 return obj;
90 }
91
92 if (!(map instanceof Map)) {
93 return obj;
94 }
95
96 if (obj.__ref) {
97 const refKey = obj.__ref;
98 if (visited.has(refKey)) return obj;
99 visited.add(refKey);
100
101 if (map.has(refKey)) {
102 const resolved = map.get(refKey);
103 return resolveRefs(resolved, map, visited);
104 }
105 return obj;
106 }
107
108 if (obj.__refs && Array.isArray(obj.__refs)) {
109 return obj.__refs.map(refKey => {
110 if (visited.has(refKey)) return { __ref: refKey };
111 visited.add(refKey);
112
113 if (map.has(refKey)) {
114 const resolved = map.get(refKey);
115 return resolveRefs(resolved, map, visited);
116 }
117 return { __ref: refKey };
118 });
119 }
120
121 if (obj.__id) {
122 const refKey = obj.__id;
123 if (!visited.has(refKey) && map.has(refKey)) {
124 visited.add(refKey);
125 const lookedUp = map.get(refKey);
126 const merged = { ...obj, ...lookedUp };
127 const resolved = {};
128 for (const key in merged) {
129 resolved[key] = resolveRefs(merged[key], map, visited);
130 }
131 return resolved;
132 }
133 }
134
135 if (Array.isArray(obj)) {
136 return obj.map(item => resolveRefs(item, map, visited));
137 }
138
139 const resolved = {};
140 for (const key in obj) {
141 resolved[key] = resolveRefs(obj[key], map, visited);
142 }
143 return resolved;
144}
145
146window.getPostType = function(mediaType) {
147 switch (mediaType) {
148 case 1: return "Photo";
149 case 2: return "Video";
150 case 8: return "Carousel";
151 default: return null;
152 }
153}
154
155window.getSavedPostType = function(item) {
156 if (item.isSidecar) return "Carousel";
157 if (item.isVideo) return "Video";
158 return "Photo";
159}
160
161window.getImageUrl = function(item) {
162 const candidates = item.image_versions2?.candidates;
163 if (Array.isArray(candidates) && candidates[0]?.url) {
164 return candidates[0].url;
165 }
166
167 const resolverData = item["$r:client__srcSet"]?.__resolverSnapshot?.data;
168 if (resolverData?.image_versions2?.candidates?.[0]?.url) {
169 return resolverData.image_versions2.candidates[0].url;
170 }
171
172 return null;
173}
174
175window.getCurrentInstagramUrl = function() {
176 if (typeof location === "undefined") return "";
177 return location.href || "";
178}
179
180window.isInstagramReelsUrl = function() {
181 const currentUrl = getCurrentInstagramUrl();
182 return currentUrl.includes("instagram.com/reels/") || currentUrl.includes("instagram.com/reel/");
183}
184
185window.getCurrentInstagramReelsCode = function() {
186 if (!isInstagramReelsUrl()) return null;
187 return getInstagramCodeFromUrl(getCurrentInstagramUrl());
188}
189
190window.getInstagramCodeFromUrl = function(url) {
191 if (!url) return null;
192 try {
193 const parsedUrl = new URL(url);
194 const parts = parsedUrl.pathname.split("/").filter(Boolean);
195 return ["p", "reel", "reels"].includes(parts[0]) && parts[1] ? parts[1] : null;
196 } catch (error) {
197 const match = url.match(/instagram\.com\/(?:p|reel|reels)\/([^/?#]+)/);
198 return match ? match[1] : null;
199 }
200}
201
202window.cacheUsersFromData = function(data) {
203 if (!data || typeof data !== "object") return;
204 let users = [];
205 if (data instanceof Map) {
206 users = searchFieldMap(data, "full_name");
207 users = users.map(item => resolveRefs(item, data));
208 } else {
209 users = searchField(data, "full_name");
210 }
211 for (const user of users) {
212 if (user && user.username) {
213 getCachedUser(user);
214 }
215 }
216}
217
218window.getPostDetailValueCount = function(item) {
219 return [
220 item.caption,
221 item.likeCount,
222 item.commentCount,
223 item.viewCount,
224 item.user?.username,
225 item.user?.full_name,
226 item.user?.profile_pic_url,
227 item.imageUrl,
228 item.videoUrl,
229 item.postedAt,
230 item.duration,
231 item.hasAudio,
232 item.audioTitle,
233 item.audioArtist,
234 item.isPaidPartnership,
235 item.commentsDisabled,
236 item.accessibilityCaption
237 ].filter(value => value !== null && value !== undefined && value !== "").length;
238}
239
240window.mergePostDetails = function(existing, incoming) {
241 if (!existing) return incoming;
242 const preferred = getPostDetailValueCount(incoming) > getPostDetailValueCount(existing) ? incoming : existing;
243 const fallback = preferred === incoming ? existing : incoming;
244 return {
245 ...fallback,
246 ...preferred,
247 user: {
248 ...(fallback.user || {}),
249 ...(preferred.user || {})
250 },
251 raw: preferred.raw || fallback.raw
252 };
253}
254
255window.getPostDetailCandidates = function(data) {
256 if (!data || typeof data !== "object") return [];
257 let candidates = [];
258 if (data instanceof Map) {
259 candidates = [
260 ...searchFieldMap(data, "coauthor_producers"),
261 ...searchFieldMap(data, "code")
262 ].map(item => resolveRefs(item, data));
263 } else {
264 candidates = [
265 ...searchField(data, "coauthor_producers"),
266 ...searchField(data, "code")
267 ];
268 }
269
270 return candidates.filter(item => {
271 if (!item || typeof item !== "object") return false;
272 const key = item.code || item.pk?.toString() || item.id?.toString();
273 return Boolean(key);
274 });
275}
276
277
278
279window.isReelPostDetailItem = function(item) {
280 return item?.code && (item.product_type === "clips" || item.media_type === 2 || item.clips_metadata);
281}
282
283window.preparePostDetailItem = function(item) {
284 const postId = item.pk?.toString() || item.id?.toString();
285 if (!postId) return null;
286
287 const user = getCachedUser(item.user || item.owner || item.caption?.user);
288 const caption = item.caption;
289 const captionText = typeof caption === "string" ? caption : caption?.text;
290 const isReel = item.product_type === "clips" || item.media_type === 2;
291 const isCarousel = item.media_type === 8 || item.carousel_media_count > 0;
292
293 let imageUrl = item.image_versions2?.candidates?.[0]?.url
294 || item.carousel_media?.[0]?.image_versions2?.candidates?.[0]?.url;
295
296 let videoUrl = item.video_versions?.[0]?.url
297 || item.carousel_media?.[0]?.video_versions?.[0]?.url;
298
299 let taggedUsers = null;
300 if (item.usertags?.in?.length > 0) {
301 taggedUsers = item.usertags.in.map(tag => tag.user?.username).filter(Boolean).join(", ");
302 }
303
304 return {
305 id: postId,
306 code: item.code,
307 type: getPostType(item.media_type),
308 caption: captionText,
309 likeCount: item.like_count?.toString(),
310 commentCount: item.comment_count?.toString(),
311 viewCount: item.view_count?.toString() || item.play_count?.toString(),
312 user,
313 url: item.code ? `https://www.instagram.com/${isReel ? "reel" : "p"}/${item.code}/` : null,
314 imageUrl,
315 videoUrl,
316 coverImage: item.image_versions2?.candidates?.[0]?.url,
317 postedAt: item.taken_at ? new Date(item.taken_at * 1000).toISOString() : null,
318 location: item.location?.name,
319 duration: item.video_duration?.toString(),
320 hasAudio: item.has_audio,
321 audioTitle: item.clips_metadata?.original_sound_info?.original_audio_title,
322 audioArtist: item.clips_metadata?.original_sound_info?.ig_artist?.username,
323 taggedUsers,
324 isCarousel,
325 carouselCount: item.carousel_media_count?.toString() || item.carousel_media?.length?.toString(),
326 originalWidth: item.original_width?.toString(),
327 originalHeight: item.original_height?.toString(),
328 isPaidPartnership: item.is_paid_partnership,
329 commentsDisabled: item.comments_disabled,
330 likesDisabled: item.like_and_view_counts_disabled,
331 accessibilityCaption: item.accessibility_caption,
332 raw: item
333 };
334}
335
336window.cachePostDetailItem = function(item) {
337 if (!isReelPostDetailItem(item)) return;
338 const prepared = preparePostDetailItem(item);
339 if (!prepared) return;
340 const cached = postDetailsCache.get(item.code);
341 if (!cached) {
342 postDetailsCache.set(item.code, item);
343 return;
344 }
345 const cachedPrepared = preparePostDetailItem(cached);
346 const merged = mergePostDetails(cachedPrepared, prepared);
347 postDetailsCache.set(item.code, merged.raw);
348}
349
350window.preparePostsFromRequest = function(data) {
351 const results = [];
352 const seen = new Set();
353
354 for (const item of data) {
355 let posts = searchField(item, "media_notes");
356 if (posts.length === 0) {
357 posts = searchField(item, "clips_tab_pinned_user_ids");
358 }
359
360 for (const post of posts) {
361 const postId = post.id?.toString() || post.pk?.toString();
362 if (!postId || seen.has(postId)) continue;
363
364 if (!("clips_tab_pinned_user_ids" in post) && ("sponsor_tags" in post)) {
365 if (post.is_paid_partnership !== false) continue;
366 }
367
368 seen.add(postId);
369 const user = getCachedUser(post.user);
370 const isReel = post.product_type === "clips" || post.media_type === 2;
371
372 results.push({
373 id: postId,
374 code: post.code,
375 user,
376 type: getPostType(post.media_type),
377 text: post.caption?.text,
378 image: getImageUrl(post),
379 video: post.video_versions?.[0]?.url,
380 likes: post.like_count?.toString(),
381 commentsCount: post.comment_count?.toString(),
382 url: post.code ? `https://www.instagram.com/${isReel ? "reel" : "p"}/${post.code}/` : null,
383 date: post.taken_at ? new Date(post.taken_at * 1000).toISOString() : null,
384 commentsDisabled: post.comments_disabled,
385 accessibilityCaption: post.accessibility_caption,
386 raw: post
387 });
388 }
389 }
390
391 return results;
392}
393
394window.preparePostsFromDom = function(data) {
395 const results = [];
396 const seen = new Set();
397
398 for (const kv of data) {
399 const parsed = typeof kv === "string" ? JSON.parse(kv) : kv;
400 let posts = searchField(parsed, "media_notes");
401 if (posts.length === 0) {
402 posts = searchField(parsed, "clips_tab_pinned_user_ids");
403 }
404
405 for (const post of posts) {
406 const postId = post.id?.toString() || post.pk?.toString();
407 if (!postId || seen.has(postId)) continue;
408
409 if (!("clips_tab_pinned_user_ids" in post) && ("sponsor_tags" in post)) {
410 if (post.is_paid_partnership !== false) continue;
411 }
412
413 seen.add(postId);
414 const user = getCachedUser(post.user);
415 const isReel = post.product_type === "clips" || post.media_type === 2;
416
417 results.push({
418 id: postId,
419 code: post.code,
420 user,
421 type: getPostType(post.media_type),
422 text: post.caption?.text,
423 image: getImageUrl(post),
424 video: post.video_versions?.[0]?.url,
425 likes: post.like_count?.toString(),
426 commentsCount: post.comment_count?.toString(),
427 url: post.code ? `https://www.instagram.com/${isReel ? "reel" : "p"}/${post.code}/` : null,
428 date: post.taken_at ? new Date(post.taken_at * 1000).toISOString() : null,
429 commentsDisabled: post.comments_disabled,
430 accessibilityCaption: post.accessibility_caption,
431 raw: post
432 });
433 }
434 }
435
436 return results;
437}
438
439window.preparePostsFromReact = function(data) {
440 const results = [];
441 const seen = new Set();
442
443 for (const item of data) {
444 if (item && "isFetching" in item && Array.isArray(item.posts)) {
445 for (const post of item.posts) {
446 const postId = post.id?.toString();
447 if (!postId || seen.has(postId)) continue;
448 if (post.isSponsored) continue;
449
450 seen.add(postId);
451 const owner = post.owner;
452 const isReel = post.productType === "clips" || post.isVideo;
453
454 results.push({
455 id: postId,
456 code: post.code,
457 user: owner ? {
458 username: owner.username,
459 full_name: owner.fullName,
460 profile_pic_url: owner.profilePictureUrl,
461 is_verified: owner.isVerified
462 } : null,
463 type: getSavedPostType(post),
464 text: post.caption,
465 image: post.src || post.displayResources?.[0]?.src,
466 video: post.videoResources?.[0]?.src,
467 likes: post.numLikes?.toString(),
468 commentsCount: null,
469 url: post.code ? `https://www.instagram.com/${isReel ? "reel" : "p"}/${post.code}/` : null,
470 date: post.postedAt ? new Date(post.postedAt * 1000).toISOString() : null,
471 commentsDisabled: post.commentsDisabled,
472 accessibilityCaption: post.accessibilityCaption,
473 raw: post
474 });
475 }
476 continue;
477 }
478
479 if (item instanceof Map) {
480 cacheUsersFromData(item);
481 let posts = searchFieldMap(item, "sponsor_tags");
482 if (posts.length === 0) {
483 posts = searchFieldMap(item, "clips_tab_pinned_user_ids");
484 }
485 posts = posts.map(p => resolveRefs(p, item));
486
487 for (const post of posts) {
488 const postId = post.id?.toString() || post.pk?.toString();
489 if (!postId || seen.has(postId)) continue;
490
491 if (!("clips_tab_pinned_user_ids" in post) && ("sponsor_tags" in post)) {
492 if (post.is_paid_partnership !== false) continue;
493 }
494
495 seen.add(postId);
496 const user = getCachedUser(post.user);
497 const isReel = post.product_type === "clips" || post.media_type === 2;
498
499 results.push({
500 id: postId,
501 code: post.code,
502 user,
503 type: getPostType(post.media_type),
504 text: post.caption?.text,
505 image: getImageUrl(post),
506 video: post.video_versions?.[0]?.url,
507 likes: post.like_count?.toString(),
508 commentsCount: post.comment_count?.toString(),
509 url: post.code ? `https://www.instagram.com/${isReel ? "reel" : "p"}/${post.code}/` : null,
510 date: post.taken_at ? new Date(post.taken_at * 1000).toISOString() : null,
511 commentsDisabled: post.comments_disabled,
512 accessibilityCaption: post.accessibility_caption,
513 raw: post
514 });
515 }
516 continue;
517 }
518
519 const edges = item?.data?.xdt_api__v1__feed__user_timeline_graphql_connection?.edges;
520 if (edges) {
521 for (const edge of edges) {
522 const post = edge.node;
523 const postId = post.id?.toString() || post.pk?.toString();
524 if (!postId || seen.has(postId)) continue;
525
526 seen.add(postId);
527 const isReel = post.product_type === "clips" || post.media_type === 2;
528
529 results.push({
530 id: postId,
531 code: post.code,
532 user: post.user,
533 type: getPostType(post.media_type),
534 text: post.caption?.text,
535 image: post.image_versions2?.candidates?.[0]?.url,
536 video: post.video_versions?.[0]?.url,
537 likes: post.like_count?.toString(),
538 commentsCount: post.comment_count?.toString(),
539 url: post.code ? `https://www.instagram.com/${isReel ? "reel" : "p"}/${post.code}/` : null,
540 date: post.taken_at ? new Date(post.taken_at * 1000).toISOString() : null,
541 commentsDisabled: post.comments_disabled,
542 accessibilityCaption: post.accessibility_caption,
543 raw: edge
544 });
545 }
546 continue;
547 }
548
549 cacheUsersFromData(item);
550 let posts = searchField(item, "media_notes");
551 if (posts.length === 0) {
552 posts = searchField(item, "clips_tab_pinned_user_ids");
553 }
554
555 for (const post of posts) {
556 const postId = post.id?.toString() || post.pk?.toString();
557 if (!postId || seen.has(postId)) continue;
558
559 if (!("clips_tab_pinned_user_ids" in post) && ("sponsor_tags" in post)) {
560 if (post.is_paid_partnership !== false) continue;
561 }
562
563 seen.add(postId);
564 const user = getCachedUser(post.user);
565 const isReel = post.product_type === "clips" || post.media_type === 2;
566
567 results.push({
568 id: postId,
569 code: post.code,
570 user,
571 type: getPostType(post.media_type),
572 text: post.caption?.text,
573 image: getImageUrl(post),
574 video: post.video_versions?.[0]?.url,
575 likes: post.like_count?.toString(),
576 commentsCount: post.comment_count?.toString(),
577 url: post.code ? `https://www.instagram.com/${isReel ? "reel" : "p"}/${post.code}/` : null,
578 date: post.taken_at ? new Date(post.taken_at * 1000).toISOString() : null,
579 commentsDisabled: post.comments_disabled,
580 accessibilityCaption: post.accessibility_caption,
581 raw: post
582 });
583 }
584 }
585
586 return results;
587}
588
589window.formatPosts = function(prepared) {
590 return prepared.map(item => ({
591 id: item.id,
592 id2: item.code,
593 highlight: { id2: item.code },
594 raw: item.raw,
595 formatted: {
596 "id": item.id,
597 "Post Author": item.user?.username || "Not Available",
598 "Post Author Full Name": item.user?.full_name || item.user?.fullName || "Not Available",
599 "Post Author Image": item.user?.profile_pic_url || item.user?.profilePictureUrl || "Not Available",
600 "Post Author URL": item.user?.username ? `https://www.instagram.com/${item.user.username}/` : "Not Available",
601 "Post Author Is Verified": formatBoolean(item.user?.is_verified ?? item.user?.isVerified),
602 "Post Type": item.type || "Not Available",
603 "Post Text": item.text || "Not Available",
604 "Post Image": item.image || "Not Available",
605 "Post Video": item.video || "Not Available",
606 "Post Likes": item.likes || "Not Available",
607 "Post Comments Count": item.commentsCount || "Not Available",
608 "Post URL": item.url || "Not Available",
609 "Post Date": item.date || "Not Available",
610 "Is Comments Disabled": formatBoolean(item.commentsDisabled),
611 "Post Accessibility Caption": item.accessibilityCaption || "Not Available"
612 }
613 }));
614}
615
616window.posts = function(rawData) {
617 try {
618 if (isInstagramReelsUrl()) return [];
619
620 let prepared = [];
621 const seen = new Set();
622
623 for (const entry of rawData) {
624 let batch = [];
625 if (entry.metadata.method === "request") {
626 batch = preparePostsFromRequest(entry.data);
627 } else if (entry.metadata.method === "dom") {
628 batch = preparePostsFromDom(entry.data);
629 } else if (entry.metadata.method === "react") {
630 batch = preparePostsFromReact(entry.data);
631 }
632 for (const item of batch) {
633 if (!seen.has(item.id)) {
634 seen.add(item.id);
635 prepared.push(item);
636 }
637 }
638 }
639
640 return formatPosts(prepared);
641 } catch (error) {
642 return [];
643 }
644}
645
646
647
648window.prepareStories = function(rawData) {
649 const results = [];
650 const seen = new Set();
651 const userStore = new Map();
652
653 for (const entry of rawData) {
654 const dataItems = Array.isArray(entry.data) ? entry.data : [entry.data];
655 for (const data of dataItems) {
656 const stories = searchField(data, "story_cta");
657 searchField(data, "profile_pic_url").forEach(user => {
658 userStore.set(user.id, user);
659 });
660
661 for (const item of stories) {
662 const storyId = item.pk?.toString() || item.id?.toString();
663 if (!storyId || seen.has(storyId)) continue;
664 seen.add(storyId);
665
666 let user = item.user;
667 if (user && !user.profile_pic_url && userStore.get(user.id)) {
668 user = userStore.get(user.id);
669 }
670
671 results.push({
672 id: storyId,
673 type: getPostType(item.media_type),
674 image: item.image_versions2?.candidates?.[0]?.url,
675 video: item.video_versions?.[0]?.url,
676 link: item.pk && user?.username ? `https://www.instagram.com/stories/${user.username}/${item.pk}/` : null,
677 date: item.taken_at ? new Date(item.taken_at * 1000).toISOString() : null,
678 expiringAt: item.expiring_at ? new Date(item.expiring_at * 1000).toISOString() : null,
679 accessibilityCaption: item.accessibility_caption,
680 user,
681 bloksFullName: item.story_bloks_stickers?.[0]?.bloks_sticker?.sticker_data?.ig_mention?.full_name,
682 raw: item
683 });
684 }
685 }
686 }
687
688 return results;
689}
690
691window.formatStories = function(prepared) {
692 return prepared.map(item => ({
693 id: item.id,
694 highlight: { id: item.id },
695 raw: item.raw,
696 formatted: {
697 "id": item.id,
698 "Story Type": item.type || "Not Available",
699 "Story Image": item.image || "Not Available",
700 "Story Video": item.video || "Not Available",
701 "Story Link": item.link || "Not Available",
702 "Story Date": item.date || "Not Available",
703 "Story Expiring At": item.expiringAt || "Not Available",
704 "Story Accessibility Caption": item.accessibilityCaption || "Not Available",
705 "Author Username": item.user?.username || "Not Available",
706 "Author Full Name": item.user?.full_name || item.bloksFullName || "Not Available",
707 "Author Image": item.user?.profile_pic_url || "Not Available",
708 "Author URL": item.user?.username ? `https://www.instagram.com/${item.user.username}/` : "Not Available",
709 "Author Is Verified": formatBoolean(item.user?.is_verified)
710 }
711 }));
712}
713
714window.stories = function(rawData) {
715 try {
716 const prepared = prepareStories(rawData);
717 return formatStories(prepared);
718 } catch (error) {
719 return [];
720 }
721}
722
723
724
725window.preparePostDetails = function(rawData) {
726 const byPostKey = new Map();
727 const reelsCode = getCurrentInstagramReelsCode();
728 const currentUrl = getCurrentInstagramUrl();
729
730 for (const entry of rawData) {
731 const dataItems = Array.isArray(entry.data) ? entry.data : [entry.data];
732 const entryUrl = entry.metadata?.url || entry.metadata?.href || entry.url || entry.sourceUrl;
733 const entryCode = getInstagramCodeFromUrl(entryUrl);
734
735 for (const data of dataItems) {
736 cacheUsersFromData(data);
737 }
738
739 for (const data of dataItems) {
740 const items = getPostDetailCandidates(data);
741
742 for (const item of items) {
743 cachePostDetailItem(item);
744 const prepared = preparePostDetailItem(item);
745 if (!prepared) continue;
746
747 const targetCode = entryCode || reelsCode;
748 if (targetCode) {
749 if (item.code !== targetCode) continue;
750 } else if (!item.code || !currentUrl.includes(item.code)) {
751 continue;
752 }
753 const postKey = item.code || prepared.id;
754 byPostKey.set(postKey, mergePostDetails(byPostKey.get(postKey), prepared));
755 }
756 }
757 }
758
759 if (reelsCode && postDetailsCache.has(reelsCode)) {
760 console.log("Instagram postDetails cache check", {
761 currentUrl,
762 reelsCode,
763 cacheSize: postDetailsCache.size,
764 cacheKeys: Array.from(postDetailsCache.keys()),
765 cacheHit: true
766 });
767 const cachedPrepared = preparePostDetailItem(postDetailsCache.get(reelsCode));
768 if (cachedPrepared) {
769 byPostKey.set(reelsCode, mergePostDetails(byPostKey.get(reelsCode), cachedPrepared));
770 }
771 } else if (reelsCode) {
772 console.log("Instagram postDetails cache check", {
773 currentUrl,
774 reelsCode,
775 cacheSize: postDetailsCache.size,
776 cacheKeys: Array.from(postDetailsCache.keys()),
777 cacheHit: false
778 });
779 }
780
781 return Array.from(byPostKey.values());
782}
783
784window.formatPostDetails = function(prepared) {
785 return prepared.map(item => ({
786 id: item.id,
787 id2: item.code,
788 highlight: { id: item.id },
789 raw: item.raw,
790 formatted: {
791 "id": item.id,
792 "Post Type": item.type || "Not Available",
793 "Caption": item.caption || "Not Available",
794 "Like Count": item.likeCount || "Not Available",
795 "Comment Count": item.commentCount || "Not Available",
796 "View Count": item.viewCount || "Not Available",
797 "Author Username": item.user?.username || "Not Available",
798 "Author Full Name": item.user?.full_name || "Not Available",
799 "Author ID": item.user?.pk?.toString() || item.user?.id?.toString() || "Not Available",
800 "Author URL": item.user?.username ? `https://www.instagram.com/${item.user.username}/` : "Not Available",
801 "Author Is Verified": formatBoolean(item.user?.is_verified),
802 "Author Profile Pic": item.user?.profile_pic_url || item.user?.hd_profile_pic_url_info?.url || "Not Available",
803 "Post URL": item.url || "Not Available",
804 "Image URL": item.imageUrl || "Not Available",
805 "Video URL": item.videoUrl || "Not Available",
806 "Cover Image": item.coverImage || "Not Available",
807 "Posted At": item.postedAt || "Not Available",
808 "Location": item.location || "Not Available",
809 "Duration": item.duration || "Not Available",
810 "Has Audio": formatBoolean(item.hasAudio),
811 "Audio Title": item.audioTitle || "Not Available",
812 "Audio Artist": item.audioArtist || "Not Available",
813 "Tagged Users": item.taggedUsers || "Not Available",
814 "Is Carousel": formatBoolean(item.isCarousel),
815 "Carousel Count": item.carouselCount || "Not Available",
816 "Original Width": item.originalWidth || "Not Available",
817 "Original Height": item.originalHeight || "Not Available",
818 "Is Paid Partnership": formatBoolean(item.isPaidPartnership),
819 "Comments Disabled": formatBoolean(item.commentsDisabled),
820 "Likes Disabled": formatBoolean(item.likesDisabled),
821 "Accessibility Caption": item.accessibilityCaption || "Not Available"
822 }
823 }));
824}
825
826window.postDetails = function(rawData) {
827 console.log(rawData)
828 try {
829 const prepared = preparePostDetails(rawData);
830 return formatPostDetails(prepared);
831 } catch (error) {
832 return [];
833 }
834}
835
836
837
838window.prepareComments = function(rawData) {
839 const results = [];
840 const seen = new Set();
841
842 for (const entry of rawData) {
843 const dataItems = Array.isArray(entry.data) ? entry.data : [entry.data];
844 for (const data of dataItems) {
845 const comments = searchField(data, "comment_like_count");
846
847 for (const item of comments) {
848 const commentId = item.pk?.toString() || item.id?.toString();
849 if (!commentId || seen.has(commentId)) continue;
850 seen.add(commentId);
851
852 const commentDate = item.created_at ? new Date(item.created_at * 1000).toISOString() : null;
853
854 results.push({
855 id: commentId,
856 date: commentDate,
857 text: item.text,
858 media: item.giphy_media_info?.first_party_cdn_proxied_images?.fixed_height?.url,
859 likes: item.comment_like_count?.toString(),
860 user: item.user,
861 isReply: !!item.parent_comment_id,
862 parentCommentId: item.parent_comment_id?.toString(),
863 childCommentCount: item.child_comment_count,
864 raw: item
865 });
866 }
867 }
868 }
869
870 return results;
871}
872
873window.formatComments = function(prepared) {
874 return prepared.map(item => ({
875 id: item.id,
876 id2: item.date,
877 highlight: { id2: item.date },
878 raw: item.raw,
879 formatted: {
880 "id": item.id,
881 "Comment Text": item.text || "Not Available",
882 "Comment Media": item.media || "Not Available",
883 "Comment Date": item.date || "Not Available",
884 "Comment Likes": item.likes || "Not Available",
885 "Author Username": item.user?.username || "Not Available",
886 "Author ID": item.user?.pk || item.user?.id || "Not Available",
887 "Author URL": item.user?.username ? `https://www.instagram.com/${item.user.username}/` : "Not Available",
888 "Author Is Verified": formatBoolean(item.user?.is_verified),
889 "Is Reply": formatBoolean(item.isReply),
890 "Parent Comment ID": item.parentCommentId || "Not Available",
891 "Has Replies": formatBoolean(item.childCommentCount > 0),
892 "Reply Count": item.childCommentCount?.toString() || "Not Available"
893 }
894 }));
895}
896
897window.comments = function(rawData) {
898 try {
899 const prepared = prepareComments(rawData);
900 return formatComments(prepared);
901 } catch (error) {
902 return [];
903 }
904}
905
906
907
908window.prepareProfile = function(rawData) {
909 const results = [];
910 const seen = new Set();
911
912 for (const entry of rawData) {
913 const dataItems = Array.isArray(entry.data) ? entry.data : [entry.data];
914
915 for (const data of dataItems) {
916 let users = [];
917
918 if (data instanceof Map) {
919 users = searchFieldMap(data, "biography");
920 users = users.map(user => resolveRefs(user, data));
921 } else {
922 users = searchField(data, "biography");
923 }
924
925 for (const item of users) {
926 const userId = item.pk?.toString() || item.id?.toString();
927 if (!userId || seen.has(userId)) continue;
928 seen.add(userId);
929
930 results.push({
931 id: userId,
932 username: item.username,
933 fullName: item.full_name,
934 biography: item.biography,
935 externalUrl: item.external_url,
936 followerCount: item.follower_count?.toString(),
937 followingCount: item.following_count?.toString(),
938 mediaCount: item.media_count?.toString(),
939 isVerified: item.is_verified,
940 isPrivate: item.is_private,
941 isBusiness: item.is_business,
942 category: item.category,
943 profilePicUrl: item.hd_profile_pic_url_info?.url || item.profile_pic_url,
944 bioLinks: item.bio_links?.map(link => link.url),
945 raw: item
946 });
947 }
948 }
949 }
950
951 return results;
952}
953
954window.formatProfile = function(prepared) {
955 return prepared.map(item => ({
956 id: item.id,
957 id2: item.username,
958 highlight: { id: item.id },
959 raw: item.raw,
960 formatted: {
961 "id": item.id,
962 "Username": item.username || "Not Available",
963 "Full Name": item.fullName || "Not Available",
964 "Biography": item.biography || "Not Available",
965 "Profile URL": item.username ? `https://www.instagram.com/${item.username}/` : "Not Available",
966 "External URL": item.externalUrl || "Not Available",
967 "Follower Count": item.followerCount || "Not Available",
968 "Following Count": item.followingCount || "Not Available",
969 "Post Count": item.mediaCount || "Not Available",
970 "Is Verified": formatBoolean(item.isVerified),
971 "Is Private": formatBoolean(item.isPrivate),
972 "Is Business": formatBoolean(item.isBusiness),
973 "Category": item.category || "Not Available",
974 "Profile Picture URL": item.profilePicUrl || "Not Available",
975 "All Bio Links": joinList(item.bioLinks)
976 }
977 }));
978}
979
980window.profile = function(rawData) {
981 try {
982 const prepared = prepareProfile(rawData);
983 return formatProfile(prepared);
984 } catch (error) {
985 return [];
986 }
987}
988
989
990
991window.prepareUsers = function(rawData) {
992 const results = [];
993 const seen = new Set();
994
995 for (const entry of rawData) {
996 const dataItems = Array.isArray(entry.data) ? entry.data : [entry.data];
997 for (const data of dataItems) {
998 const users = searchField(data, "profile_pic_url");
999
1000 for (const item of users) {
1001 const userId = item.pk?.toString() || item.id?.toString();
1002 if (!userId || seen.has(userId)) continue;
1003 seen.add(userId);
1004
1005 results.push({
1006 id: userId,
1007 username: item.username,
1008 fullName: item.full_name,
1009 isPrivate: item.is_private,
1010 isVerified: item.is_verified,
1011 profilePicUrl: item.profile_pic_url,
1012 hasAnonPic: item.has_anonymous_profile_picture,
1013 latestStoryTime: item.latest_reel_media ? new Date(item.latest_reel_media * 1000).toISOString() : null,
1014 raw: item
1015 });
1016 }
1017 }
1018 }
1019
1020 return results;
1021}
1022
1023window.formatUsers = function(prepared) {
1024 return prepared.map(item => ({
1025 id: item.id,
1026 id2: item.username,
1027 highlight: { id2: item.username },
1028 raw: item.raw,
1029 formatted: {
1030 "id": item.id,
1031 "Username": item.username || "Not Available",
1032 "Full Name": item.fullName || "Not Available",
1033 "Profile URL": item.username ? `https://www.instagram.com/${item.username}/` : "Not Available",
1034 "Is Private": formatBoolean(item.isPrivate),
1035 "Is Verified": formatBoolean(item.isVerified),
1036 "Profile Picture URL": item.profilePicUrl || "Not Available",
1037 "Has Anonymous Profile Picture": formatBoolean(item.hasAnonPic),
1038 "Latest Story Time": item.latestStoryTime || "Not Available"
1039 }
1040 }));
1041}
1042
1043window.followers = function(rawData) {
1044 try {
1045 const prepared = prepareUsers(rawData);
1046 return formatUsers(prepared);
1047 } catch (error) {
1048 return [];
1049 }
1050}
1051
1052window.following = function(rawData) {
1053 try {
1054 const prepared = prepareUsers(rawData);
1055 return formatUsers(prepared);
1056 } catch (error) {
1057 return [];
1058 }
1059}