instagram-archiver 0.2.0__py3-none-any.whl → 0.3.0__py3-none-any.whl

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.

Potentially problematic release.


This version of instagram-archiver might be problematic. Click here for more details.

@@ -0,0 +1,170 @@
1
+ """Typing helpers."""
2
+ # ruff: noqa: D101
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Literal, NotRequired, TypedDict
6
+
7
+ if TYPE_CHECKING:
8
+ from collections.abc import Sequence
9
+
10
+ __all__ = ('BrowserName', 'CarouselMedia', 'Comments', 'Edge', 'HasID', 'HighlightsTray',
11
+ 'MediaInfo', 'MediaInfoItem', 'MediaInfoItemImageVersions2Candidate', 'UserInfo',
12
+ 'WebProfileInfo', 'WebProfileInfoData', 'XDTAPIV1FeedUserTimelineGraphQLConnection',
13
+ 'XDTAPIV1FeedUserTimelineGraphQLConnectionContainer', 'XDTMediaDict')
14
+
15
+
16
+ class MediaInfoItemVideoVersion(TypedDict):
17
+ height: int
18
+ url: str
19
+ width: int
20
+
21
+
22
+ class MediaInfoItemImageVersions2Candidate(TypedDict):
23
+ height: int
24
+ """Height of the image."""
25
+ url: str
26
+ """URL of the image."""
27
+ width: int
28
+ """Width of the image."""
29
+
30
+
31
+ class HighlightItem(TypedDict):
32
+ id: str
33
+ """Identifier."""
34
+
35
+
36
+ class HighlightsTray(TypedDict):
37
+ tray: Sequence[HighlightItem]
38
+ """Highlights tray items."""
39
+
40
+
41
+ class PageInfo(TypedDict):
42
+ end_cursor: str
43
+ """End cursor for pagination."""
44
+ has_next_page: bool
45
+ """Whether there are more pages."""
46
+
47
+
48
+ class EdgeOwnerToTimelineMedia(TypedDict):
49
+ edges: Sequence[Edge]
50
+ page_info: PageInfo
51
+ """Pagination information."""
52
+
53
+
54
+ class UserInfo(TypedDict):
55
+ """User information."""
56
+ edge_owner_to_timeline_media: EdgeOwnerToTimelineMedia
57
+ """Timeline media edge."""
58
+ id: str
59
+ """User ID."""
60
+ profile_pic_url_hd: str
61
+ """Profile picture URL."""
62
+
63
+
64
+ class MediaInfoItemImageVersions2(TypedDict):
65
+ candidates: Sequence[MediaInfoItemImageVersions2Candidate]
66
+ """Image versions."""
67
+
68
+
69
+ class CarouselMedia(TypedDict):
70
+ image_versions2: MediaInfoItemImageVersions2
71
+ """Image versions."""
72
+ id: str
73
+ """Identifier."""
74
+
75
+
76
+ class HasID(TypedDict):
77
+ """Dictionary with an ``id`` field."""
78
+ id: str
79
+ """Identifier."""
80
+
81
+
82
+ class MediaInfoItem(TypedDict):
83
+ """Media information item."""
84
+ carousel_media: NotRequired[Sequence[CarouselMedia] | None]
85
+ """Carousel media items."""
86
+ image_versions2: MediaInfoItemImageVersions2
87
+ """Image versions."""
88
+ id: str
89
+ """Identifier."""
90
+ taken_at: int
91
+ """Timestamp when the media was taken"""
92
+ user: HasID
93
+ """User who posted the media."""
94
+ video_dash_manifest: NotRequired[str | None]
95
+ """URL of the video dash manifest."""
96
+ video_duration: float
97
+ """Duration of the video in seconds."""
98
+ video_versions: Sequence[MediaInfoItemVideoVersion]
99
+ """Video versions."""
100
+
101
+
102
+ class Comments(TypedDict):
103
+ """Comments container."""
104
+ can_view_more_preview_comments: bool
105
+ """Whether more preview comments can be viewed."""
106
+ comments: Sequence[HasID]
107
+ """List of comments."""
108
+ next_min_id: str
109
+ """Next minimum ID for pagination."""
110
+
111
+
112
+ class MediaInfo(TypedDict):
113
+ """Media information."""
114
+ items: Sequence[MediaInfoItem]
115
+ """List of media items."""
116
+
117
+
118
+ class Owner(TypedDict):
119
+ id: str
120
+ """Owner ID."""
121
+ username: str
122
+ """Owner username."""
123
+
124
+
125
+ class XDTMediaDict(TypedDict):
126
+ __typename: Literal['XDTMediaDict']
127
+ """Type name."""
128
+ code: str
129
+ """Short code."""
130
+ id: str
131
+ """Media ID."""
132
+ owner: Owner
133
+ """Owner information."""
134
+ video_dash_manifest: NotRequired[str | None]
135
+ """Video dash manifest URL, if available."""
136
+
137
+
138
+ class Edge(TypedDict):
139
+ """Edge of a graph."""
140
+ node: XDTMediaDict
141
+ """Node at this edge."""
142
+
143
+
144
+ class XDTAPIV1FeedUserTimelineGraphQLConnection(TypedDict):
145
+ edges: Sequence[Edge]
146
+ """Edges of the graph."""
147
+ page_info: PageInfo
148
+ """Pagination information."""
149
+
150
+
151
+ class XDTAPIV1FeedUserTimelineGraphQLConnectionContainer(TypedDict):
152
+ """Container for :py:class:`XDTAPIV1FeedUserTimelineGraphQLConnection`."""
153
+ xdt_api__v1__feed__user_timeline_graphql_connection: XDTAPIV1FeedUserTimelineGraphQLConnection
154
+ """User timeline data."""
155
+
156
+
157
+ class WebProfileInfoData(TypedDict):
158
+ user: UserInfo
159
+ """User information."""
160
+
161
+
162
+ class WebProfileInfo(TypedDict):
163
+ """Profile information container."""
164
+ data: WebProfileInfoData
165
+ """Profile data."""
166
+
167
+
168
+ BrowserName = Literal['brave', 'chrome', 'chromium', 'edge', 'firefox', 'opera', 'safari',
169
+ 'vivaldi']
170
+ """Possible browser choices to get cookies from."""
@@ -1,55 +1,112 @@
1
- from contextlib import contextmanager
2
- from os import chdir as os_chdir, getcwd
3
- from os.path import isfile
1
+ """Utility functions."""
2
+ from __future__ import annotations
3
+
4
4
  from pathlib import Path
