@vicociv/instaloader 0.1.0

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.
@@ -0,0 +1,1664 @@
1
+ /**
2
+ * Base exception for Instaloader.
3
+ * This exception should not be thrown directly.
4
+ */
5
+ declare class InstaloaderException extends Error {
6
+ constructor(message?: string);
7
+ }
8
+ /**
9
+ * Thrown when Instagram API returns a 400 Bad Request.
10
+ */
11
+ declare class QueryReturnedBadRequestException extends InstaloaderException {
12
+ constructor(message?: string);
13
+ }
14
+ /**
15
+ * Thrown when Instagram API returns a 403 Forbidden.
16
+ */
17
+ declare class QueryReturnedForbiddenException extends InstaloaderException {
18
+ constructor(message?: string);
19
+ }
20
+ /**
21
+ * Thrown when the requested profile does not exist.
22
+ */
23
+ declare class ProfileNotExistsException extends InstaloaderException {
24
+ constructor(message?: string);
25
+ }
26
+ /**
27
+ * @deprecated Not raised anymore since version 4.2.2
28
+ */
29
+ declare class ProfileHasNoPicsException extends InstaloaderException {
30
+ constructor(message?: string);
31
+ }
32
+ /**
33
+ * Thrown when trying to access a private profile that is not followed.
34
+ */
35
+ declare class PrivateProfileNotFollowedException extends InstaloaderException {
36
+ constructor(message?: string);
37
+ }
38
+ /**
39
+ * Thrown when login is required to access a resource.
40
+ */
41
+ declare class LoginRequiredException extends InstaloaderException {
42
+ constructor(message?: string);
43
+ }
44
+ /**
45
+ * Base exception for login-related errors.
46
+ */
47
+ declare class LoginException extends InstaloaderException {
48
+ constructor(message?: string);
49
+ }
50
+ /**
51
+ * Thrown when two-factor authentication is required.
52
+ */
53
+ declare class TwoFactorAuthRequiredException extends LoginException {
54
+ readonly twoFactorInfo: TwoFactorInfo;
55
+ constructor(twoFactorInfo: TwoFactorInfo, message?: string);
56
+ }
57
+ interface TwoFactorInfo {
58
+ username: string;
59
+ identifier: string;
60
+ obfuscatedPhoneNumber?: string;
61
+ showMessengerCodeOption?: boolean;
62
+ showNewLoginScreen?: boolean;
63
+ showTrustedDeviceOption?: boolean;
64
+ phoneverificationSettings?: PhoneVerificationSettings;
65
+ pendingTrustedNotificationPolling?: boolean;
66
+ }
67
+ interface PhoneVerificationSettings {
68
+ maxSmsCount?: number;
69
+ resendSmsDelaySec?: number;
70
+ robocallCountDownTimeSec?: number;
71
+ robocallAfterMaxSms?: boolean;
72
+ }
73
+ /**
74
+ * Thrown when an invalid argument is passed.
75
+ */
76
+ declare class InvalidArgumentException extends InstaloaderException {
77
+ constructor(message?: string);
78
+ }
79
+ /**
80
+ * Thrown when the API returns an unexpected response.
81
+ */
82
+ declare class BadResponseException extends InstaloaderException {
83
+ constructor(message?: string);
84
+ }
85
+ /**
86
+ * Thrown when login credentials are invalid.
87
+ */
88
+ declare class BadCredentialsException extends LoginException {
89
+ constructor(message?: string);
90
+ }
91
+ /**
92
+ * Thrown when there is a network connection error.
93
+ */
94
+ declare class ConnectionException extends InstaloaderException {
95
+ constructor(message?: string);
96
+ }
97
+ /**
98
+ * Thrown when a post has changed since it was loaded.
99
+ * @since 4.2.2
100
+ */
101
+ declare class PostChangedException extends InstaloaderException {
102
+ constructor(message?: string);
103
+ }
104
+ /**
105
+ * Thrown when Instagram API returns a 404 Not Found.
106
+ */
107
+ declare class QueryReturnedNotFoundException extends ConnectionException {
108
+ constructor(message?: string);
109
+ }
110
+ /**
111
+ * Thrown when Instagram API returns a 429 Too Many Requests.
112
+ */
113
+ declare class TooManyRequestsException extends ConnectionException {
114
+ constructor(message?: string);
115
+ }
116
+ /**
117
+ * Thrown when iPhone support is disabled but an iPhone-only feature is requested.
118
+ */
119
+ declare class IPhoneSupportDisabledException extends InstaloaderException {
120
+ constructor(message?: string);
121
+ }
122
+ /**
123
+ * Exception that is not caught in the error handlers inside the download loop
124
+ * and so aborts the download loop.
125
+ *
126
+ * This exception is not a subclass of InstaloaderException.
127
+ *
128
+ * @since 4.7
129
+ */
130
+ declare class AbortDownloadException extends Error {
131
+ constructor(message?: string);
132
+ }
133
+ /**
134
+ * Thrown when the session file is not found.
135
+ */
136
+ declare class SessionNotFoundException extends InstaloaderException {
137
+ constructor(message?: string);
138
+ }
139
+ /**
140
+ * Thrown when a checkpoint/challenge is required.
141
+ */
142
+ declare class CheckpointRequiredException extends ConnectionException {
143
+ readonly checkpointUrl: string | undefined;
144
+ constructor(message?: string, checkpointUrl?: string);
145
+ }
146
+ /**
147
+ * Thrown when the iterator state is invalid or expired.
148
+ */
149
+ declare class InvalidIteratorException extends InstaloaderException {
150
+ constructor(message?: string);
151
+ }
152
+
153
+ /**
154
+ * Common types used throughout the Instaloader library.
155
+ */
156
+ /**
157
+ * Generic JSON object type.
158
+ */
159
+ type JsonValue = string | number | boolean | null | JsonValue[] | {
160
+ [key: string]: JsonValue;
161
+ };
162
+ type JsonObject = {
163
+ [key: string]: JsonValue;
164
+ };
165
+ /**
166
+ * Cookie object for session management.
167
+ */
168
+ interface CookieData {
169
+ [key: string]: string;
170
+ }
171
+ /**
172
+ * HTTP headers object.
173
+ */
174
+ interface HttpHeaders {
175
+ [key: string]: string;
176
+ }
177
+ /**
178
+ * GraphQL query response.
179
+ */
180
+ interface GraphQLResponse {
181
+ data?: JsonObject;
182
+ status?: string;
183
+ message?: string;
184
+ [key: string]: JsonValue | undefined;
185
+ }
186
+ /**
187
+ * Login response from Instagram.
188
+ */
189
+ interface LoginResponse {
190
+ authenticated?: boolean;
191
+ user?: boolean;
192
+ userId?: string;
193
+ status?: string;
194
+ message?: string;
195
+ checkpoint_url?: string;
196
+ two_factor_required?: boolean;
197
+ two_factor_info?: {
198
+ two_factor_identifier: string;
199
+ obfuscated_phone_number?: string;
200
+ show_messenger_code_option?: boolean;
201
+ show_new_login_screen?: boolean;
202
+ show_trusted_device_option?: boolean;
203
+ pending_trusted_notification_polling?: boolean;
204
+ };
205
+ oneTapPrompt?: boolean;
206
+ }
207
+ /**
208
+ * HTTP response information.
209
+ */
210
+ interface ResponseInfo {
211
+ status: number;
212
+ statusText: string;
213
+ headers: Headers;
214
+ url: string;
215
+ }
216
+ /**
217
+ * Request options for fetch.
218
+ */
219
+ interface RequestOptions {
220
+ method?: 'GET' | 'POST' | 'HEAD';
221
+ headers?: HeadersInit;
222
+ body?: string | URLSearchParams;
223
+ redirect?: RequestRedirect;
224
+ signal?: AbortSignal;
225
+ }
226
+ /**
227
+ * Session data for persistence.
228
+ */
229
+ interface SessionData {
230
+ cookies: CookieData;
231
+ username: string;
232
+ userId?: string;
233
+ }
234
+ /**
235
+ * Rate controller query timestamps.
236
+ */
237
+ interface QueryTimestamps {
238
+ [queryType: string]: number[];
239
+ }
240
+ /**
241
+ * iPhone headers for API requests.
242
+ */
243
+ interface IPhoneHeaders {
244
+ 'User-Agent': string;
245
+ 'x-ads-opt-out': string;
246
+ 'x-bloks-is-panorama-enabled': string;
247
+ 'x-bloks-version-id': string;
248
+ 'x-fb-client-ip': string;
249
+ 'x-fb-connection-type': string;
250
+ 'x-fb-http-engine': string;
251
+ 'x-fb-server-cluster': string;
252
+ 'x-fb': string;
253
+ 'x-ig-abr-connection-speed-kbps': string;
254
+ 'x-ig-app-id': string;
255
+ 'x-ig-app-locale': string;
256
+ 'x-ig-app-startup-country': string;
257
+ 'x-ig-bandwidth-speed-kbps': string;
258
+ 'x-ig-capabilities': string;
259
+ 'x-ig-connection-speed': string;
260
+ 'x-ig-connection-type': string;
261
+ 'x-ig-device-locale': string;
262
+ 'x-ig-mapped-locale': string;
263
+ 'x-ig-timezone-offset': string;
264
+ 'x-ig-www-claim': string;
265
+ 'x-pigeon-session-id': string;
266
+ 'x-tigon-is-retry': string;
267
+ 'x-whatsapp': string;
268
+ [key: string]: string;
269
+ }
270
+ /**
271
+ * Post node from GraphQL response.
272
+ */
273
+ interface PostNode {
274
+ id: string;
275
+ shortcode: string;
276
+ typename?: string;
277
+ __typename?: string;
278
+ display_url?: string;
279
+ is_video?: boolean;
280
+ video_url?: string;
281
+ edge_media_to_caption?: {
282
+ edges: Array<{
283
+ node: {
284
+ text: string;
285
+ };
286
+ }>;
287
+ };
288
+ edge_media_to_comment?: {
289
+ count: number;
290
+ };
291
+ edge_liked_by?: {
292
+ count: number;
293
+ };
294
+ edge_media_preview_like?: {
295
+ count: number;
296
+ };
297
+ owner?: {
298
+ id: string;
299
+ username: string;
300
+ };
301
+ taken_at_timestamp?: number;
302
+ location?: {
303
+ id: string;
304
+ name: string;
305
+ slug?: string;
306
+ } | null;
307
+ accessibility_caption?: string | null;
308
+ edge_sidecar_to_children?: {
309
+ edges: Array<{
310
+ node: PostNode;
311
+ }>;
312
+ };
313
+ video_view_count?: number;
314
+ video_duration?: number;
315
+ }
316
+ /**
317
+ * Profile node from GraphQL response.
318
+ */
319
+ interface ProfileNode {
320
+ id: string;
321
+ username: string;
322
+ full_name?: string;
323
+ biography?: string;
324
+ profile_pic_url?: string;
325
+ profile_pic_url_hd?: string;
326
+ is_private?: boolean;
327
+ is_verified?: boolean;
328
+ is_business_account?: boolean;
329
+ business_category_name?: string | null;
330
+ external_url?: string | null;
331
+ edge_followed_by?: {
332
+ count: number;
333
+ };
334
+ edge_follow?: {
335
+ count: number;
336
+ };
337
+ edge_owner_to_timeline_media?: {
338
+ count: number;
339
+ };
340
+ followed_by_viewer?: boolean;
341
+ follows_viewer?: boolean;
342
+ blocked_by_viewer?: boolean;
343
+ has_blocked_viewer?: boolean;
344
+ requested_by_viewer?: boolean;
345
+ }
346
+ /**
347
+ * Story item node from GraphQL response.
348
+ */
349
+ interface StoryItemNode {
350
+ id: string;
351
+ __typename?: string;
352
+ display_url?: string;
353
+ is_video?: boolean;
354
+ video_resources?: Array<{
355
+ src: string;
356
+ profile?: string;
357
+ }>;
358
+ taken_at_timestamp?: number;
359
+ expiring_at_timestamp?: number;
360
+ story_cta_url?: string | null;
361
+ owner?: {
362
+ id: string;
363
+ username: string;
364
+ };
365
+ }
366
+ /**
367
+ * Highlight node from GraphQL response.
368
+ */
369
+ interface HighlightNode {
370
+ id: string;
371
+ title: string;
372
+ cover_media?: {
373
+ thumbnail_src?: string;
374
+ };
375
+ cover_media_cropped_thumbnail?: {
376
+ url?: string;
377
+ };
378
+ owner?: {
379
+ id: string;
380
+ username: string;
381
+ };
382
+ }
383
+ /**
384
+ * Comment node from GraphQL response.
385
+ */
386
+ interface CommentNode {
387
+ id: string;
388
+ text: string;
389
+ created_at: number;
390
+ owner: {
391
+ id: string;
392
+ username: string;
393
+ profile_pic_url?: string;
394
+ };
395
+ edge_liked_by?: {
396
+ count: number;
397
+ };
398
+ edge_threaded_comments?: {
399
+ count: number;
400
+ edges: Array<{
401
+ node: CommentNode;
402
+ }>;
403
+ };
404
+ }
405
+ /**
406
+ * Hashtag node from GraphQL response.
407
+ */
408
+ interface HashtagNode {
409
+ id: string;
410
+ name: string;
411
+ profile_pic_url?: string;
412
+ edge_hashtag_to_media?: {
413
+ count: number;
414
+ };
415
+ edge_hashtag_to_top_posts?: {
416
+ edges: Array<{
417
+ node: PostNode;
418
+ }>;
419
+ };
420
+ }
421
+ /**
422
+ * Location node from GraphQL response.
423
+ */
424
+ interface LocationNode {
425
+ id: string;
426
+ name: string;
427
+ slug?: string;
428
+ has_public_page?: boolean;
429
+ lat?: number;
430
+ lng?: number;
431
+ }
432
+ /**
433
+ * Page info for pagination.
434
+ */
435
+ interface PageInfo {
436
+ has_next_page: boolean;
437
+ end_cursor: string | null;
438
+ }
439
+ /**
440
+ * Edge connection type for GraphQL pagination.
441
+ */
442
+ interface EdgeConnection<T> {
443
+ count?: number;
444
+ page_info: PageInfo;
445
+ edges: Array<{
446
+ node: T;
447
+ }>;
448
+ }
449
+ /**
450
+ * Frozen iterator state for resumable downloads.
451
+ */
452
+ interface FrozenIteratorState {
453
+ queryHash?: string;
454
+ queryVariables: JsonObject;
455
+ queryReferer?: string | null;
456
+ contextUsername?: string | null;
457
+ totalIndex: number;
458
+ bestBefore?: number;
459
+ remainingData?: Array<{
460
+ node: JsonObject;
461
+ }> | null;
462
+ firstNode?: JsonObject | null;
463
+ docId?: string;
464
+ }
465
+
466
+ /**
467
+ * InstaloaderContext - HTTP client and low-level communication with Instagram.
468
+ * Ported from Python instaloader/instaloadercontext.py
469
+ */
470
+
471
+ /**
472
+ * Returns default user agent string.
473
+ */
474
+ declare function defaultUserAgent(): string;
475
+ /**
476
+ * Returns default iPhone headers for API requests.
477
+ */
478
+ declare function defaultIphoneHeaders(): HttpHeaders;
479
+ /**
480
+ * Class providing request tracking and rate controlling to stay within rate limits.
481
+ */
482
+ declare class RateController {
483
+ protected _context: InstaloaderContext;
484
+ protected _queryTimestamps: Map<string, number[]>;
485
+ protected _earliestNextRequestTime: number;
486
+ protected _iphoneEarliestNextRequestTime: number;
487
+ constructor(context: InstaloaderContext);
488
+ /**
489
+ * Wait given number of seconds.
490
+ */
491
+ sleep(secs: number): Promise<void>;
492
+ /**
493
+ * Return how many requests of the given type can be done within a sliding window of 11 minutes.
494
+ */
495
+ countPerSlidingWindow(queryType: string): number;
496
+ private _reqsInSlidingWindow;
497
+ /**
498
+ * Calculate time needed to wait before query can be executed.
499
+ */
500
+ queryWaittime(queryType: string, currentTime: number, untrackedQueries?: boolean): number;
501
+ /**
502
+ * Called before a query to Instagram.
503
+ */
504
+ waitBeforeQuery(queryType: string): Promise<void>;
505
+ /**
506
+ * Handle a 429 Too Many Requests response.
507
+ */
508
+ handle429(queryType: string): Promise<void>;
509
+ }
510
+ interface InstaloaderContextOptions {
511
+ /** Whether to sleep between requests (default: true) */
512
+ sleep?: boolean;
513
+ /** Whether to suppress output (default: false) */
514
+ quiet?: boolean;
515
+ /** Custom user agent string */
516
+ userAgent?: string;
517
+ /** Maximum connection retry attempts (default: 3) */
518
+ maxConnectionAttempts?: number;
519
+ /** Request timeout in milliseconds (default: 300000) */
520
+ requestTimeout?: number;
521
+ /** Custom rate controller factory */
522
+ rateController?: (ctx: InstaloaderContext) => RateController;
523
+ /** HTTP status codes that should cause an AbortDownloadException */
524
+ fatalStatusCodes?: number[];
525
+ /** Whether to enable iPhone API support (default: true) */
526
+ iphoneSupport?: boolean;
527
+ }
528
+ /**
529
+ * Class providing methods for logging and low-level communication with Instagram.
530
+ *
531
+ * It provides low-level communication routines getJson(), graphqlQuery(), getIphoneJson()
532
+ * and implements mechanisms for rate controlling and error handling.
533
+ *
534
+ * Further, it provides methods for logging in and general session handles.
535
+ */
536
+ declare class InstaloaderContext {
537
+ readonly userAgent: string;
538
+ readonly requestTimeout: number;
539
+ readonly maxConnectionAttempts: number;
540
+ readonly sleep: boolean;
541
+ readonly quiet: boolean;
542
+ readonly iphoneSupport: boolean;
543
+ readonly fatalStatusCodes: number[];
544
+ private _cookieJar;
545
+ private _csrfToken;
546
+ private _username;
547
+ private _userId;
548
+ private _iphoneHeaders;
549
+ private _rateController;
550
+ private _errorLog;
551
+ private _twoFactorAuthPending;
552
+ /** Raise all errors instead of catching them (for testing) */
553
+ raiseAllErrors: boolean;
554
+ /** Cache profile from id (mapping from id to Profile) */
555
+ readonly profile_id_cache: Map<number, any>;
556
+ constructor(options?: InstaloaderContextOptions);
557
+ private _initAnonymousCookies;
558
+ /** True if this instance is logged in. */
559
+ get is_logged_in(): boolean;
560
+ /** The username of the logged-in user, or null. */
561
+ get username(): string | null;
562
+ /** The user ID of the logged-in user, or null. */
563
+ get userId(): string | null;
564
+ /** iPhone headers for API requests. */
565
+ get iphone_headers(): HttpHeaders;
566
+ /** Whether any error has been reported and stored. */
567
+ get hasStoredErrors(): boolean;
568
+ /**
569
+ * Log a message to stdout (can be suppressed with quiet option).
570
+ * @param message - The message to log
571
+ * @param newline - Whether to add a newline (default true, false for inline messages)
572
+ */
573
+ log(message: string, newline?: boolean): void;
574
+ /**
575
+ * Log a non-fatal error message to stderr.
576
+ */
577
+ error(message: string, repeatAtEnd?: boolean): void;
578
+ /**
579
+ * Close the context and print any stored errors.
580
+ */
581
+ close(): void;
582
+ /**
583
+ * Returns default HTTP headers for requests.
584
+ */
585
+ private _defaultHttpHeader;
586
+ /**
587
+ * Sleep a short time if sleep is enabled.
588
+ */
589
+ doSleep(): Promise<void>;
590
+ /**
591
+ * Get cookies as a plain object.
592
+ */
593
+ getCookies(url?: string): CookieData;
594
+ /**
595
+ * Set cookies from a plain object.
596
+ */
597
+ setCookies(cookies: CookieData, url?: string): void;
598
+ /**
599
+ * Save session data for later restoration.
600
+ */
601
+ saveSession(): CookieData;
602
+ /**
603
+ * Load session data from a saved session.
604
+ */
605
+ loadSession(username: string, sessionData: CookieData): void;
606
+ /**
607
+ * Update cookies with new values.
608
+ */
609
+ updateCookies(cookies: CookieData): void;
610
+ /**
611
+ * Build cookie header string from cookie jar.
612
+ */
613
+ private _getCookieHeader;
614
+ /**
615
+ * Parse and store cookies from Set-Cookie headers.
616
+ */
617
+ private _storeCookies;
618
+ /**
619
+ * Format response error message.
620
+ */
621
+ private _responseError;
622
+ /**
623
+ * Make a JSON request to Instagram.
624
+ */
625
+ getJson(path: string, params: JsonObject, options?: {
626
+ host?: string;
627
+ usePost?: boolean;
628
+ attempt?: number;
629
+ headers?: HttpHeaders;
630
+ }): Promise<JsonObject>;
631
+ /**
632
+ * Do a GraphQL Query.
633
+ */
634
+ graphql_query(queryHash: string, variables: JsonObject, referer?: string): Promise<JsonObject>;
635
+ /**
636
+ * Do a doc_id-based GraphQL Query using POST.
637
+ */
638
+ doc_id_graphql_query(docId: string, variables: JsonObject, referer?: string): Promise<JsonObject>;
639
+ /**
640
+ * JSON request to i.instagram.com.
641
+ */
642
+ get_iphone_json(path: string, params: JsonObject): Promise<JsonObject>;
643
+ /**
644
+ * HEAD a URL anonymously.
645
+ */
646
+ head(url: string, options?: {
647
+ allowRedirects?: boolean;
648
+ }): Promise<{
649
+ headers: Map<string, string>;
650
+ }>;
651
+ /**
652
+ * Test if logged in by querying the current user.
653
+ */
654
+ testLogin(): Promise<string | null>;
655
+ /**
656
+ * Login to Instagram.
657
+ */
658
+ login(username: string, password: string): Promise<void>;
659
+ /**
660
+ * Second step of login if 2FA is enabled.
661
+ */
662
+ twoFactorLogin(twoFactorCode: string): Promise<void>;
663
+ }
664
+
665
+ /**
666
+ * NodeIterator - Async iterator for paginated GraphQL results.
667
+ *
668
+ * Ported from Python instaloader/nodeiterator.py
669
+ */
670
+
671
+ /**
672
+ * Frozen state of a NodeIterator for resumable downloads.
673
+ */
674
+ declare class FrozenNodeIterator {
675
+ readonly queryHash: string | null;
676
+ readonly queryVariables: JsonObject;
677
+ readonly queryReferer: string | null;
678
+ readonly contextUsername: string | null;
679
+ readonly totalIndex: number;
680
+ readonly bestBefore: number | null;
681
+ readonly remainingData: {
682
+ edges: Array<{
683
+ node: JsonObject;
684
+ }>;
685
+ page_info: {
686
+ has_next_page: boolean;
687
+ end_cursor: string | null;
688
+ };
689
+ count?: number;
690
+ } | null;
691
+ readonly firstNode: JsonObject | null;
692
+ readonly docId: string | undefined;
693
+ constructor(params: {
694
+ queryHash: string | null;
695
+ queryVariables: JsonObject;
696
+ queryReferer: string | null;
697
+ contextUsername: string | null;
698
+ totalIndex: number;
699
+ bestBefore: number | null;
700
+ remainingData: {
701
+ edges: Array<{
702
+ node: JsonObject;
703
+ }>;
704
+ page_info: {
705
+ has_next_page: boolean;
706
+ end_cursor: string | null;
707
+ };
708
+ count?: number;
709
+ } | null;
710
+ firstNode: JsonObject | null;
711
+ docId: string | undefined;
712
+ });
713
+ /**
714
+ * Convert to plain object for JSON serialization.
715
+ */
716
+ toObject(): {
717
+ queryHash: string | null;
718
+ queryVariables: JsonObject;
719
+ queryReferer: string | null;
720
+ contextUsername: string | null;
721
+ totalIndex: number;
722
+ bestBefore: number | null;
723
+ remainingData: {
724
+ edges: Array<{
725
+ node: JsonObject;
726
+ }>;
727
+ page_info: {
728
+ has_next_page: boolean;
729
+ end_cursor: string | null;
730
+ };
731
+ count?: number;
732
+ } | null;
733
+ firstNode: JsonObject | null;
734
+ docId: string | undefined;
735
+ };
736
+ /**
737
+ * Create from plain object (JSON deserialization).
738
+ */
739
+ static fromObject(obj: ReturnType<FrozenNodeIterator['toObject']>): FrozenNodeIterator;
740
+ }
741
+ interface NodeIteratorData {
742
+ edges: Array<{
743
+ node: JsonObject;
744
+ }>;
745
+ page_info: {
746
+ has_next_page: boolean;
747
+ end_cursor: string | null;
748
+ };
749
+ count?: number;
750
+ }
751
+ interface NodeIteratorOptions<T> {
752
+ context: InstaloaderContext;
753
+ queryHash: string | null;
754
+ edgeExtractor: (data: JsonObject) => JsonObject;
755
+ nodeWrapper: (node: JsonObject) => T;
756
+ queryVariables?: JsonObject;
757
+ queryReferer?: string | null;
758
+ firstData?: NodeIteratorData;
759
+ isFirst?: (item: T, currentFirst: T | null) => boolean;
760
+ docId?: string;
761
+ }
762
+ /**
763
+ * Iterate the nodes within edges in a GraphQL pagination.
764
+ *
765
+ * What makes this iterator special is its ability to freeze/store its current state,
766
+ * e.g. to interrupt an iteration, and later thaw/resume from where it left off.
767
+ *
768
+ * @example
769
+ * ```typescript
770
+ * const postIterator = profile.getPosts();
771
+ * try {
772
+ * for await (const post of postIterator) {
773
+ * await doSomethingWith(post);
774
+ * }
775
+ * } catch (e) {
776
+ * if (e instanceof KeyboardInterrupt) {
777
+ * save("resume_information.json", postIterator.freeze());
778
+ * }
779
+ * }
780
+ * ```
781
+ *
782
+ * And later reuse it with `thaw()`:
783
+ * ```typescript
784
+ * const postIterator = profile.getPosts();
785
+ * postIterator.thaw(load("resume_information.json"));
786
+ * ```
787
+ */
788
+ declare class NodeIterator<T> implements AsyncIterable<T> {
789
+ private static readonly _graphql_page_length;
790
+ private static readonly _shelf_life_days;
791
+ private readonly _context;
792
+ private readonly _queryHash;
793
+ private readonly _docId;
794
+ private readonly _edgeExtractor;
795
+ private readonly _nodeWrapper;
796
+ private readonly _queryVariables;
797
+ private readonly _queryReferer;
798
+ private readonly _isFirst;
799
+ private _pageIndex;
800
+ private _totalIndex;
801
+ private _data;
802
+ private _bestBefore;
803
+ private _firstNode;
804
+ private _initialized;
805
+ private _initPromise;
806
+ constructor(options: NodeIteratorOptions<T>);
807
+ private _initialize;
808
+ private _ensureInitialized;
809
+ private _query;
810
+ private _queryDocId;
811
+ private _queryQueryHash;
812
+ /**
813
+ * The count as returned by Instagram.
814
+ * This is not always the total count this iterator will yield.
815
+ */
816
+ get count(): number | undefined;
817
+ /**
818
+ * Number of items that have already been returned.
819
+ */
820
+ get totalIndex(): number;
821
+ /**
822
+ * Magic string for easily identifying a matching iterator file for resuming.
823
+ * Two NodeIterators are matching if and only if they have the same magic.
824
+ */
825
+ get magic(): string;
826
+ /**
827
+ * If this iterator has produced any items, returns the first item produced.
828
+ *
829
+ * It is possible to override what is considered the first item by passing
830
+ * a callback function as the `isFirst` parameter when creating the class.
831
+ */
832
+ get firstItem(): T | null;
833
+ /**
834
+ * Static page length used for pagination.
835
+ */
836
+ static pageLength(): number;
837
+ /**
838
+ * Freeze the iterator for later resuming.
839
+ */
840
+ freeze(): FrozenNodeIterator;
841
+ /**
842
+ * Use this iterator for resuming from earlier iteration.
843
+ *
844
+ * @throws InvalidArgumentException if the iterator has already been used or the frozen state doesn't match
845
+ */
846
+ thaw(frozen: FrozenNodeIterator): void;
847
+ /**
848
+ * Async iterator implementation.
849
+ */
850
+ [Symbol.asyncIterator](): AsyncIterator<T>;
851
+ }
852
+ /**
853
+ * Options for resumable iteration.
854
+ */
855
+ interface ResumableIterationOptions<T> {
856
+ context: InstaloaderContext;
857
+ iterator: AsyncIterable<T> | Iterable<T>;
858
+ load: (context: InstaloaderContext, path: string) => FrozenNodeIterator | Promise<FrozenNodeIterator>;
859
+ save: (frozen: FrozenNodeIterator, path: string) => void | Promise<void>;
860
+ formatPath: (magic: string) => string;
861
+ checkBbd?: boolean;
862
+ enabled?: boolean;
863
+ }
864
+ /**
865
+ * Result of resumable iteration setup.
866
+ */
867
+ interface ResumableIterationResult {
868
+ isResuming: boolean;
869
+ startIndex: number;
870
+ }
871
+ /**
872
+ * High-level function to handle resumable iteration.
873
+ *
874
+ * Note: Unlike Python's context manager, this returns the resumption info
875
+ * and the caller is responsible for handling interrupts.
876
+ *
877
+ * @example
878
+ * ```typescript
879
+ * const postIterator = profile.getPosts();
880
+ * const { isResuming, startIndex } = await resumableIteration({
881
+ * context: L.context,
882
+ * iterator: postIterator,
883
+ * load: async (_, path) => FrozenNodeIterator.fromObject(JSON.parse(await fs.readFile(path, 'utf-8'))),
884
+ * save: async (fni, path) => fs.writeFile(path, JSON.stringify(fni.toObject())),
885
+ * formatPath: (magic) => `resume_info_${magic}.json`,
886
+ * });
887
+ *
888
+ * try {
889
+ * for await (const post of postIterator) {
890
+ * await doSomethingWith(post);
891
+ * }
892
+ * } catch (e) {
893
+ * // Save state on interrupt
894
+ * if (postIterator instanceof NodeIterator) {
895
+ * await save(postIterator.freeze(), formatPath(postIterator.magic));
896
+ * }
897
+ * throw e;
898
+ * }
899
+ * ```
900
+ */
901
+ declare function resumableIteration<T>(options: ResumableIterationOptions<T>): Promise<ResumableIterationResult>;
902
+
903
+ /**
904
+ * Data structures for Instagram content.
905
+ * Ported from Python instaloader/structures.py
906
+ */
907
+
908
+ /**
909
+ * Item of a Sidecar Post.
910
+ */
911
+ interface PostSidecarNode {
912
+ /** Whether this node is a video. */
913
+ is_video: boolean;
914
+ /** URL of image or video thumbnail. */
915
+ display_url: string;
916
+ /** URL of video or null. */
917
+ video_url: string | null;
918
+ }
919
+ /**
920
+ * Answer to a comment.
921
+ */
922
+ interface PostCommentAnswer {
923
+ /** ID number of comment. */
924
+ id: number;
925
+ /** Timestamp when comment was created (UTC). */
926
+ created_at_utc: Date;
927
+ /** Comment text. */
928
+ text: string;
929
+ /** Owner Profile of the comment. */
930
+ owner: Profile;
931
+ /** Number of likes on comment. */
932
+ likes_count: number;
933
+ }
934
+ /**
935
+ * Location associated with a post.
936
+ */
937
+ interface PostLocation {
938
+ /** ID number of location. */
939
+ id: number;
940
+ /** Location name. */
941
+ name: string;
942
+ /** URL friendly variant of location name. */
943
+ slug: string;
944
+ /** Whether location has a public page. */
945
+ has_public_page: boolean | null;
946
+ /** Latitude (number or null). */
947
+ lat: number | null;
948
+ /** Longitude (number or null). */
949
+ lng: number | null;
950
+ }
951
+ /**
952
+ * Convert a shortcode to a mediaid.
953
+ */
954
+ declare function shortcodeToMediaid(code: string): bigint;
955
+ /**
956
+ * Convert a mediaid to a shortcode.
957
+ */
958
+ declare function mediaidToShortcode(mediaid: bigint): string;
959
+ /**
960
+ * Extract hashtags from text.
961
+ */
962
+ declare function extractHashtags(text: string): string[];
963
+ /**
964
+ * Extract @mentions from text.
965
+ */
966
+ declare function extractMentions(text: string): string[];
967
+ /**
968
+ * Represents a comment on a post.
969
+ */
970
+ declare class PostComment {
971
+ private readonly _context;
972
+ private readonly _node;
973
+ private readonly _answers;
974
+ private readonly _post;
975
+ constructor(context: InstaloaderContext, node: JsonObject, answers: AsyncIterable<PostCommentAnswer>, post: Post);
976
+ /**
977
+ * Create a PostComment from an iPhone API struct.
978
+ */
979
+ static fromIphoneStruct(context: InstaloaderContext, media: JsonObject, answers: AsyncIterable<PostCommentAnswer>, post: Post): PostComment;
980
+ /** ID number of comment. */
981
+ get id(): number;
982
+ /** Timestamp when comment was created (UTC). */
983
+ get created_at_utc(): Date;
984
+ /** Comment text. */
985
+ get text(): string;
986
+ /** Owner Profile of the comment. */
987
+ get owner(): Profile;
988
+ /** Number of likes on comment. */
989
+ get likes_count(): number;
990
+ /** Iterator which yields all PostCommentAnswer for the comment. */
991
+ get answers(): AsyncIterable<PostCommentAnswer>;
992
+ toString(): string;
993
+ }
994
+ /**
995
+ * Structure containing information about an Instagram post.
996
+ *
997
+ * Created by methods Profile.get_posts(), Instaloader.get_hashtag_posts(),
998
+ * Instaloader.get_feed_posts() and Profile.get_saved_posts().
999
+ *
1000
+ * This class unifies access to the properties associated with a post.
1001
+ * It implements equality comparison and is hashable.
1002
+ */
1003
+ declare class Post {
1004
+ private readonly _context;
1005
+ private _node;
1006
+ private _owner_profile;
1007
+ private _full_metadata_dict;
1008
+ private _location;
1009
+ private _iphone_struct_;
1010
+ /**
1011
+ * @param context InstaloaderContext used for additional queries if necessary.
1012
+ * @param node Node structure, as returned by Instagram.
1013
+ * @param owner_profile The Profile of the owner, if already known at creation.
1014
+ */
1015
+ constructor(context: InstaloaderContext, node: JsonObject, owner_profile?: Profile | null);
1016
+ /**
1017
+ * Create a post object from a given shortcode.
1018
+ */
1019
+ static fromShortcode(context: InstaloaderContext, shortcode: string): Promise<Post>;
1020
+ /**
1021
+ * Create a post object from a given mediaid.
1022
+ */
1023
+ static fromMediaid(context: InstaloaderContext, mediaid: bigint): Promise<Post>;
1024
+ /**
1025
+ * Create a post from a given iphone_struct.
1026
+ */
1027
+ static fromIphoneStruct(context: InstaloaderContext, media: JsonObject): Post;
1028
+ private static _convertIphoneCarousel;
1029
+ /** The values of __typename fields that the Post class can handle. */
1030
+ static supportedGraphqlTypes(): string[];
1031
+ /** Media shortcode. URL of the post is instagram.com/p/<shortcode>/. */
1032
+ get shortcode(): string;
1033
+ /** The mediaid is a decimal representation of the media shortcode. */
1034
+ get mediaid(): bigint;
1035
+ /** Title of post */
1036
+ get title(): string | null;
1037
+ toString(): string;
1038
+ equals(other: Post): boolean;
1039
+ private _obtainMetadata;
1040
+ private _getFullMetadata;
1041
+ /**
1042
+ * Get iPhone struct for high quality media.
1043
+ * Reserved for future use to fetch HQ images.
1044
+ */
1045
+ private _getIphoneStruct;
1046
+ /**
1047
+ * Lookup fields in _node, and if not found in _full_metadata.
1048
+ * Throws if not found anywhere.
1049
+ */
1050
+ private _field;
1051
+ /**
1052
+ * Async version of _field that can fetch full metadata if needed.
1053
+ */
1054
+ getField(...keys: string[]): Promise<JsonValue>;
1055
+ /** Profile instance of the Post's owner. */
1056
+ getOwnerProfile(): Promise<Profile>;
1057
+ /** The Post's lowercase owner name. */
1058
+ getOwnerUsername(): Promise<string>;
1059
+ /** The ID of the Post's owner. */
1060
+ get owner_id(): number | null;
1061
+ /** Timestamp when the post was created (local time zone). */
1062
+ get date_local(): Date;
1063
+ /** Timestamp when the post was created (UTC). */
1064
+ get date_utc(): Date;
1065
+ /** Synonym to date_utc */
1066
+ get date(): Date;
1067
+ private _getTimestampDateCreated;
1068
+ /** URL of the picture / video thumbnail of the post */
1069
+ get url(): string;
1070
+ /** Type of post: GraphImage, GraphVideo or GraphSidecar */
1071
+ get typename(): string;
1072
+ /** The number of media in a sidecar Post, or 1 if not a sidecar. */
1073
+ get mediacount(): number;
1074
+ /** Caption. */
1075
+ get caption(): string | null;
1076
+ /** List of all lowercased hashtags (without preceding #) that occur in the Post's caption. */
1077
+ get caption_hashtags(): string[];
1078
+ /** List of all lowercased profiles that are mentioned in the Post's caption, without preceding @. */
1079
+ get caption_mentions(): string[];
1080
+ /** Printable caption, useful as a format specifier for --filename-pattern. */
1081
+ get pcaption(): string;
1082
+ /** Accessibility caption of the post, if available. */
1083
+ get accessibility_caption(): string | null;
1084
+ /** List of all lowercased users that are tagged in the Post. */
1085
+ get tagged_users(): string[];
1086
+ /** True if the Post is a video. */
1087
+ get is_video(): boolean;
1088
+ /** URL of the video, or null. */
1089
+ get video_url(): string | null;
1090
+ /** View count of the video, or null. */
1091
+ get video_view_count(): number | null;
1092
+ /** Duration of the video in seconds, or null. */
1093
+ get video_duration(): number | null;
1094
+ /** Whether the viewer has liked the post, or null if not logged in. */
1095
+ get viewer_has_liked(): boolean | null;
1096
+ /** Likes count */
1097
+ get likes(): number;
1098
+ /** Comment count including answers */
1099
+ get comments(): number;
1100
+ /** Whether Post is a sponsored post. */
1101
+ get is_sponsored(): boolean;
1102
+ /** Returns true if is_video for each media in sidecar. */
1103
+ getIsVideos(): boolean[];
1104
+ /** Sidecar nodes of a Post with typename==GraphSidecar. */
1105
+ getSidecarNodes(start?: number, end?: number): Generator<PostSidecarNode>;
1106
+ /** Returns Post as a JSON-serializable object. */
1107
+ toJSON(): JsonObject;
1108
+ }
1109
+ /**
1110
+ * An Instagram Profile.
1111
+ *
1112
+ * Provides methods for accessing profile properties, as well as get_posts()
1113
+ * and for own profile get_saved_posts().
1114
+ *
1115
+ * This class implements equality comparison and is hashable.
1116
+ */
1117
+ declare class Profile {
1118
+ private readonly _context;
1119
+ private _node;
1120
+ private _has_public_story;
1121
+ private _has_full_metadata;
1122
+ private _iphone_struct_;
1123
+ constructor(context: InstaloaderContext, node: JsonObject);
1124
+ /**
1125
+ * Create a Profile instance from a given username.
1126
+ * Raises exception if it does not exist.
1127
+ */
1128
+ static fromUsername(context: InstaloaderContext, username: string): Promise<Profile>;
1129
+ /**
1130
+ * Create a Profile instance from a given userid.
1131
+ * If possible, use fromUsername or constructor instead.
1132
+ */
1133
+ static fromId(context: InstaloaderContext, profileId: number): Promise<Profile>;
1134
+ /**
1135
+ * Create a profile from a given iphone_struct.
1136
+ */
1137
+ static fromIphoneStruct(context: InstaloaderContext, media: JsonObject): Profile;
1138
+ /**
1139
+ * Return own profile if logged-in.
1140
+ */
1141
+ static ownProfile(context: InstaloaderContext): Promise<Profile>;
1142
+ private _obtainMetadata;
1143
+ private _metadata;
1144
+ /**
1145
+ * Async version that can fetch full metadata if needed.
1146
+ */
1147
+ getMetadata(...keys: string[]): Promise<JsonValue>;
1148
+ /** User ID */
1149
+ get userid(): number;
1150
+ /** Profile Name (lowercase) */
1151
+ get username(): string;
1152
+ toString(): string;
1153
+ equals(other: Profile): boolean;
1154
+ /** Whether this is a private profile */
1155
+ get is_private(): boolean;
1156
+ /** Whether the viewer follows this profile */
1157
+ get followed_by_viewer(): boolean;
1158
+ /** Number of posts */
1159
+ getMediacount(): Promise<number>;
1160
+ /** Number of followers */
1161
+ getFollowers(): Promise<number>;
1162
+ /** Number of followees */
1163
+ getFollowees(): Promise<number>;
1164
+ /** External URL in bio */
1165
+ getExternalUrl(): Promise<string | null>;
1166
+ /** Whether this is a business account */
1167
+ getIsBusinessAccount(): Promise<boolean>;
1168
+ /** Business category name */
1169
+ getBusinessCategoryName(): Promise<string | null>;
1170
+ /** Biography (normalized) */
1171
+ getBiography(): Promise<string>;
1172
+ /** Full name */
1173
+ getFullName(): Promise<string>;
1174
+ /** Whether the viewer blocked this profile */
1175
+ get blocked_by_viewer(): boolean;
1176
+ /** Whether this profile follows the viewer */
1177
+ get follows_viewer(): boolean;
1178
+ /** Whether this profile has blocked the viewer */
1179
+ get has_blocked_viewer(): boolean;
1180
+ /** Whether this profile is verified */
1181
+ getIsVerified(): Promise<boolean>;
1182
+ /** Profile picture URL */
1183
+ getProfilePicUrl(): Promise<string>;
1184
+ /**
1185
+ * Helper to check if a post is newer than the current first post.
1186
+ * Used for determining the "first" (newest) post in an iteration.
1187
+ */
1188
+ private static _makeIsNewestChecker;
1189
+ /**
1190
+ * Retrieve all posts from a profile.
1191
+ *
1192
+ * @returns NodeIterator[Post]
1193
+ */
1194
+ getPosts(): NodeIterator<Post>;
1195
+ /**
1196
+ * Get Posts that are marked as saved by the user.
1197
+ *
1198
+ * @returns NodeIterator[Post]
1199
+ * @throws LoginRequiredException if not logged in as the target profile
1200
+ */
1201
+ getSavedPosts(): NodeIterator<Post>;
1202
+ /**
1203
+ * Retrieve all posts where a profile is tagged.
1204
+ *
1205
+ * @returns NodeIterator[Post]
1206
+ */
1207
+ getTaggedPosts(): NodeIterator<Post>;
1208
+ /** Returns Profile as a JSON-serializable object. */
1209
+ toJSON(): JsonObject;
1210
+ }
1211
+ /**
1212
+ * Structure containing information about a user story item (image or video).
1213
+ *
1214
+ * Created by method Story.get_items(). This class implements equality comparison
1215
+ * and is hashable.
1216
+ */
1217
+ declare class StoryItem {
1218
+ private readonly _context;
1219
+ private readonly _node;
1220
+ private _owner_profile;
1221
+ private _iphone_struct_;
1222
+ constructor(context: InstaloaderContext, node: JsonObject, owner_profile?: Profile | null);
1223
+ /**
1224
+ * Create a StoryItem object from a given mediaid.
1225
+ */
1226
+ static fromMediaid(context: InstaloaderContext, mediaid: bigint): Promise<StoryItem>;
1227
+ /** The mediaid is a decimal representation of the media shortcode. */
1228
+ get mediaid(): bigint;
1229
+ /** Convert mediaid to a shortcode-like string. */
1230
+ get shortcode(): string;
1231
+ toString(): string;
1232
+ equals(other: StoryItem): boolean;
1233
+ /** Profile instance of the story item's owner. */
1234
+ getOwnerProfile(): Promise<Profile>;
1235
+ /** The StoryItem owner's lowercase name. */
1236
+ getOwnerUsername(): Promise<string>;
1237
+ /** The ID of the StoryItem owner. */
1238
+ getOwnerId(): Promise<number>;
1239
+ /** Timestamp when the StoryItem was created (local time zone). */
1240
+ get date_local(): Date;
1241
+ /** Timestamp when the StoryItem was created (UTC). */
1242
+ get date_utc(): Date;
1243
+ /** Synonym to date_utc */
1244
+ get date(): Date;
1245
+ /** Timestamp when the StoryItem will get unavailable (local time zone). */
1246
+ get expiring_local(): Date;
1247
+ /** Timestamp when the StoryItem will get unavailable (UTC). */
1248
+ get expiring_utc(): Date;
1249
+ /** URL of the picture / video thumbnail of the StoryItem */
1250
+ get url(): string;
1251
+ /** Type of story item: GraphStoryImage or GraphStoryVideo */
1252
+ get typename(): string;
1253
+ /** Caption. */
1254
+ get caption(): string | null;
1255
+ /** List of all lowercased hashtags in the StoryItem's caption. */
1256
+ get caption_hashtags(): string[];
1257
+ /** List of all lowercased profiles mentioned in the StoryItem's caption. */
1258
+ get caption_mentions(): string[];
1259
+ /** Printable caption. */
1260
+ get pcaption(): string;
1261
+ /** True if the StoryItem is a video. */
1262
+ get is_video(): boolean;
1263
+ /** URL of the video, or null. */
1264
+ get video_url(): string | null;
1265
+ /** Returns StoryItem as a JSON-serializable object. */
1266
+ toJSON(): JsonObject;
1267
+ }
1268
+ /**
1269
+ * Structure representing a user story with its associated items.
1270
+ *
1271
+ * Provides methods for accessing story properties, as well as getItems()
1272
+ * to request associated StoryItem nodes.
1273
+ *
1274
+ * This class implements equality comparison and is hashable.
1275
+ */
1276
+ declare class Story {
1277
+ protected readonly _context: InstaloaderContext;
1278
+ protected readonly _node: JsonObject;
1279
+ protected _unique_id: string | null;
1280
+ protected _owner_profile: Profile | null;
1281
+ protected _iphone_struct_: JsonObject | null;
1282
+ constructor(context: InstaloaderContext, node: JsonObject);
1283
+ toString(): string;
1284
+ equals(other: Story): boolean;
1285
+ /**
1286
+ * This ID only equals amongst Story instances which have the same owner
1287
+ * and the same set of StoryItem.
1288
+ */
1289
+ get unique_id(): string;
1290
+ /** Timestamp of the most recent StoryItem that has been watched or null (local time zone). */
1291
+ get last_seen_local(): Date | null;
1292
+ /** Timestamp of the most recent StoryItem that has been watched or null (UTC). */
1293
+ get last_seen_utc(): Date | null;
1294
+ /** Timestamp when the last item of the story was created (local time zone). */
1295
+ get latest_media_local(): Date;
1296
+ /** Timestamp when the last item of the story was created (UTC). */
1297
+ get latest_media_utc(): Date;
1298
+ /** Count of items associated with the Story instance. */
1299
+ get itemcount(): number;
1300
+ /** Profile instance of the story owner. */
1301
+ get owner_profile(): Profile;
1302
+ /** The story owner's lowercase username. */
1303
+ get owner_username(): string;
1304
+ /** The story owner's ID. */
1305
+ get owner_id(): number;
1306
+ protected _fetchIphoneStruct(): Promise<void>;
1307
+ /** Retrieve all items from a story. */
1308
+ getItems(): AsyncGenerator<StoryItem>;
1309
+ }
1310
+ /**
1311
+ * Structure representing a user's highlight with its associated story items.
1312
+ *
1313
+ * Extends Story and provides methods for accessing highlight properties.
1314
+ */
1315
+ declare class Highlight extends Story {
1316
+ private _items;
1317
+ constructor(context: InstaloaderContext, node: JsonObject, owner?: Profile | null);
1318
+ toString(): string;
1319
+ /** A unique ID identifying this set of highlights. */
1320
+ get unique_id(): string;
1321
+ /** Profile instance of the highlights' owner. */
1322
+ get owner_profile(): Profile;
1323
+ /** The title of these highlights. */
1324
+ get title(): string;
1325
+ /** URL of the highlights' cover. */
1326
+ get cover_url(): string;
1327
+ /** URL of the cropped version of the cover. */
1328
+ get cover_cropped_url(): string;
1329
+ private _fetchItems;
1330
+ protected _fetchIphoneStruct(): Promise<void>;
1331
+ /** Count of items associated with the Highlight instance. */
1332
+ get itemcount(): number;
1333
+ /** Get accurate item count (async). */
1334
+ getItemcount(): Promise<number>;
1335
+ /** Retrieve all associated highlight items. */
1336
+ getItems(): AsyncGenerator<StoryItem>;
1337
+ }
1338
+ /**
1339
+ * An Instagram Hashtag.
1340
+ *
1341
+ * Provides methods for accessing hashtag properties and retrieving associated posts.
1342
+ * This class implements equality comparison and is hashable.
1343
+ */
1344
+ declare class Hashtag {
1345
+ private readonly _context;
1346
+ private _node;
1347
+ private _has_full_metadata;
1348
+ constructor(context: InstaloaderContext, node: JsonObject);
1349
+ /**
1350
+ * Create a Hashtag instance from a given hashtag name, without preceding '#'.
1351
+ */
1352
+ static fromName(context: InstaloaderContext, name: string): Promise<Hashtag>;
1353
+ /** Hashtag name lowercased, without preceding '#' */
1354
+ get name(): string;
1355
+ private _query;
1356
+ private _obtainMetadata;
1357
+ private _metadata;
1358
+ getMetadata(...keys: string[]): Promise<JsonValue>;
1359
+ toString(): string;
1360
+ equals(other: Hashtag): boolean;
1361
+ /** Hashtag ID */
1362
+ getHashtagId(): Promise<number>;
1363
+ /** Profile picture URL of the hashtag */
1364
+ getProfilePicUrl(): Promise<string>;
1365
+ /** Hashtag description */
1366
+ getDescription(): Promise<string | null>;
1367
+ /** Whether following is allowed */
1368
+ getAllowFollowing(): Promise<boolean>;
1369
+ /** Whether the current user is following this hashtag */
1370
+ getIsFollowing(): Promise<boolean>;
1371
+ /** Count of all media associated with this hashtag */
1372
+ getMediacount(): Promise<number>;
1373
+ /** Yields the top posts of the hashtag. */
1374
+ getTopPosts(): AsyncGenerator<Post>;
1375
+ /**
1376
+ * Yields the recent posts associated with this hashtag.
1377
+ *
1378
+ * @deprecated Use getPostsResumable() as this method may return incorrect results.
1379
+ */
1380
+ getPosts(): AsyncGenerator<Post>;
1381
+ /**
1382
+ * Get the recent posts of the hashtag in a resumable fashion.
1383
+ *
1384
+ * @returns NodeIterator[Post]
1385
+ */
1386
+ getPostsResumable(): NodeIterator<Post>;
1387
+ /** Returns Hashtag as a JSON-serializable object. */
1388
+ toJSON(): JsonObject;
1389
+ }
1390
+ /**
1391
+ * An invocation of this class triggers a search on Instagram for the provided search string.
1392
+ *
1393
+ * Provides methods to access the search results as profiles, locations and hashtags.
1394
+ */
1395
+ declare class TopSearchResults {
1396
+ private readonly _context;
1397
+ private readonly _searchstring;
1398
+ private _node;
1399
+ constructor(context: InstaloaderContext, searchstring: string);
1400
+ private _ensureLoaded;
1401
+ /** Provides the Profile instances from the search result. */
1402
+ getProfiles(): AsyncGenerator<Profile>;
1403
+ /** Provides all profile names from the search result that start with the search string. */
1404
+ getPrefixedUsernames(): AsyncGenerator<string>;
1405
+ /** Provides instances of PostLocation from the search result. */
1406
+ getLocations(): AsyncGenerator<PostLocation>;
1407
+ /** Provides the hashtags from the search result as strings. */
1408
+ getHashtagStrings(): AsyncGenerator<string>;
1409
+ /** Provides the hashtags from the search result. */
1410
+ getHashtags(): AsyncGenerator<Hashtag>;
1411
+ /** The string that was searched for on Instagram. */
1412
+ get searchstring(): string;
1413
+ }
1414
+ /**
1415
+ * Type that can be exported to JSON.
1416
+ */
1417
+ type JsonExportable = Post | Profile | StoryItem | Hashtag;
1418
+ /**
1419
+ * Returns Instaloader JSON structure for a Post, Profile, StoryItem, or Hashtag
1420
+ * so that it can be loaded by loadStructure.
1421
+ */
1422
+ declare function getJsonStructure(structure: JsonExportable): JsonObject;
1423
+ /**
1424
+ * Loads a Post, Profile, StoryItem, or Hashtag from a json structure.
1425
+ */
1426
+ declare function loadStructure(context: InstaloaderContext, jsonStructure: JsonObject): JsonExportable;
1427
+
1428
+ /**
1429
+ * Instaloader - Main class for downloading Instagram content.
1430
+ *
1431
+ * Ported from Python instaloader/instaloader.py
1432
+ */
1433
+
1434
+ /**
1435
+ * Options for the Instaloader class.
1436
+ */
1437
+ interface InstaloaderOptions {
1438
+ /** Enable sleep between requests (rate limiting) */
1439
+ sleep?: boolean;
1440
+ /** Suppress output messages */
1441
+ quiet?: boolean;
1442
+ /** Custom user agent string */
1443
+ userAgent?: string;
1444
+ /** Directory pattern for downloads, default is "{target}" */
1445
+ dirnamePattern?: string;
1446
+ /** Filename pattern for downloads, default is "{date_utc}_UTC" */
1447
+ filenamePattern?: string;
1448
+ /** Title pattern for profile pics and covers */
1449
+ titlePattern?: string;
1450
+ /** Download pictures, default true */
1451
+ downloadPictures?: boolean;
1452
+ /** Download videos, default true */
1453
+ downloadVideos?: boolean;
1454
+ /** Download video thumbnails, default true */
1455
+ downloadVideoThumbnails?: boolean;
1456
+ /** Download geotags, default false */
1457
+ downloadGeotags?: boolean;
1458
+ /** Download comments, default false */
1459
+ downloadComments?: boolean;
1460
+ /** Save metadata JSON, default true */
1461
+ saveMetadata?: boolean;
1462
+ /** Compress JSON files with xz, default true */
1463
+ compressJson?: boolean;
1464
+ /** Pattern for post metadata txt files */
1465
+ postMetadataTxtPattern?: string;
1466
+ /** Pattern for story item metadata txt files */
1467
+ storyitemMetadataTxtPattern?: string;
1468
+ /** Maximum connection attempts, default 3 */
1469
+ maxConnectionAttempts?: number;
1470
+ /** Request timeout in seconds, default 300 */
1471
+ requestTimeout?: number;
1472
+ /** Custom rate controller factory */
1473
+ rateController?: (context: InstaloaderContext) => RateController;
1474
+ /** Resume file prefix, or null to disable resume */
1475
+ resumePrefix?: string | null;
1476
+ /** Check best-before date of resume files */
1477
+ checkResumeBbd?: boolean;
1478
+ /** Slide range for sidecar downloads (e.g., "1-3", "last") */
1479
+ slide?: string;
1480
+ /** Status codes that should abort the download */
1481
+ fatalStatusCodes?: number[];
1482
+ /** Enable iPhone API support */
1483
+ iphoneSupport?: boolean;
1484
+ /** Sanitize paths for Windows compatibility */
1485
+ sanitizePaths?: boolean;
1486
+ }
1487
+ /**
1488
+ * Gets the config directory for storing sessions and stamps.
1489
+ */
1490
+ declare function getConfigDir(): string;
1491
+ /**
1492
+ * Returns the default session filename for a given username.
1493
+ */
1494
+ declare function getDefaultSessionFilename(username: string): string;
1495
+ /**
1496
+ * Returns the default stamps filename.
1497
+ */
1498
+ declare function getDefaultStampsFilename(): string;
1499
+ /**
1500
+ * Check if a format string contains a specific key.
1501
+ */
1502
+ declare function formatStringContainsKey(formatString: string, key: string): boolean;
1503
+ /**
1504
+ * Sanitize a path component for safe filesystem usage.
1505
+ */
1506
+ declare function sanitizePath(str: string, forceWindowsPath?: boolean): string;
1507
+ /**
1508
+ * Format a filename with item attributes.
1509
+ * Note: This is a simplified synchronous version. Some properties like owner
1510
+ * require async access in the TypeScript version.
1511
+ */
1512
+ declare function formatFilename(pattern: string, item: Post | StoryItem | Profile, target?: string, sanitize?: boolean): string;
1513
+ /**
1514
+ * Main Instaloader class for downloading Instagram content.
1515
+ *
1516
+ * @example
1517
+ * ```typescript
1518
+ * const L = new Instaloader();
1519
+ *
1520
+ * // Login
1521
+ * await L.login('username', 'password');
1522
+ *
1523
+ * // Download a profile
1524
+ * const profile = await Profile.fromUsername(L.context, 'instagram');
1525
+ * await L.downloadProfile(profile);
1526
+ *
1527
+ * // Save session for later
1528
+ * await L.saveSessionToFile();
1529
+ * ```
1530
+ */
1531
+ declare class Instaloader {
1532
+ /** The associated InstaloaderContext for low-level operations */
1533
+ readonly context: InstaloaderContext;
1534
+ readonly dirnamePattern: string;
1535
+ readonly filenamePattern: string;
1536
+ readonly titlePattern: string;
1537
+ readonly downloadPictures: boolean;
1538
+ readonly downloadVideos: boolean;
1539
+ readonly downloadVideoThumbnails: boolean;
1540
+ readonly downloadGeotags: boolean;
1541
+ readonly downloadComments: boolean;
1542
+ readonly saveMetadata: boolean;
1543
+ readonly compressJson: boolean;
1544
+ readonly postMetadataTxtPattern: string;
1545
+ readonly storyitemMetadataTxtPattern: string;
1546
+ readonly resumePrefix: string | null;
1547
+ readonly checkResumeBbd: boolean;
1548
+ readonly sanitizePaths: boolean;
1549
+ readonly slide: string;
1550
+ private slideStart;
1551
+ private slideEnd;
1552
+ constructor(options?: InstaloaderOptions);
1553
+ /**
1554
+ * Close the session and clean up resources.
1555
+ */
1556
+ close(): void;
1557
+ /**
1558
+ * Save session to a dictionary.
1559
+ */
1560
+ saveSession(): Record<string, string>;
1561
+ /**
1562
+ * Load session from a dictionary.
1563
+ */
1564
+ loadSession(username: string, sessionData: Record<string, string>): void;
1565
+ /**
1566
+ * Save session to file.
1567
+ */
1568
+ saveSessionToFile(filename?: string): Promise<void>;
1569
+ /**
1570
+ * Load session from file.
1571
+ */
1572
+ loadSessionFromFile(username: string, filename?: string): Promise<void>;
1573
+ /**
1574
+ * Test if the current session is valid.
1575
+ * Returns the username if logged in, null otherwise.
1576
+ */
1577
+ testLogin(): Promise<string | null>;
1578
+ /**
1579
+ * Login with username and password.
1580
+ */
1581
+ login(user: string, passwd: string): Promise<void>;
1582
+ /**
1583
+ * Complete two-factor authentication.
1584
+ */
1585
+ twoFactorLogin(twoFactorCode: string): Promise<void>;
1586
+ /**
1587
+ * Download a picture or video from a URL.
1588
+ *
1589
+ * @param filename - Base filename (without extension)
1590
+ * @param url - URL to download from
1591
+ * @param mtime - Modification time to set on the file
1592
+ * @param filenameSuffix - Optional suffix to add before extension
1593
+ * @returns True if file was downloaded, false if it already existed
1594
+ */
1595
+ downloadPic(filename: string, url: string, mtime: Date, filenameSuffix?: string): Promise<boolean>;
1596
+ /**
1597
+ * Save metadata JSON for a structure.
1598
+ */
1599
+ saveMetadataJson(filename: string, structure: Post | StoryItem | Profile): Promise<void>;
1600
+ /**
1601
+ * Save caption to a text file.
1602
+ */
1603
+ saveCaption(filename: string, mtime: Date, caption: string): Promise<void>;
1604
+ /**
1605
+ * Download a single post.
1606
+ *
1607
+ * @param post - Post to download
1608
+ * @param target - Target directory name
1609
+ * @returns True if something was downloaded
1610
+ */
1611
+ downloadPost(post: Post, target: string): Promise<boolean>;
1612
+ /**
1613
+ * Download posts from an iterator.
1614
+ *
1615
+ * @param posts - Iterator of posts
1616
+ * @param target - Target directory name
1617
+ * @param options - Download options
1618
+ */
1619
+ downloadPosts(posts: AsyncIterable<Post>, target: string, options?: {
1620
+ fastUpdate?: boolean;
1621
+ postFilter?: (post: Post) => boolean;
1622
+ maxCount?: number;
1623
+ totalCount?: number;
1624
+ ownerProfile?: Profile;
1625
+ possiblyPinned?: number;
1626
+ }): Promise<void>;
1627
+ /**
1628
+ * Download a profile's posts.
1629
+ */
1630
+ downloadProfile(profile: Profile, options?: {
1631
+ fastUpdate?: boolean;
1632
+ postFilter?: (post: Post) => boolean;
1633
+ maxCount?: number;
1634
+ downloadProfilePic?: boolean;
1635
+ downloadStories?: boolean;
1636
+ downloadHighlights?: boolean;
1637
+ }): Promise<void>;
1638
+ /**
1639
+ * Download a profile's profile picture.
1640
+ */
1641
+ downloadProfilePic(profile: Profile): Promise<void>;
1642
+ /**
1643
+ * Download posts for a hashtag.
1644
+ */
1645
+ downloadHashtag(hashtag: Hashtag, options?: {
1646
+ maxCount?: number;
1647
+ postFilter?: (post: Post) => boolean;
1648
+ resumable?: boolean;
1649
+ }): Promise<void>;
1650
+ /**
1651
+ * Get a profile by username.
1652
+ */
1653
+ getProfile(username: string): Promise<Profile>;
1654
+ /**
1655
+ * Get a post by shortcode.
1656
+ */
1657
+ getPost(shortcode: string): Promise<Post>;
1658
+ /**
1659
+ * Get a hashtag by name.
1660
+ */
1661
+ getHashtag(name: string): Promise<Hashtag>;
1662
+ }
1663
+
1664
+ export { AbortDownloadException, BadCredentialsException, BadResponseException, CheckpointRequiredException, type CommentNode, ConnectionException, type CookieData, type EdgeConnection, type FrozenIteratorState, FrozenNodeIterator, type GraphQLResponse, Hashtag, type HashtagNode, Highlight, type HighlightNode, type HttpHeaders, type IPhoneHeaders, IPhoneSupportDisabledException, Instaloader, InstaloaderContext, type InstaloaderContextOptions, InstaloaderException, type InstaloaderOptions, InvalidArgumentException, InvalidIteratorException, type JsonExportable, type JsonObject, type JsonValue, type LocationNode, LoginException, LoginRequiredException, type LoginResponse, NodeIterator, type NodeIteratorOptions, type PageInfo, type PhoneVerificationSettings, Post, PostChangedException, PostComment, type PostCommentAnswer, type PostLocation, type PostNode, type PostSidecarNode, PrivateProfileNotFollowedException, Profile, ProfileHasNoPicsException, type ProfileNode, ProfileNotExistsException, QueryReturnedBadRequestException, QueryReturnedForbiddenException, QueryReturnedNotFoundException, type QueryTimestamps, RateController, type RequestOptions, type ResponseInfo, type ResumableIterationOptions, type ResumableIterationResult, type SessionData, SessionNotFoundException, Story, StoryItem, type StoryItemNode, NodeIterator as StructureNodeIterator, TooManyRequestsException, TopSearchResults, TwoFactorAuthRequiredException, type TwoFactorInfo, defaultIphoneHeaders, defaultUserAgent, extractHashtags, extractMentions, formatFilename, formatStringContainsKey, getConfigDir, getDefaultSessionFilename, getDefaultStampsFilename, getJsonStructure, loadStructure, mediaidToShortcode, resumableIteration, sanitizePath, shortcodeToMediaid };