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 const connection = item?.xdt_fbsearch__top_serp_graphql;
445 if (connection?.edges?.length > 0) {
446 for (const edge of (connection.edges || [])) {
447 const items = edge.node?.items || [];
448 for (const mediaItem of items) {
449 const fragKey = "usePolarisKeywordSearchRelayReduxSync_media";
450 const frag = mediaItem?.[fragKey]?.__fragments?.[fragKey];
451 const post = frag && Object.keys(frag).length > 2 ? frag : mediaItem;
452 const postId = post.pk?.toString() || post.id?.toString();
453 if (!postId || !post.code || seen.has(postId)) continue;
454 seen.add(postId);
455 const isReel = post.media_type === 2;
456 results.push({
457 id: postId,
458 code: post.code,
459 user: post.user || mediaItem.user,
460 type: getPostType(post.media_type),
461 text: post.caption?.text,
462 image: post.image_versions2?.candidates?.[0]?.url,
463 video: post.video_versions?.[0]?.url,
464 likes: post.like_count?.toString(),
465 commentsCount: post.comment_count?.toString(),
466 url: `https://www.instagram.com/${isReel ? "reel" : "p"}/${post.code}/`,
467 date: post.taken_at ? new Date(post.taken_at * 1000).toISOString() : null,
468 commentsDisabled: post.comments_disabled,
469 accessibilityCaption: post.accessibility_caption,
470 raw: mediaItem
471 });
472 }
473 }
474 continue;
475 }
476
477 if (item && "isFetching" in item && Array.isArray(item.posts)) {
478 for (const post of item.posts) {
479 const postId = post.id?.toString();
480 if (!postId || seen.has(postId)) continue;
481 if (post.isSponsored) continue;
482
483 seen.add(postId);
484 const owner = post.owner;
485 const isReel = post.productType === "clips" || post.isVideo;
486
487 results.push({
488 id: postId,
489 code: post.code,
490 user: owner ? {
491 username: owner.username,
492 full_name: owner.fullName,
493 profile_pic_url: owner.profilePictureUrl,
494 is_verified: owner.isVerified
495 } : null,
496 type: getSavedPostType(post),
497 text: post.caption,
498 image: post.src || post.displayResources?.[0]?.src,
499 video: post.videoResources?.[0]?.src,
500 likes: post.numLikes?.toString(),
501 commentsCount: null,
502 url: post.code ? `https://www.instagram.com/${isReel ? "reel" : "p"}/${post.code}/` : null,
503 date: post.postedAt ? new Date(post.postedAt * 1000).toISOString() : null,
504 commentsDisabled: post.commentsDisabled,
505 accessibilityCaption: post.accessibilityCaption,
506 raw: post
507 });
508 }
509 continue;
510 }
511
512 if (item instanceof Map) {
513 cacheUsersFromData(item);
514 let posts = searchFieldMap(item, "sponsor_tags");
515 if (posts.length === 0) {
516 posts = searchFieldMap(item, "clips_tab_pinned_user_ids");
517 }
518 posts = posts.map(p => resolveRefs(p, item));
519
520 for (const post of posts) {
521 const postId = post.id?.toString() || post.pk?.toString();
522 if (!postId || seen.has(postId)) continue;
523
524 if (!("clips_tab_pinned_user_ids" in post) && ("sponsor_tags" in post)) {
525 if (post.is_paid_partnership !== false) continue;
526 }
527
528 seen.add(postId);
529 const user = getCachedUser(post.user);
530 const isReel = post.product_type === "clips" || post.media_type === 2;
531
532 results.push({
533 id: postId,
534 code: post.code,
535 user,
536 type: getPostType(post.media_type),
537 text: post.caption?.text,
538 image: getImageUrl(post),
539 video: post.video_versions?.[0]?.url,
540 likes: post.like_count?.toString(),
541 commentsCount: post.comment_count?.toString(),
542 url: post.code ? `https://www.instagram.com/${isReel ? "reel" : "p"}/${post.code}/` : null,
543 date: post.taken_at ? new Date(post.taken_at * 1000).toISOString() : null,
544 commentsDisabled: post.comments_disabled,
545 accessibilityCaption: post.accessibility_caption,
546 raw: post
547 });
548 }
549 continue;
550 }
551
552 const edges = item?.data?.xdt_api__v1__feed__user_timeline_graphql_connection?.edges;
553 if (edges) {
554 for (const edge of edges) {
555 const post = edge.node;
556 const postId = post.id?.toString() || post.pk?.toString();
557 if (!postId || seen.has(postId)) continue;
558
559 seen.add(postId);
560 const isReel = post.product_type === "clips" || post.media_type === 2;
561
562 results.push({
563 id: postId,
564 code: post.code,
565 user: post.user,
566 type: getPostType(post.media_type),
567 text: post.caption?.text,
568 image: post.image_versions2?.candidates?.[0]?.url,
569 video: post.video_versions?.[0]?.url,
570 likes: post.like_count?.toString(),
571 commentsCount: post.comment_count?.toString(),
572 url: post.code ? `https://www.instagram.com/${isReel ? "reel" : "p"}/${post.code}/` : null,
573 date: post.taken_at ? new Date(post.taken_at * 1000).toISOString() : null,
574 commentsDisabled: post.comments_disabled,
575 accessibilityCaption: post.accessibility_caption,
576 raw: edge
577 });
578 }
579 continue;
580 }
581
582 cacheUsersFromData(item);
583 let posts = searchField(item, "media_notes");
584 if (posts.length === 0) {
585 posts = searchField(item, "clips_tab_pinned_user_ids");
586 }
587
588 for (const post of posts) {
589 const postId = post.id?.toString() || post.pk?.toString();
590 if (!postId || seen.has(postId)) continue;
591
592 if (!("clips_tab_pinned_user_ids" in post) && ("sponsor_tags" in post)) {
593 if (post.is_paid_partnership !== false) continue;
594 }
595
596 seen.add(postId);
597 const user = getCachedUser(post.user);
598 const isReel = post.product_type === "clips" || post.media_type === 2;
599
600 results.push({
601 id: postId,
602 code: post.code,
603 user,
604 type: getPostType(post.media_type),
605 text: post.caption?.text,
606 image: getImageUrl(post),
607 video: post.video_versions?.[0]?.url,
608 likes: post.like_count?.toString(),
609 commentsCount: post.comment_count?.toString(),
610 url: post.code ? `https://www.instagram.com/${isReel ? "reel" : "p"}/${post.code}/` : null,
611 date: post.taken_at ? new Date(post.taken_at * 1000).toISOString() : null,
612 commentsDisabled: post.comments_disabled,
613 accessibilityCaption: post.accessibility_caption,
614 raw: post
615 });
616 }
617 }
618
619 return results;
620}
621
622window.formatPosts = function(prepared) {
623 return prepared.map(item => ({
624 id: item.id,
625 id2: item.code,
626 highlight: { id2: item.code },
627 raw: item.raw,
628 formatted: {
629 "id": item.id,
630 "Post Author": item.user?.username || "Not Available",
631 "Post Author Full Name": item.user?.full_name || item.user?.fullName || "Not Available",
632 "Post Author Image": item.user?.profile_pic_url || item.user?.profilePictureUrl || "Not Available",
633 "Post Author URL": item.user?.username ? `https://www.instagram.com/${item.user.username}/` : "Not Available",
634 "Post Author Is Verified": formatBoolean(item.user?.is_verified ?? item.user?.isVerified),
635 "Post Type": item.type || "Not Available",
636 "Post Text": item.text || "Not Available",
637 "Post Image": item.image || "Not Available",
638 "Post Video": item.video || "Not Available",
639 "Post Likes": item.likes || "Not Available",
640 "Post Comments Count": item.commentsCount || "Not Available",
641 "Post URL": item.url || "Not Available",
642 "Post Date": item.date || "Not Available",
643 "Is Comments Disabled": formatBoolean(item.commentsDisabled),
644 "Post Accessibility Caption": item.accessibilityCaption || "Not Available"
645 }
646 }));
647}
648
649window.posts = function(rawData) {
650 try {
651 if (isInstagramReelsUrl()) return [];
652
653 let prepared = [];
654 const seen = new Set();
655
656 for (const entry of rawData) {
657 let batch = [];
658 if (entry.metadata.method === "request") {
659 batch = preparePostsFromRequest(entry.data);
660 } else if (entry.metadata.method === "dom") {
661 batch = preparePostsFromDom(entry.data);
662 } else if (entry.metadata.method === "react") {
663 batch = preparePostsFromReact(entry.data);
664 }
665 for (const item of batch) {
666 if (!seen.has(item.id)) {
667 seen.add(item.id);
668 prepared.push(item);
669 }
670 }
671 }
672
673 return formatPosts(prepared);
674 } catch (error) {
675 return [];
676 }
677}
678
679
680
681window.prepareStories = function(rawData) {
682 const results = [];
683 const seen = new Set();
684 const userStore = new Map();
685
686 for (const entry of rawData) {
687 const dataItems = Array.isArray(entry.data) ? entry.data : [entry.data];
688 for (const data of dataItems) {
689 const stories = searchField(data, "story_cta");
690 searchField(data, "profile_pic_url").forEach(user => {
691 userStore.set(user.id, user);
692 });
693
694 for (const item of stories) {
695 const storyId = item.pk?.toString() || item.id?.toString();
696 if (!storyId || seen.has(storyId)) continue;
697 seen.add(storyId);
698
699 let user = item.user;
700 if (user && !user.profile_pic_url && userStore.get(user.id)) {
701 user = userStore.get(user.id);
702 }
703
704 results.push({
705 id: storyId,
706 type: getPostType(item.media_type),
707 image: item.image_versions2?.candidates?.[0]?.url,
708 video: item.video_versions?.[0]?.url,
709 link: item.pk && user?.username ? `https://www.instagram.com/stories/${user.username}/${item.pk}/` : null,
710 date: item.taken_at ? new Date(item.taken_at * 1000).toISOString() : null,
711 expiringAt: item.expiring_at ? new Date(item.expiring_at * 1000).toISOString() : null,
712 accessibilityCaption: item.accessibility_caption,
713 user,
714 bloksFullName: item.story_bloks_stickers?.[0]?.bloks_sticker?.sticker_data?.ig_mention?.full_name,
715 raw: item
716 });
717 }
718 }
719 }
720
721 return results;
722}
723
724window.formatStories = function(prepared) {
725 return prepared.map(item => ({
726 id: item.id,
727 highlight: { id: item.id },
728 raw: item.raw,
729 formatted: {
730 "id": item.id,
731 "Story Type": item.type || "Not Available",
732 "Story Image": item.image || "Not Available",
733 "Story Video": item.video || "Not Available",
734 "Story Link": item.link || "Not Available",
735 "Story Date": item.date || "Not Available",
736 "Story Expiring At": item.expiringAt || "Not Available",
737 "Story Accessibility Caption": item.accessibilityCaption || "Not Available",
738 "Author Username": item.user?.username || "Not Available",
739 "Author Full Name": item.user?.full_name || item.bloksFullName || "Not Available",
740 "Author Image": item.user?.profile_pic_url || "Not Available",
741 "Author URL": item.user?.username ? `https://www.instagram.com/${item.user.username}/` : "Not Available",
742 "Author Is Verified": formatBoolean(item.user?.is_verified)
743 }
744 }));
745}
746
747window.stories = function(rawData) {
748 try {
749 const prepared = prepareStories(rawData);
750 return formatStories(prepared);
751 } catch (error) {
752 return [];
753 }
754}
755
756
757
758window.preparePostDetails = function(rawData) {
759 const byPostKey = new Map();
760 const reelsCode = getCurrentInstagramReelsCode();
761 const currentUrl = getCurrentInstagramUrl();
762
763 for (const entry of rawData) {
764 const dataItems = Array.isArray(entry.data) ? entry.data : [entry.data];
765 const entryUrl = entry.metadata?.url || entry.metadata?.href || entry.url || entry.sourceUrl;
766 const entryCode = getInstagramCodeFromUrl(entryUrl);
767
768 for (const data of dataItems) {
769 cacheUsersFromData(data);
770 }
771
772 for (const data of dataItems) {
773 const items = getPostDetailCandidates(data);
774
775 for (const item of items) {
776 cachePostDetailItem(item);
777 const prepared = preparePostDetailItem(item);
778 if (!prepared) continue;
779
780 const targetCode = entryCode || reelsCode;
781 if (targetCode) {
782 if (item.code !== targetCode) continue;
783 } else if (!item.code || !currentUrl.includes(item.code)) {
784 continue;
785 }
786 const postKey = item.code || prepared.id;
787 byPostKey.set(postKey, mergePostDetails(byPostKey.get(postKey), prepared));
788 }
789 }
790 }
791
792 if (reelsCode && postDetailsCache.has(reelsCode)) {
793 console.log("Instagram postDetails cache check", {
794 currentUrl,
795 reelsCode,
796 cacheSize: postDetailsCache.size,
797 cacheKeys: Array.from(postDetailsCache.keys()),
798 cacheHit: true
799 });
800 const cachedPrepared = preparePostDetailItem(postDetailsCache.get(reelsCode));
801 if (cachedPrepared) {
802 byPostKey.set(reelsCode, mergePostDetails(byPostKey.get(reelsCode), cachedPrepared));
803 }
804 } else if (reelsCode) {
805 console.log("Instagram postDetails cache check", {
806 currentUrl,
807 reelsCode,
808 cacheSize: postDetailsCache.size,
809 cacheKeys: Array.from(postDetailsCache.keys()),
810 cacheHit: false
811 });
812 }
813
814 return Array.from(byPostKey.values());
815}
816
817window.formatPostDetails = function(prepared) {
818 return prepared.map(item => ({
819 id: item.id,
820 id2: item.code,
821 highlight: { id: item.id },
822 raw: item.raw,
823 formatted: {
824 "id": item.id,
825 "Post Type": item.type || "Not Available",
826 "Caption": item.caption || "Not Available",
827 "Like Count": item.likeCount || "Not Available",
828 "Comment Count": item.commentCount || "Not Available",
829 "View Count": item.viewCount || "Not Available",
830 "Author Username": item.user?.username || "Not Available",
831 "Author Full Name": item.user?.full_name || "Not Available",
832 "Author ID": item.user?.pk?.toString() || item.user?.id?.toString() || "Not Available",
833 "Author URL": item.user?.username ? `https://www.instagram.com/${item.user.username}/` : "Not Available",
834 "Author Is Verified": formatBoolean(item.user?.is_verified),
835 "Author Profile Pic": item.user?.profile_pic_url || item.user?.hd_profile_pic_url_info?.url || "Not Available",
836 "Post URL": item.url || "Not Available",
837 "Image URL": item.imageUrl || "Not Available",
838 "Video URL": item.videoUrl || "Not Available",
839 "Cover Image": item.coverImage || "Not Available",
840 "Posted At": item.postedAt || "Not Available",
841 "Location": item.location || "Not Available",
842 "Duration": item.duration || "Not Available",
843 "Has Audio": formatBoolean(item.hasAudio),
844 "Audio Title": item.audioTitle || "Not Available",
845 "Audio Artist": item.audioArtist || "Not Available",
846 "Tagged Users": item.taggedUsers || "Not Available",
847 "Is Carousel": formatBoolean(item.isCarousel),
848 "Carousel Count": item.carouselCount || "Not Available",
849 "Original Width": item.originalWidth || "Not Available",
850 "Original Height": item.originalHeight || "Not Available",
851 "Is Paid Partnership": formatBoolean(item.isPaidPartnership),
852 "Comments Disabled": formatBoolean(item.commentsDisabled),
853 "Likes Disabled": formatBoolean(item.likesDisabled),
854 "Accessibility Caption": item.accessibilityCaption || "Not Available"
855 }
856 }));
857}
858
859window.postDetails = function(rawData) {
860 console.log(rawData)
861 try {
862 const prepared = preparePostDetails(rawData);
863 return formatPostDetails(prepared);
864 } catch (error) {
865 return [];
866 }
867}
868
869
870
871window.prepareComments = function(rawData) {
872 const results = [];
873 const seen = new Set();
874
875 for (const entry of rawData) {
876 const dataItems = Array.isArray(entry.data) ? entry.data : [entry.data];
877 for (const data of dataItems) {
878 const comments = searchField(data, "comment_like_count");
879
880 for (const item of comments) {
881 const commentId = item.pk?.toString() || item.id?.toString();
882 if (!commentId || seen.has(commentId)) continue;
883 seen.add(commentId);
884
885 const commentDate = item.created_at ? new Date(item.created_at * 1000).toISOString() : null;
886
887 results.push({
888 id: commentId,
889 date: commentDate,
890 text: item.text,
891 media: item.giphy_media_info?.first_party_cdn_proxied_images?.fixed_height?.url,
892 likes: item.comment_like_count?.toString(),
893 user: item.user,
894 isReply: !!item.parent_comment_id,
895 parentCommentId: item.parent_comment_id?.toString(),
896 childCommentCount: item.child_comment_count,
897 raw: item
898 });
899 }
900 }
901 }
902
903 return results;
904}
905
906window.formatComments = function(prepared) {
907 return prepared.map(item => ({
908 id: item.id,
909 id2: item.date,
910 highlight: { id2: item.date },
911 raw: item.raw,
912 formatted: {
913 "id": item.id,
914 "Comment Text": item.text || "Not Available",
915 "Comment Media": item.media || "Not Available",
916 "Comment Date": item.date || "Not Available",
917 "Comment Likes": item.likes || "Not Available",
918 "Author Username": item.user?.username || "Not Available",
919 "Author ID": item.user?.pk || item.user?.id || "Not Available",
920 "Author URL": item.user?.username ? `https://www.instagram.com/${item.user.username}/` : "Not Available",
921 "Author Is Verified": formatBoolean(item.user?.is_verified),
922 "Is Reply": formatBoolean(item.isReply),
923 "Parent Comment ID": item.parentCommentId || "Not Available",
924 "Has Replies": formatBoolean(item.childCommentCount > 0),
925 "Reply Count": item.childCommentCount?.toString() || "Not Available"
926 }
927 }));
928}
929
930window.comments = function(rawData) {
931 try {
932 const prepared = prepareComments(rawData);
933 return formatComments(prepared);
934 } catch (error) {
935 return [];
936 }
937}
938
939
940
941window.prepareProfile = function(rawData) {
942 const results = [];
943 const seen = new Set();
944
945 for (const entry of rawData) {
946 const dataItems = Array.isArray(entry.data) ? entry.data : [entry.data];
947
948 for (const data of dataItems) {
949 let users = [];
950
951 if (data instanceof Map) {
952 users = searchFieldMap(data, "biography");
953 users = users.map(user => resolveRefs(user, data));
954 } else {
955 users = searchField(data, "biography");
956 }
957
958 for (const item of users) {
959 const userId = item.pk?.toString() || item.id?.toString();
960 if (!userId || seen.has(userId)) continue;
961 seen.add(userId);
962
963 results.push({
964 id: userId,
965 username: item.username,
966 fullName: item.full_name,
967 biography: item.biography,
968 externalUrl: item.external_url,
969 followerCount: item.follower_count?.toString(),
970 followingCount: item.following_count?.toString(),
971 mediaCount: item.media_count?.toString(),
972 isVerified: item.is_verified,
973 isPrivate: item.is_private,
974 isBusiness: item.is_business,
975 category: item.category,
976 profilePicUrl: item.hd_profile_pic_url_info?.url || item.profile_pic_url,
977 bioLinks: item.bio_links?.map(link => link.url),
978 raw: item
979 });
980 }
981 }
982 }
983
984 return results;
985}
986
987window.formatProfile = function(prepared) {
988 return prepared.map(item => ({
989 id: item.id,
990 id2: item.username,
991 highlight: { id: item.id },
992 raw: item.raw,
993 formatted: {
994 "id": item.id,
995 "Username": item.username || "Not Available",
996 "Full Name": item.fullName || "Not Available",
997 "Biography": item.biography || "Not Available",
998 "Profile URL": item.username ? `https://www.instagram.com/${item.username}/` : "Not Available",
999 "External URL": item.externalUrl || "Not Available",
1000 "Follower Count": item.followerCount || "Not Available",
1001 "Following Count": item.followingCount || "Not Available",
1002 "Post Count": item.mediaCount || "Not Available",
1003 "Is Verified": formatBoolean(item.isVerified),
1004 "Is Private": formatBoolean(item.isPrivate),
1005 "Is Business": formatBoolean(item.isBusiness),
1006 "Category": item.category || "Not Available",
1007 "Profile Picture URL": item.profilePicUrl || "Not Available",
1008 "All Bio Links": joinList(item.bioLinks)
1009 }
1010 }));
1011}
1012
1013window.profile = function(rawData) {
1014 try {
1015 const prepared = prepareProfile(rawData);
1016 return formatProfile(prepared);
1017 } catch (error) {
1018 return [];
1019 }
1020}
1021
1022
1023
1024window.prepareUsers = function(rawData) {
1025 const results = [];
1026 const seen = new Set();
1027
1028 for (const entry of rawData) {
1029 const dataItems = Array.isArray(entry.data) ? entry.data : [entry.data];
1030 for (const data of dataItems) {
1031 const users = searchField(data, "profile_pic_url");
1032
1033 for (const item of users) {
1034 const userId = item.pk?.toString() || item.id?.toString();
1035 if (!userId || seen.has(userId)) continue;
1036 seen.add(userId);
1037
1038 results.push({
1039 id: userId,
1040 username: item.username,
1041 fullName: item.full_name,
1042 isPrivate: item.is_private,
1043 isVerified: item.is_verified,
1044 profilePicUrl: item.profile_pic_url,
1045 hasAnonPic: item.has_anonymous_profile_picture,
1046 latestStoryTime: item.latest_reel_media ? new Date(item.latest_reel_media * 1000).toISOString() : null,
1047 raw: item
1048 });
1049 }
1050 }
1051 }
1052
1053 return results;
1054}
1055
1056window.formatUsers = function(prepared) {
1057 return prepared.map(item => ({
1058 id: item.id,
1059 id2: item.username,
1060 highlight: { id2: item.username },
1061 raw: item.raw,
1062 formatted: {
1063 "id": item.id,
1064 "Username": item.username || "Not Available",
1065 "Full Name": item.fullName || "Not Available",
1066 "Profile URL": item.username ? `https://www.instagram.com/${item.username}/` : "Not Available",
1067 "Is Private": formatBoolean(item.isPrivate),
1068 "Is Verified": formatBoolean(item.isVerified),
1069 "Profile Picture URL": item.profilePicUrl || "Not Available",
1070 "Has Anonymous Profile Picture": formatBoolean(item.hasAnonPic),
1071 "Latest Story Time": item.latestStoryTime || "Not Available"
1072 }
1073 }));
1074}
1075
1076window.followers = function(rawData) {
1077 try {
1078 const prepared = prepareUsers(rawData);
1079 return formatUsers(prepared);
1080 } catch (error) {
1081 return [];
1082 }
1083}
1084
1085window.following = function(rawData) {
1086 try {
1087 const prepared = prepareUsers(rawData);
1088 return formatUsers(prepared);
1089 } catch (error) {
1090 return [];
1091 }
1092}