5
- from types import FrameType
6
- from typing import Generic, Iterator, Literal, TypeVar
5
+ from typing import TYPE_CHECKING, Any, Literal, Protocol, TypeVar, override
7
6
  import json
8
7
  import logging
9
- import sys
8
+ import logging.config
10
9
 
11
- from loguru import logger
12
10
  import click
13
11
 
14
- __all__ = ('UnknownMimetypeError', 'chdir', 'get_extension', 'json_dumps_formatted', 'write_if_new')
12
+ if TYPE_CHECKING:
13
+ from .typing import Edge
14
+
15
+ __all__ = ('JSONFormattedString', 'UnknownMimetypeError', 'get_extension', 'json_dumps_formatted',
16
+ 'setup_logging', 'write_if_new')
15
17
 
16
18
  T = TypeVar('T')
17
19
 
18
20
 
19
- class JSONFormattedString(Generic[T]): # pylint: disable=too-few-public-methods
20
- def __init__(self, formatted: str, original: T) -> None:
21
+ def setup_logging(*,
22
+ debug: bool = False,
23
+ force_color: bool = False,
24
+ no_color: bool = False) -> None: # pragma: no cover
25
+ """Set up logging configuration."""
26
+ logging.config.dictConfig({
27
+ 'version': 1,
28
+ 'disable_existing_loggers': True,
29
+ 'root': {
30
+ 'handlers': ('console',),
31
+ 'level': 'DEBUG' if debug else 'INFO',
32
+ },
33
+ 'formatters': {
34
+ 'default': {
35
+ '()': 'colorlog.ColoredFormatter',
36
+ 'force_color': force_color,
37
+ 'format':
38
+ '%(log_color)s%(levelname)-8s%(reset)s | %(light_green)s%(name)s%(reset)s:'
39
+ '%(light_red)s%(funcName)s%(reset)s:%(blue)s%(lineno)d%(reset)s - %(message)s',
40
+ 'no_color': no_color,
41
+ },
42
+ 'simple': {
43
+ 'format': '%(message)s',
44
+ },
45
+ },
46
+ 'handlers': {
47
+ 'console': {
48
+ 'class': 'colorlog.StreamHandler',
49
+ 'formatter': 'default' if debug else 'simple',
50
+ },
51
+ },
52
+ 'loggers': {
53
+ 'instagram_archiver': {
54
+ 'handlers': ('console',),
55
+ 'propagate': False,
56
+ },
57
+ 'urllib3': {
58
+ 'handlers': ('console',),
59
+ 'propagate': False,
60
+ }
61
+ },
62
+ })
63
+
64
+
65
+ class JSONFormattedString:
66
+ """Contains a formatted version of the JSON str and the original value."""
67
+ def __init__(self, formatted: str, original: Any) -> None:
21
68
  self.formatted = formatted
