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