@chilfish/gallery-dl-instagram 0.2.0 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,14 +1,11 @@
1
- import { _ as Metadata, a as ExtractorOptions, b as Storage, c as ConfigManager, d as DirectoryMsg, f as ExtractorClass, g as MessageIter, h as Message, i as Extractor, l as Config, m as HttpResponse, n as InstagramSDK, o as Logger, p as HttpClient, r as SDKOptions, s as noopLogger, t as ExtractOptions, u as ConfigValue, v as QueueMsg, x as UrlMsg, y as RequestConfig } from "./sdk-CK9x5wFL.mjs";
1
+ import { _ as Metadata, a as ExtractorOptions, b as Storage, c as ConfigManager, d as DirectoryMsg, f as ExtractorClass, g as MessageIter, h as Message, i as Extractor, l as Config, m as HttpResponse, n as InstagramSDK, o as Logger, p as HttpClient, r as SDKOptions, s as noopLogger, t as ExtractOptions, u as ConfigValue, v as QueueMsg, x as UrlMsg, y as RequestConfig } from "./sdk-DyZz22bT.mjs";
2
2
 
3
3
  //#region src/core/job.d.ts
4
4
  declare abstract class Job {
5
5
  readonly extractor: Extractor;
6
6
  status: number;
7
7
  constructor(extractor: Extractor);
8
- /**
9
- * Main entry point. Calls ``extractor[Symbol.asyncIterator]()`` and
10
- * dispatches every yielded message.
11
- */
8
+ /** Main entry point. Dispatches every yielded message. */
12
9
  run(): Promise<number>;
13
10
  /** Override in subclasses to print a summary. */
14
11
  protected _report(): void;
@@ -16,7 +13,8 @@ declare abstract class Job {
16
13
  abstract handleUrl(msg: UrlMsg): Promise<void>;
17
14
  abstract handleQueue(msg: QueueMsg): Promise<void>;
18
15
  }
19
- /** An in-memory archive: category → Set<archive-key>. */
16
+ //#endregion
17
+ //#region src/core/download-job.d.ts
20
18
  type ArchiveMap = Map<string, Set<string>>;
21
19
  declare class DownloadJob extends Job {
22
20
  /** Base output directory (prepended to all paths). */
@@ -25,32 +23,24 @@ declare class DownloadJob extends Job {
25
23
  private _currentDir;
26
24
  /** In-memory archive keyed by archive format. */
27
25
  readonly archive: ArchiveMap;
28
- /**
29
- * Registry of per-category "archive formats" — the key is formed
30
- * by interpolating this format string over the metadata.
31
- */
32
26
  private readonly _archiveFmts;
33
27
  private _postCount;
34
28
  private _fileCount;
35
29
  private _downloadedBytes;
36
30
  private _skippedCount;
37
31
  registerArchive(category: string, format: string): void;
38
- /** Simple format-string interpolation for archive keys. */
39
32
  private _interp;
40
- /** Check whether this URL has already been downloaded (and skip). */
41
33
  private _isArchived;
42
- /** Mark a post/media as archived. */
43
34
  private _archive;
44
- /** Handlers */
45
35
  handleDirectory(msg: DirectoryMsg): Promise<void>;
46
36
  handleUrl(msg: UrlMsg): Promise<void>;
47
37
  handleQueue(msg: QueueMsg): Promise<void>;
48
- /** Report */
49
38
  protected _report(): void;
50
- /** Path builders */
51
39
  private _buildDirPath;
52
40
  private _buildFilename;
53
41
  }
42
+ //#endregion
43
+ //#region src/core/print-job.d.ts
54
44
  declare class PrintJob extends Job {
55
45
  private _currentDir;
56
46
  private _files;
@@ -61,7 +51,6 @@ declare class PrintJob extends Job {
61
51
  handleDirectory(msg: DirectoryMsg): Promise<void>;
62
52
  handleUrl(msg: UrlMsg): Promise<void>;
63
53
  handleQueue(msg: QueueMsg): Promise<void>;
64
- /** Output */
65
54
  private _flushPost;
66
55
  private _wrap;
67
56
  protected _report(): void;
@@ -108,6 +97,7 @@ interface InstagramUser {
108
97
  count: number;
109
98
  };
110
99
  followed_by_viewer?: boolean;
100
+ is_verified?: boolean;
111
101
  }
112
102
  interface ImageCandidate {
113
103
  url: string;
@@ -152,19 +142,25 @@ interface MusicSticker {
152
142
  interface MusicAssetInfo {
153
143
  id: string;
154
144
  title?: string;
145
+ sanitized_title?: string;
146
+ subtitle?: string;
155
147
  display_artist?: string;
156
148
  ig_artist?: string;
149
+ ig_username?: string;
157
150
  duration_in_ms?: number;
158
151
  highlight_start_times_in_ms?: number[];
159
152
  progressive_download_url: string;
160
153
  cover_artwork_uri?: string;
154
+ cover_artwork_thumbnail_uri?: string;
155
+ has_lyrics?: boolean;
156
+ is_explicit?: boolean;
161
157
  }
162
158
  interface MusicConsumptionInfo {
163
159
  display_artist?: string;
164
160
  ig_artist?: string;
165
161
  }
166
162
  interface MusicMetadata {
167
- music_info?: MusicAssetInfo;
163
+ music_info?: MusicSticker;
168
164
  }
169
165
  interface InstagramPost {
170
166
  pk: string;
@@ -285,9 +281,14 @@ interface ParsedMedia {
285
281
  audio_url?: string;
286
282
  audio_user?: string;
287
283
  audio_title?: string;
284
+ audio_subtitle?: string;
288
285
  audio_artist?: string;
289
286
  audio_duration?: number;
290
287
  audio_timestamps?: number[];
288
+ audio_cover_artwork_uri?: string;
289
+ audio_cover_artwork_thumbnail_uri?: string;
290
+ audio_has_lyrics?: boolean;
291
+ audio_is_explicit?: boolean;
291
292
  _ytdl_manifest_data?: string;
292
293
  sidecar_media_id?: string;
293
294
  sidecar_shortcode?: string;
@@ -433,24 +434,48 @@ declare abstract class InstagramExtractor extends Extractor {
433
434
  protected _assignUser(user: InstagramUser): void;
434
435
  }
435
436
  //#endregion
436
- //#region src/instagram/extractors.d.ts
437
- declare class InstagramPostExtractor extends InstagramExtractor {
438
- static readonly subcategory = "post";
437
+ //#region src/instagram/extractors/avatar.d.ts
438
+ declare class InstagramAvatarExtractor extends InstagramExtractor {
439
+ static readonly subcategory = "avatar";
439
440
  static pattern: RegExp;
440
- readonly subcategory = "post";
441
+ readonly subcategory = "avatar";
441
442
  constructor(opts: InstagramExtractorOptions);
442
- static fromURL(url: string, opts: InstagramExtractorOptions): InstagramPostExtractor | null;
443
+ static fromURL(url: string, opts: InstagramExtractorOptions): InstagramAvatarExtractor | null;
443
444
  posts(): AsyncGenerator<InstagramPost>;
444
445
  }
445
- declare class InstagramUserExtractor extends InstagramExtractor {
446
- static readonly subcategory = "user";
446
+ //#endregion
447
+ //#region src/instagram/extractors/highlights.d.ts
448
+ declare class InstagramHighlightsExtractor extends InstagramExtractor {
449
+ static readonly subcategory = "highlights";
447
450
  static pattern: RegExp;
448
- readonly subcategory = "user";
451
+ readonly subcategory = "highlights";
449
452
  constructor(opts: InstagramExtractorOptions);
450
- static fromURL(url: string, opts: InstagramExtractorOptions): InstagramUserExtractor | null;
453
+ static fromURL(url: string, opts: InstagramExtractorOptions): InstagramHighlightsExtractor | null;
454
+ posts(): AsyncGenerator<InstagramPost>;
455
+ }
456
+ //#endregion
457
+ //#region src/instagram/extractors/info.d.ts
458
+ declare class InstagramInfoExtractor extends InstagramExtractor {
459
+ static readonly subcategory = "info";
460
+ static pattern: RegExp;
461
+ readonly subcategory = "info";
462
+ constructor(opts: InstagramExtractorOptions);
463
+ static fromURL(url: string, opts: InstagramExtractorOptions): InstagramInfoExtractor | null;
451
464
  items(): MessageIter;
452
465
  posts(): AsyncGenerator<InstagramPost>;
453
466
  }
467
+ //#endregion
468
+ //#region src/instagram/extractors/post.d.ts
469
+ declare class InstagramPostExtractor extends InstagramExtractor {
470
+ static readonly subcategory = "post";
471
+ static pattern: RegExp;
472
+ readonly subcategory = "post";
473
+ constructor(opts: InstagramExtractorOptions);
474
+ static fromURL(url: string, opts: InstagramExtractorOptions): InstagramPostExtractor | null;
475
+ posts(): AsyncGenerator<InstagramPost>;
476
+ }
477
+ //#endregion
478
+ //#region src/instagram/extractors/posts-list.d.ts
454
479
  declare class InstagramPostsExtractor extends InstagramExtractor {
455
480
  static readonly subcategory = "posts";
456
481
  static pattern: RegExp;
@@ -459,6 +484,8 @@ declare class InstagramPostsExtractor extends InstagramExtractor {
459
484
  static fromURL(url: string, opts: InstagramExtractorOptions): InstagramPostsExtractor | null;
460
485
  posts(): AsyncGenerator<InstagramPost>;
461
486
  }
487
+ //#endregion
488
+ //#region src/instagram/extractors/reels-list.d.ts
462
489
  declare class InstagramReelsExtractor extends InstagramExtractor {
463
490
  static readonly subcategory = "reels";
464
491
  static pattern: RegExp;
@@ -467,16 +494,18 @@ declare class InstagramReelsExtractor extends InstagramExtractor {
467
494
  static fromURL(url: string, opts: InstagramExtractorOptions): InstagramReelsExtractor | null;
468
495
  posts(): AsyncGenerator<InstagramPost>;
469
496
  }
470
- declare class InstagramTaggedExtractor extends InstagramExtractor {
471
- static readonly subcategory = "tagged";
497
+ //#endregion
498
+ //#region src/instagram/extractors/saved.d.ts
499
+ declare class InstagramSavedExtractor extends InstagramExtractor {
500
+ static readonly subcategory = "saved";
472
501
  static pattern: RegExp;
473
- readonly subcategory = "tagged";
474
- private _taggedUserId;
502
+ readonly subcategory = "saved";
475
503
  constructor(opts: InstagramExtractorOptions);
476
- static fromURL(url: string, opts: InstagramExtractorOptions): InstagramTaggedExtractor | null;
477
- metadata(): Promise<Record<string, unknown>>;
504
+ static fromURL(url: string, opts: InstagramExtractorOptions): InstagramSavedExtractor | null;
478
505
  posts(): AsyncGenerator<InstagramPost>;
479
506
  }
507
+ //#endregion
508
+ //#region src/instagram/extractors/stories.d.ts
480
509
  declare class InstagramStoriesExtractor extends InstagramExtractor {
481
510
  static readonly subcategory = "stories";
482
511
  static pattern: RegExp;
@@ -487,14 +516,8 @@ declare class InstagramStoriesExtractor extends InstagramExtractor {
487
516
  static fromURL(url: string, opts: InstagramExtractorOptions): InstagramStoriesExtractor | null;
488
517
  posts(): AsyncGenerator<InstagramPost>;
489
518
  }
490
- declare class InstagramHighlightsExtractor extends InstagramExtractor {
491
- static readonly subcategory = "highlights";
492
- static pattern: RegExp;
493
- readonly subcategory = "highlights";
494
- constructor(opts: InstagramExtractorOptions);
495
- static fromURL(url: string, opts: InstagramExtractorOptions): InstagramHighlightsExtractor | null;
496
- posts(): AsyncGenerator<InstagramPost>;
497
- }
519
+ //#endregion
520
+ //#region src/instagram/extractors/tag.d.ts
498
521
  declare class InstagramTagExtractor extends InstagramExtractor {
499
522
  static readonly subcategory = "tag";
500
523
  static pattern: RegExp;
@@ -504,41 +527,41 @@ declare class InstagramTagExtractor extends InstagramExtractor {
504
527
  metadata(): Promise<Record<string, unknown>>;
505
528
  posts(): AsyncGenerator<InstagramPost>;
506
529
  }
507
- declare class InstagramInfoExtractor extends InstagramExtractor {
508
- static readonly subcategory = "info";
509
- static pattern: RegExp;
510
- readonly subcategory = "info";
511
- constructor(opts: InstagramExtractorOptions);
512
- static fromURL(url: string, opts: InstagramExtractorOptions): InstagramInfoExtractor | null;
513
- items(): MessageIter;
514
- posts(): AsyncGenerator<InstagramPost>;
515
- }
516
- declare class InstagramAvatarExtractor extends InstagramExtractor {
517
- static readonly subcategory = "avatar";
530
+ //#endregion
531
+ //#region src/instagram/extractors/tagged.d.ts
532
+ declare class InstagramTaggedExtractor extends InstagramExtractor {
533
+ static readonly subcategory = "tagged";
518
534
  static pattern: RegExp;
519
- readonly subcategory = "avatar";
535
+ readonly subcategory = "tagged";
536
+ private _taggedUserId;
520
537
  constructor(opts: InstagramExtractorOptions);
521
- static fromURL(url: string, opts: InstagramExtractorOptions): InstagramAvatarExtractor | null;
538
+ static fromURL(url: string, opts: InstagramExtractorOptions): InstagramTaggedExtractor | null;
539
+ metadata(): Promise<Record<string, unknown>>;
522
540
  posts(): AsyncGenerator<InstagramPost>;
523
541
  }
524
- declare class InstagramSavedExtractor extends InstagramExtractor {
525
- static readonly subcategory = "saved";
542
+ //#endregion
543
+ //#region src/instagram/extractors/user.d.ts
544
+ declare class InstagramUserExtractor extends InstagramExtractor {
545
+ static readonly subcategory = "user";
526
546
  static pattern: RegExp;
527
- readonly subcategory = "saved";
547
+ readonly subcategory = "user";
528
548
  constructor(opts: InstagramExtractorOptions);
529
- static fromURL(url: string, opts: InstagramExtractorOptions): InstagramSavedExtractor | null;
549
+ static fromURL(url: string, opts: InstagramExtractorOptions): InstagramUserExtractor | null;
550
+ items(): MessageIter;
530
551
  posts(): AsyncGenerator<InstagramPost>;
531
552
  }
532
553
  //#endregion
533
- //#region src/instagram/parsers.d.ts
534
- /** Main entry REST */
554
+ //#region src/instagram/parsers/graphql.d.ts
555
+ /** Parse a GraphQL post/edge response. */
556
+ declare function parsePostGraphql(post: Record<string, unknown>, cfg: ParserConfig): ParsedPost;
557
+ //#endregion
558
+ //#region src/instagram/parsers/rest.d.ts
559
+ /** Main entry — parse a REST post response. */
535
560
  declare function parsePostRest(post: InstagramPost, cfg: ParserConfig): ParsedPost;
536
- /** Tagged users */
561
+ /** Extract tagged users from various field formats. */
537
562
  declare function extractTaggedUsers(src: Record<string, unknown>, dest: ParsedMedia): void;
538
- /** Audio / music extraction */
563
+ /** Extract audio/music metadata from a story sticker. */
539
564
  declare function extractAudio(src: Record<string, unknown>, dest: Record<string, unknown>, sticker: MusicSticker, cfg: ParserConfig): ParsedMedia | null;
540
- /** GraphQL parser */
541
- declare function parsePostGraphql(post: Record<string, unknown>, cfg: ParserConfig): ParsedPost;
542
565
  //#endregion
543
566
  //#region src/message.d.ts
544
567
  declare function directory(metadata?: Metadata): DirectoryMsg;
package/dist/index.mjs CHANGED
@@ -1,2 +1,180 @@
1
- import { A as directory, C as nameExtFromURL, D as unquote, E as unescape, F as PrintJob, I as Extractor, L as noopLogger, M as url, N as DownloadJob, O as idFromShortcode, P as Job, R as ConfigManager, S as findTags, T as parseUnicodeEscapes, _ as parsePostRest, a as InstagramPostExtractor, b as extr, c as InstagramSavedExtractor, d as InstagramTaggedExtractor, f as InstagramUserExtractor, g as parsePostGraphql, h as extractTaggedUsers, i as InstagramInfoExtractor, j as queue, k as shortcodeFromId, l as InstagramStoriesExtractor, m as extractAudio, n as InstagramAvatarExtractor, o as InstagramPostsExtractor, p as InstagramExtractor, r as InstagramHighlightsExtractor, s as InstagramReelsExtractor, t as InstagramSDK, u as InstagramTagExtractor, v as InstagramRestAPI, w as parseInt, x as extract, y as ensureHttpScheme } from "./sdk-Bn0VCUIT.mjs";
1
+ import { A as directory, B as _YELLOW, C as extract, D as parseUnicodeEscapes, E as parseInt, F as Extractor, G as pad, H as c, I as noopLogger, K as ConfigManager, L as DownloadJob, M as url, N as idFromShortcode, O as unescape, P as shortcodeFromId, R as Job, S as extr, T as nameExtFromURL, U as dim, V as b, W as g, _ as extractAudio, a as InstagramTaggedExtractor, b as InstagramRestAPI, c as InstagramSavedExtractor, d as InstagramPostExtractor, f as InstagramInfoExtractor, g as parsePostGraphql, h as InstagramExtractor, i as InstagramUserExtractor, j as queue, k as unquote, l as InstagramReelsExtractor, m as InstagramAvatarExtractor, o as InstagramTagExtractor, p as InstagramHighlightsExtractor, s as InstagramStoriesExtractor, t as InstagramSDK, u as InstagramPostsExtractor, v as extractTaggedUsers, w as findTags, x as ensureHttpScheme, y as parsePostRest, z as _RESET } from "./sdk-E0L5ISZC.mjs";
2
+ //#region src/core/print-job.ts
3
+ var PrintJob = class PrintJob extends Job {
4
+ _currentDir = {};
5
+ _files = [];
6
+ _postCount = 0;
7
+ _fileCount = 0;
8
+ _width;
9
+ constructor(extractor) {
10
+ super(extractor);
11
+ this._width = Math.min(process.stdout.columns ?? 80, 100);
12
+ }
13
+ async handleDirectory(msg) {
14
+ if (this._postCount > 0) this._flushPost();
15
+ this._currentDir = { ...msg.metadata };
16
+ this._postCount++;
17
+ this._files = [];
18
+ }
19
+ async handleUrl(msg) {
20
+ const meta = {
21
+ ...this._currentDir,
22
+ ...msg.metadata
23
+ };
24
+ this._fileCount++;
25
+ const ext = meta.extension ?? "jpg";
26
+ const mid = meta.media_id ?? "?";
27
+ this._files.push({
28
+ num: meta.num ?? this._files.length + 1,
29
+ filename: `${mid}.${ext}`,
30
+ width: meta.width ?? 0,
31
+ height: meta.height ?? 0,
32
+ videoUrl: meta.video_url ?? null,
33
+ audioUrl: meta.audio_url ?? null,
34
+ audioTitle: meta.audio_title ?? void 0,
35
+ audioArtist: meta.audio_artist ?? void 0,
36
+ audioDuration: meta.audio_duration ?? void 0,
37
+ audioHasLyrics: meta.audio_has_lyrics ?? void 0,
38
+ audioIsExplicit: meta.audio_is_explicit ?? void 0,
39
+ coverArtworkUri: meta.audio_cover_artwork_uri ?? meta.audio_cover_artwork_thumbnail_uri ?? void 0
40
+ });
41
+ }
42
+ async handleQueue(msg) {
43
+ if (this._files.length > 0 || this._postCount > 0) this._flushPost();
44
+ this._postCount = 0;
45
+ this._files = [];
46
+ const extrClass = {
47
+ ...this._currentDir,
48
+ ...msg.metadata
49
+ }._extractor;
50
+ if (!extrClass || typeof extrClass !== "object") return;
51
+ const cls = extrClass;
52
+ const match = cls.pattern.exec(msg.url);
53
+ if (!match) return;
54
+ const parentExtr = this.extractor;
55
+ const childJob = new PrintJob(Reflect.construct(cls, [{
56
+ url: msg.url,
57
+ match,
58
+ config: parentExtr.config,
59
+ http: parentExtr.http,
60
+ storage: parentExtr.storage,
61
+ log: parentExtr.log
62
+ }]));
63
+ const childStatus = await childJob.run();
64
+ this.status |= childStatus;
65
+ this._postCount += childJob._postCount;
66
+ this._fileCount += childJob._fileCount;
67
+ }
68
+ _flushPost() {
69
+ const m = this._currentDir;
70
+ if (Object.keys(m).length === 0) return;
71
+ const w = this._width;
72
+ const labelW = 14;
73
+ const shortcode = m.post_shortcode ?? "?";
74
+ const header = ` Post #${this._postCount}: ${shortcode} `;
75
+ const padTotal = w - 2 - header.length;
76
+ const padL = Math.floor(padTotal / 2);
77
+ const padR = padTotal - padL;
78
+ process.stdout.write(`\n${dim("┌")}${"─".repeat(padL)}${b(header)}${"─".repeat(padR)}${dim("┐")}\n`);
79
+ const row = (label, value, color) => {
80
+ const colored = typeof color === "function" ? color(value) : color ? `${color}${value}${_RESET}` : value;
81
+ process.stdout.write(` ${dim("│")} ${c(pad(label, labelW))} ${colored}\n`);
82
+ };
83
+ const username = m.username ?? "?";
84
+ const fullname = m.fullname ?? "";
85
+ row("Author:", fullname ? `${username} (${fullname})` : username, g);
86
+ row("Date:", m.date ?? m.post_date ?? "?");
87
+ row("Likes:", `${typeof m.likes === "number" ? m.likes.toLocaleString() : "?"} | Liked: ${m.liked ? "yes" : "no"}`);
88
+ row("Type:", `${m.type ?? "?"} (${this._files.length} files)`);
89
+ row("URL:", m.post_url ?? "?");
90
+ const desc = m.description ?? "";
91
+ if (desc) {
92
+ process.stdout.write(` ${dim("│")}\n`);
93
+ process.stdout.write(` ${dim("│")} ${b("Description:")}\n`);
94
+ for (const line of desc.split("\n")) for (const wl of this._wrap(line, w - 8)) process.stdout.write(` ${dim("│")} ${dim(wl)}\n`);
95
+ }
96
+ const tags = m.tags;
97
+ if (tags && tags.length > 0) {
98
+ process.stdout.write(` ${dim("│")}\n`);
99
+ process.stdout.write(` ${dim("│")} ${b("Tags:")} ${dim(tags.map((t) => `#${t}`).join(" "))}\n`);
100
+ }
101
+ const locName = m.location_slug ?? "";
102
+ const locId = m.location_id ?? "";
103
+ if (locName || locId) row("Location:", locId ? `${locName} (ID: ${locId})` : locName);
104
+ const coauthors = m.coauthors;
105
+ if (coauthors && coauthors.length > 0) row("Co-authors:", coauthors.map((c) => c.full_name ? `${c.username} (${c.full_name})` : c.username).join(", "));
106
+ const pinned = m.pinned;
107
+ if (pinned && pinned.length > 0) row("Pinned:", pinned.join(", "));
108
+ const expires = m.expires;
109
+ if (expires) row("Expires:", expires, _YELLOW);
110
+ const hlTitle = m.highlight_title;
111
+ if (hlTitle) row("Highlight:", hlTitle);
112
+ const taggedUser = m.tagged_username ?? "";
113
+ if (taggedUser) {
114
+ const taggedFull = m.tagged_full_name ?? "";
115
+ row("Tagged by:", taggedFull ? `${taggedUser} (${taggedFull})` : taggedUser);
116
+ }
117
+ if (this._files.length > 0) {
118
+ process.stdout.write(` ${dim("│")}\n`);
119
+ process.stdout.write(` ${dim("│")} ${b(`Media (${this._files.length} files):`)}\n`);
120
+ const maxNumW = String(this._files.length).length;
121
+ const maxFileW = Math.max(...this._files.map((f) => f.filename.length));
122
+ const dimW = Math.min(maxFileW, 40);
123
+ for (const f of this._files) {
124
+ const numStr = `[${String(f.num).padStart(maxNumW)}]`;
125
+ const dimStr = f.filename.length > 40 ? `${f.filename.slice(0, 37)}...` : pad(f.filename, dimW);
126
+ const res = f.width ? `${f.width}x${f.height}` : "?x?";
127
+ const badges = [];
128
+ if (f.videoUrl) badges.push("video");
129
+ if (f.audioUrl) badges.push("audio");
130
+ let line = ` ${dim("│")} ${g(numStr)} ${dimStr} ${res}`;
131
+ if (badges.length > 0) line += ` ${_YELLOW}(${badges.join("+")})${_RESET}`;
132
+ process.stdout.write(`${line}\n`);
133
+ }
134
+ }
135
+ const audioFiles = this._files.filter((f) => f.audioUrl);
136
+ if (audioFiles.length > 0) {
137
+ process.stdout.write(` ${dim("│")}\n`);
138
+ process.stdout.write(` ${dim("│")} ${b("Music:")}\n`);
139
+ for (const af of audioFiles) {
140
+ if (af.audioTitle) {
141
+ const title = af.audioArtist ? `${af.audioTitle} — ${af.audioArtist}` : af.audioTitle;
142
+ process.stdout.write(` ${dim("│")} ${g("♪")} ${title}\n`);
143
+ }
144
+ if (af.audioDuration) {
145
+ const mins = Math.floor(af.audioDuration / 60);
146
+ const secs = Math.round(af.audioDuration % 60);
147
+ const badges = [`${mins}:${String(secs).padStart(2, "0")}`];
148
+ if (af.audioHasLyrics) badges.push("lyrics");
149
+ if (af.audioIsExplicit) badges.push(`${_YELLOW}explicit${_RESET}`);
150
+ process.stdout.write(` ${dim("│")} ${dim(badges.join(" · "))}\n`);
151
+ }
152
+ if (af.coverArtworkUri) process.stdout.write(` ${dim("│")} ${dim("Art:")} ${dim(`${af.coverArtworkUri.slice(0, 60)}…`)}\n`);
153
+ }
154
+ }
155
+ process.stdout.write(` ${dim("└")}${"─".repeat(w - 2)}${dim("┘")}\n`);
156
+ }
157
+ _wrap(text, maxLen) {
158
+ if (text.length <= maxLen) return [text];
159
+ const lines = [];
160
+ let remaining = text;
161
+ while (remaining.length > maxLen) {
162
+ let cut = maxLen;
163
+ while (cut > 0 && remaining[cut] !== " ") cut--;
164
+ if (cut === 0) cut = maxLen;
165
+ lines.push(remaining.slice(0, cut).trimEnd());
166
+ remaining = remaining.slice(cut).trimStart();
167
+ }
168
+ if (remaining) lines.push(remaining);
169
+ return lines;
170
+ }
171
+ _report() {
172
+ this._flushPost();
173
+ process.stdout.write(`\n${dim("──")} ${b("Summary")} ${dim("───")}\n`);
174
+ process.stdout.write(` Posts: ${g(String(this._postCount))}\n`);
175
+ process.stdout.write(` Files: ${g(String(this._fileCount))}\n`);
176
+ process.stdout.write(`\n`);
177
+ }
178
+ };
179
+ //#endregion
2
180
  export { ConfigManager, DownloadJob, Extractor, InstagramAvatarExtractor, InstagramExtractor, InstagramHighlightsExtractor, InstagramInfoExtractor, InstagramPostExtractor, InstagramPostsExtractor, InstagramReelsExtractor, InstagramRestAPI, InstagramSDK, InstagramSavedExtractor, InstagramStoriesExtractor, InstagramTagExtractor, InstagramTaggedExtractor, InstagramUserExtractor, Job, PrintJob, directory, ensureHttpScheme, extr, extract, extractAudio, extractTaggedUsers, findTags, idFromShortcode, nameExtFromURL, noopLogger, parseInt, parsePostGraphql, parsePostRest, parseUnicodeEscapes, queue, shortcodeFromId, unescape, unquote, url };
package/dist/node.cjs CHANGED
@@ -1,10 +1,10 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_sdk = require("./sdk-nzhAxf1O.cjs");
2
+ const require_sdk = require("./sdk-D8q2Rjw2.cjs");
3
3
  //#region src/node-factory.ts
4
4
  /**
5
5
  * Create an SDK instance with Node.js defaults.
6
6
  *
7
- * When ``cookies`` is provided, auto-creates an axios-based HttpClient
7
+ * When ``cookies`` is provided, auto-creates a native-fetch HttpClient
8
8
  * with CSRF token extraction. Pass ``http`` directly for custom adapters.
9
9
  *
10
10
  * ```ts
@@ -19,19 +19,17 @@ const require_sdk = require("./sdk-nzhAxf1O.cjs");
19
19
  */
20
20
  async function createSDK(opts = {}) {
21
21
  const log = opts.log ?? require_sdk.noopLogger;
22
- let http;
22
+ let http = opts.http;
23
23
  let storage = opts.storage;
24
24
  let csrfToken = "";
25
- if (opts.http) http = opts.http;
26
- else if (opts.cookies) {
27
- const { createHttpClient, extractCsrfFromCookies } = await Promise.resolve().then(() => require("./adapter-CFsiiEpM.cjs"));
28
- csrfToken = extractCsrfFromCookies(opts.cookies);
29
- http = createHttpClient(void 0, opts.cookies, log);
25
+ if (!http && opts.cookies) {
26
+ csrfToken = require_sdk.extractCsrf(opts.cookies);
27
+ http = require_sdk.createFetchHttpClient({ cookie: opts.cookies });
30
28
  if (!storage) {
31
29
  const { createStorage } = await Promise.resolve().then(() => require("./storage-BwGaT6XO.cjs"));
32
30
  storage = createStorage();
33
31
  }
34
- } else throw new Error("Either \"cookies\" or \"http\" must be provided. Get cookies from browser DevTools → Application → Cookies → instagram.com");
32
+ }
35
33
  return new require_sdk.InstagramSDK({
36
34
  http,
37
35
  storage,
package/dist/node.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { b as Storage, n as InstagramSDK, o as Logger, p as HttpClient } from "./sdk-CK9x5wFL.cjs";
1
+ import { b as Storage, n as InstagramSDK, o as Logger, p as HttpClient } from "./sdk-DyZz22bT.cjs";
2
2
 
3
3
  //#region src/node-factory.d.ts
4
4
  /** Options for the Node.js convenience factory. */
@@ -13,7 +13,7 @@ interface CreateSDKOptions {
13
13
  cookies?: string;
14
14
  /**
15
15
  * Custom HttpClient implementation.
16
- * If omitted, a Node.js axios-based client is created from ``cookies``.
16
+ * If omitted, a Node.js native-fetch client is created from ``cookies``.
17
17
  */
18
18
  http?: HttpClient;
19
19
  /**
@@ -29,7 +29,7 @@ interface CreateSDKOptions {
29
29
  /**
30
30
  * Create an SDK instance with Node.js defaults.
31
31
  *
32
- * When ``cookies`` is provided, auto-creates an axios-based HttpClient
32
+ * When ``cookies`` is provided, auto-creates a native-fetch HttpClient
33
33
  * with CSRF token extraction. Pass ``http`` directly for custom adapters.
34
34
  *
35
35
  * ```ts
package/dist/node.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { b as Storage, n as InstagramSDK, o as Logger, p as HttpClient } from "./sdk-CK9x5wFL.mjs";
1
+ import { b as Storage, n as InstagramSDK, o as Logger, p as HttpClient } from "./sdk-DyZz22bT.mjs";
2
2
 
3
3
  //#region src/node-factory.d.ts
4
4
  /** Options for the Node.js convenience factory. */
@@ -13,7 +13,7 @@ interface CreateSDKOptions {
13
13
  cookies?: string;
14
14
  /**
15
15
  * Custom HttpClient implementation.
16
- * If omitted, a Node.js axios-based client is created from ``cookies``.
16
+ * If omitted, a Node.js native-fetch client is created from ``cookies``.
17
17
  */
18
18
  http?: HttpClient;
19
19
  /**
@@ -29,7 +29,7 @@ interface CreateSDKOptions {
29
29
  /**
30
30
  * Create an SDK instance with Node.js defaults.
31
31
  *
32
- * When ``cookies`` is provided, auto-creates an axios-based HttpClient
32
+ * When ``cookies`` is provided, auto-creates a native-fetch HttpClient
33
33
  * with CSRF token extraction. Pass ``http`` directly for custom adapters.
34
34
  *
35
35
  * ```ts
package/dist/node.mjs CHANGED
@@ -1,9 +1,9 @@
1
- import { L as noopLogger, t as InstagramSDK } from "./sdk-Bn0VCUIT.mjs";
1
+ import { I as noopLogger, n as createFetchHttpClient, r as extractCsrf, t as InstagramSDK } from "./sdk-E0L5ISZC.mjs";
2
2
  //#region src/node-factory.ts
3
3
  /**
4
4
  * Create an SDK instance with Node.js defaults.
5
5
  *
6
- * When ``cookies`` is provided, auto-creates an axios-based HttpClient
6
+ * When ``cookies`` is provided, auto-creates a native-fetch HttpClient
7
7
  * with CSRF token extraction. Pass ``http`` directly for custom adapters.
8
8
  *
9
9
  * ```ts
@@ -18,19 +18,17 @@ import { L as noopLogger, t as InstagramSDK } from "./sdk-Bn0VCUIT.mjs";
18
18
  */
19
19
  async function createSDK(opts = {}) {
20
20
  const log = opts.log ?? noopLogger;
21
- let http;
21
+ let http = opts.http;
22
22
  let storage = opts.storage;
23
23
  let csrfToken = "";
24
- if (opts.http) http = opts.http;
25
- else if (opts.cookies) {
26
- const { createHttpClient, extractCsrfFromCookies } = await import("./adapter-tSleX8Cr.mjs");
27
- csrfToken = extractCsrfFromCookies(opts.cookies);
28
- http = createHttpClient(void 0, opts.cookies, log);
24
+ if (!http && opts.cookies) {
25
+ csrfToken = extractCsrf(opts.cookies);
26
+ http = createFetchHttpClient({ cookie: opts.cookies });
29
27
  if (!storage) {
30
28
  const { createStorage } = await import("./storage-77hqz5Fi.mjs");
31
29
  storage = createStorage();
32
30
  }
33
- } else throw new Error("Either \"cookies\" or \"http\" must be provided. Get cookies from browser DevTools → Application → Cookies → instagram.com");
31
+ }
34
32
  return new InstagramSDK({
35
33
  http,
36
34
  storage,