69
+ """Formatted JSON string."""
22
70
  self.original_value = original
71
+ """Original value."""
23
72
 
73
+ @override
24
74
  def __str__(self) -> str:
25
75
  return self.formatted
26
76
 
27
77
 
28
- def json_dumps_formatted(obj: T) -> JSONFormattedString[T]:
29
- return JSONFormattedString(json.dumps(obj, sort_keys=True, indent=2), obj)
78
+ def json_dumps_formatted(obj: Any) -> JSONFormattedString:
79
+ """
80
+ Return a special object with the formatted version of the JSON str and the original.
30
81
 
31
-
32
- @contextmanager
33
- def chdir(path: str | Path) -> Iterator[None]:
34
- old_path = getcwd()
35
- os_chdir(path)
36
- try:
37
- yield
38
- finally:
39
- chdir(old_path)
82
+ Parameters
83
+ ----------
84
+ obj : Any
85
+ The object to be formatted.
86
+ """
87
+ return JSONFormattedString(json.dumps(obj, sort_keys=True, indent=2), obj)
40
88
 
41
89
 
42
90
  def write_if_new(target: Path | str, content: str | bytes, mode: str = 'w') -> None:
43
- if not isfile(target):
91
+ """Write a file only if it will be a new file."""
92
+ if not Path(target).is_file():
44
93
  with click.open_file(str(target), mode) as f:
45
94
  f.write(content)
46
95
 
47
96
 
48
97
  class UnknownMimetypeError(Exception):
49
- pass
98
+ """Raised when an unknown mimetype is encountered in :py:func:`~get_extension`."""
50
99
 
51
100
 
52
101
  def get_extension(mimetype: str) -> Literal['png', 'jpg']:
102
+ """
103
+ Get the appropriate three-letter extension for a mimetype.
104
+
105
+ Raises
106
+ ------
107
+ UnknownMimetypeError
108
+ If the mimetype is not recognised.
109
+ """
53
110
  if mimetype == 'image/jpeg':
54
111
  return 'jpg'
55
112
  if mimetype == 'image/png':
@@ -57,54 +114,21 @@ def get_extension(mimetype: str) -> Literal['png', 'jpg']:
57
114
  raise UnknownMimetypeError(mimetype)
58
115
 
59
116
 
60
- class InterceptHandler(logging.Handler): # pragma: no cover
61
- """Intercept handler taken from Loguru's documentation."""
62
- def emit(self, record: logging.LogRecord) -> None:
63
- level: str | int
64
- # Get corresponding Loguru level if it exists
65
- try:
66
- level = logger.level(record.levelname).name
67
- except ValueError:
68
- level = record.levelno
69
- # Find caller from where originated the logged message
70
- frame: FrameType | None = logging.currentframe()
71
- depth = 2
72
- while frame and frame.f_code.co_filename == logging.__file__:
73
- frame = frame.f_back
74
- depth += 1
75
- logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())
76
-
77
-
78
- def setup_log_intercept_handler() -> None: # pragma: no cover
79
- """Sets up Loguru to intercept records from the logging module."""
80
- logging.basicConfig(handlers=(InterceptHandler(),), level=0)
81
-
82
-
83
- def setup_logging(debug: bool | None = False) -> None:
84
- """Shared function to enable logging."""
85
- if debug: # pragma: no cover
86
- setup_log_intercept_handler()
87
- logger.enable('')
88
- else:
89
- logger.configure(handlers=(dict(
90
- format='<level>{message}</level>',
91
- level='INFO',
92
- sink=sys.stderr,
93
- ),))
94
-
95
-
96
- class YoutubeDLLogger:
97
- def debug(self, message: str) -> None:
98
- if message.startswith('[debug] '):
99
- logger.debug(message)
100
- else:
101
- logger.info(message)
102
-
103
- def info(self, message: str) -> None:
104
- pass
105
-
106
- def warning(self, message: str) -> None:
107
- logger.warning(message)
108
-
109
- def error(self, message: str) -> None:
110
- logger.error(message)
117
+ if TYPE_CHECKING:
118
+
119
+ class InstagramClientInterface(Protocol):
120
+ should_save_comments: bool
121
+
122
+ def save_comments(self, edge: Edge) -> None:
123
+ ...
124
+ else:
125
+ InstagramClientInterface = object
126
+
127
+
128
+ class SaveCommentsCheckDisabledMixin(InstagramClientInterface):
129
+ """Mixin to control saving comments."""
130
+ @override
131
+ def save_comments(self, edge: Edge) -> None:
132
+ if not self.should_save_comments:
133
+ return
134
+ super().save_comments(edge) # type: ignore[safe-super]
@@ -0,0 +1,18 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 instagram-archiver authors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
+ associated documentation files (the "Software"), to deal in the Software without restriction,
7
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
8
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or
12
+ substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
17
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
18
+ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,119 @@
1
+ Metadata-Version: 2.3
2
+ Name: instagram-archiver
3
+ Version: 0.3.0
4
+ Summary: Save Instagram content you have access to.
5
+ License: MIT
6
+ Keywords: command line,instagram
7
+ Author: Andrew Udvare
8
+ Author-email: audvare@gmail.com
9
+ Requires-Python: >=3.12,<3.14
10
+ Classifier: Development Status :: 2 - Pre-Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Typing :: Typed
17
+ Requires-Dist: beautifulsoup4 (>=4.13.4,<5.0.0)
18
+ Requires-Dist: click (>=8.2.0,<9.0.0)
19
+ Requires-Dist: colorlog (>=6.9.0,<7.0.0)
20
+ Requires-Dist: html5lib (>=1.1,<2.0)
21
+ Requires-Dist: requests (>=2.32.3,<3.0.0)
22
+ Requires-Dist: typing-extensions (>=4.13.1,<5.0.0)
23
+ Requires-Dist: yt-dlp-utils (>=0,<1)
24
+ Project-URL: Documentation, https://instagram-archiver.readthedocs.org
25
+ Project-URL: Homepage, https://tatsh.github.io/instagram-archiver/
26
+ Project-URL: Issues, https://github.com/Tatsh/instagram-archiver/issues
27
+ Project-URL: Repository, https://github.com/Tatsh/instagram-archiver
28
+ Description-Content-Type: text/markdown
29
+
30
+ # instagram-archiver
31
+
32
+ [![Python versions](https://img.shields.io/pypi/pyversions/instagram-archiver.svg?color=blue&logo=python&logoColor=white)](https://www.python.org/)
33
+ [![PyPI - Version](https://img.shields.io/pypi/v/instagram-archiver)](https://pypi.org/project/instagram-archiver/)
34
+ [![GitHub tag (with filter)](https://img.shields.io/github/v/tag/Tatsh/instagram-archiver)](https://github.com/Tatsh/instagram-archiver/tags)
35
+ [![License](https://img.shields.io/github/license/Tatsh/instagram-archiver)](https://github.com/Tatsh/instagram-archiver/blob/master/LICENSE.txt)
36
+ [![GitHub commits since latest release (by SemVer including pre-releases)](https://img.shields.io/github/commits-since/Tatsh/instagram-archiver/v0.3.0/master)](https://github.com/Tatsh/instagram-archiver/compare/v0.3.0...master)
37
+ [![QA](https://github.com/Tatsh/instagram-archiver/actions/workflows/qa.yml/badge.svg)](https://github.com/Tatsh/instagram-archiver/actions/workflows/qa.yml)
38
+ [![Tests](https://github.com/Tatsh/instagram-archiver/actions/workflows/tests.yml/badge.svg)](https://github.com/Tatsh/instagram-archiver/actions/workflows/tests.yml)
39
+ [![Coverage Status](https://coveralls.io/repos/github/Tatsh/instagram-archiver/badge.svg?branch=master)](https://coveralls.io/github/Tatsh/instagram-archiver?branch=master)
40
+ [![Documentation Status](https://readthedocs.org/projects/instagram-archiver/badge/?version=latest)](https://instagram-archiver.readthedocs.org/?badge=latest)
41
+ [![mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/)
42
+ [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
43
+ [![pydocstyle](https://img.shields.io/badge/pydocstyle-enabled-AD4CD3)](http://www.pydocstyle.org/en/stable/)
44
+ [![pytest](https://img.shields.io/badge/pytest-zz?logo=Pytest&labelColor=black&color=black)](https://docs.pytest.org/en/stable/)
45
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
46
+ [![Downloads](https://static.pepy.tech/badge/instagram-archiver/month)](https://pepy.tech/project/instagram-archiver)
47
+ [![Stargazers](https://img.shields.io/github/stars/Tatsh/instagram-archiver?logo=github&style=flat)](https://github.com/Tatsh/instagram-archiver/stargazers)
48
+
49
+ [![@Tatsh](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fpublic.api.bsky.app%2Fxrpc%2Fapp.bsky.actor.getProfile%2F%3Factor%3Ddid%3Aplc%3Auq42idtvuccnmtl57nsucz72%26query%3D%24.followersCount%26style%3Dsocial%26logo%3Dbluesky%26label%3DFollow%2520%40Tatsh&query=%24.followersCount&style=social&logo=bluesky&label=Follow%20%40Tatsh)](https://bsky.app/profile/Tatsh.bsky.social)
50
+ [![Mastodon Follow](https://img.shields.io/mastodon/follow/109370961877277568?domain=hostux.social&style=social)](https://hostux.social/@Tatsh)
51
+
52
+ Save Instagram content you have access to.
53
+
54
+ ## Installation
55
+
56
+ ### Poetry
57
+
58
+ ```shell
59
+ poetry add instagram-archiver
60
+ ```
61
+
62
+ ### Pip
63
+
64
+ ```shell
65
+ pip install instagram-archiver
66
+ ```
67
+
68
+ ## Usage
69
+
70
+ ```plain
71
+ Usage: instagram-archiver [OPTIONS] USERNAME
72
+
73
+ Archive a profile's posts.
74
+
75
+ Options:
76
+ -o, --output-dir DIRECTORY Output directory.
77
+ -b, --browser [brave|chrome|chromium|edge|opera|vivaldi|firefox|safari]
78
+ Browser to read cookies from.
79
+ -p, --profile TEXT Browser profile.
80
+ -d, --debug Enable debug output.
81
+ --no-log Ignore log (re-fetch everything).
82
+ -C, --include-comments Also download all comments (extends download
83
+ time significantly).
84
+ -h, --help Show this message and exit.
85
+ ```
86
+
87
+ Typical use:
88
+
89
+ ```shell
90
+ instagram-archiver -o ~/instagram-backups/username username
91
+ ```
92
+
93
+ ### `instagram-save-saved`
94
+
95
+ This tool saves your saved posts (at `www.instagram.com/username/saved/all-posts`).
96
+
97
+ ```plain
98
+ Usage: instagram-save-saved [OPTIONS]
99
+
100
+ Archive your saved posts.
101
+
102
+ Options:
103
+ -o, --output-dir DIRECTORY Output directory.
104
+ -b, --browser [brave|chrome|chromium|edge|opera|vivaldi|firefox|safari]
105
+ Browser to read cookies from.
106
+ -p, --profile TEXT Browser profile.
107
+ -d, --debug Enable debug output.
108
+ -C, --include-comments Also download all comments (extends download
109
+ time significantly).
110
+ -u, --unsave Unsave posts after successful archive.
111
+ -h, --help Show this message and exit.
112
+ ```
113
+
114
+ ## Notes
115
+
116
+ The default output path is the username under the current working directory.
117
+
118
+ Videos are saved using yt-dlp and its respective configuration.
119
+
@@ -0,0 +1,15 @@
1
+ instagram_archiver/__init__.py,sha256=406v5g-tu6QhUfdMTNgI9rYbPYm7WfjiIL68HOXLXQY,270
2
+ instagram_archiver/__main__.py,sha256=oQ6s6zvZTBiEOgt-qep3bDY9ayxSanQr7KHzr6ENK0o,115
3
+ instagram_archiver/client.py,sha256=uMYembbrYWKJdXlBpuYsSK-p7tuj0qG3WMVV8M785NE,11326
4
+ instagram_archiver/constants.py,sha256=NJ8QlQZviY3dwwrIONThK_G9VcvAzOQM6Yg-hSyaj9A,1459
5
+ instagram_archiver/main.py,sha256=lW8rHPjQpqNH8TqjitW3DMILazn09sSWxJhVlkUC5Ck,3808
6
+ instagram_archiver/profile_scraper.py,sha256=BGnJZD3rF2e4aHpqSvG7UBoAiDjTyrpcYKSzsDgHO3M,7988
7
+ instagram_archiver/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ instagram_archiver/saved_scraper.py,sha256=PHSXkmK-MC-42Z4GZzNCXa8dSD682NEav1rms7mL-yk,2722
9
+ instagram_archiver/typing.py,sha256=J8TcQftpIY-IVsbx007e1WbA-XdLUhBuEWWAisFlpHA,4306
10
+ instagram_archiver/utils.py,sha256=l6f0W_brZhVPOjlKwoFYYum7ICyHJXpboTU7ANIQSPI,3842
11
+ instagram_archiver-0.3.0.dist-info/LICENSE.txt,sha256=cDLmbhzFwEUz5FL_OnA6Jp9zdz80330J6YyEq-00yNQ,1093
12
+ instagram_archiver-0.3.0.dist-info/METADATA,sha256=Vq8yWfCHOzOJduL9E0PEcIGz9qu900uiI96c1g0q3-I,5925
13
+ instagram_archiver-0.3.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
14
+ instagram_archiver-0.3.0.dist-info/entry_points.txt,sha256=kNXd0Sy6896DEBRcx2mVYiaE-OR9-XR56MpWuaNa49g,128
15
+ instagram_archiver-0.3.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.5.2
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -0,0 +1,4 @@
1
+ [console_scripts]
2
+ instagram-archiver=instagram_archiver.main:main
3
+ instagram-save-saved=instagram_archiver.main:save_saved_main
4
+
@@ -1,117 +0,0 @@
1
- # pylint: disable=unused-private-member
2
- from typing import Literal, Sequence, TypedDict
3
-
4
- from typing_extensions import NotRequired
5
-
6
-
7
- class MediaInfoItemVideoVersion(TypedDict):
8
- height: int
9
- url: str
10
- width: int
11
-
12
-
13
- class MediaInfoItemImageVersions2Candidate(TypedDict):
14
- height: int
15
- url: str
16
- width: int
17
-
18
-
19
- class HighlightItem(TypedDict):
20
- id: str
21
-
22
-
23
- class HighlightsTray(TypedDict):
24
- tray: Sequence[HighlightItem]
25
-
26
-
27
- class EdgeOwnerToTimelineMediaPageInfo(TypedDict):
28
- end_cursor: str
29
- has_next_page: bool
30
-
31
-
32
- class EdgeOwnerToTimelineMedia(TypedDict):
33
- edges: Sequence['Edge']
34
- page_info: EdgeOwnerToTimelineMediaPageInfo
35
-
36
-
37
- class UserInfo(TypedDict):
38
- edge_owner_to_timeline_media: EdgeOwnerToTimelineMedia
39
- id: str
40
- profile_pic_url_hd: str
41
-
42
-
43
- class MediaInfoItemImageVersions2(TypedDict):
44
- candidates: Sequence[MediaInfoItemImageVersions2Candidate]
45
-
46
-
47
- class CarouselMedia(TypedDict):
48
- image_versions2: MediaInfoItemImageVersions2
49
- id: str
50
-
51
-
52
- class HasID(TypedDict):
53
- id: str
54
-
55
-
56
- class MediaInfoItem(TypedDict):
57
- carousel_media: NotRequired[list[CarouselMedia]]
58
- image_versions2: MediaInfoItemImageVersions2
59
- id: str
60
- taken_at: int
61
- user: HasID
62
- video_dash_manifest: str
63
- video_duration: float
64
- video_versions: Sequence[MediaInfoItemVideoVersion]
65
-
66
-
67
- class EdgeSidecarToChildren(TypedDict):
68
- edges: Sequence['Edge']
69
-
70
-
71
- class EdgeMediaToComment(TypedDict):
72
- count: int
73
-
74
-
75
- class Comments(TypedDict):
76
- can_view_more_preview_comments: bool
77
- comments: list[HasID]
78
- next_min_id: str
79
-
80
-
81
- class MediaInfo(TypedDict):
82
- more_available: bool
83
- num_results: int
84
- items: Sequence[MediaInfoItem]
85
-
86
-
87
- class GraphSidecarNode(TypedDict):
88
- __typename: Literal['GraphSidecar']
89
- comments_disabled: bool
90
- edge_media_to_comment: EdgeMediaToComment
91
- edge_sidecar_to_children: EdgeSidecarToChildren
92
- id: str
93
- shortcode: NotRequired[str]
94
-
95
-
96
- class GraphVideoNode(TypedDict):
97
- __typename: Literal['GraphVideo']
98
- id: str
99
- shortcode: NotRequired[str]
100
-
101
-
102
- class GraphImageNode(TypedDict):
103
- __typename: Literal['GraphImage']
104
- id: str
105
- shortcode: NotRequired[str]
106
-
107
-
108
- class Edge(TypedDict):
109
- node: GraphSidecarNode | GraphImageNode | GraphVideoNode
110
-
111
-
112
- class WebProfileInfoData(TypedDict):
113
- user: UserInfo
114
-
115
-
116
- class WebProfileInfo(TypedDict):
117
- data: WebProfileInfoData
@@ -1,21 +0,0 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2023 Andrew Udvare
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.