1
0
mirror of https://github.com/instaloader/instaloader.git synced 2024-11-20 17:22:31 +01:00

Make iPhone endpoint query optional (#1076)

This commit is contained in:
A Bored Pervert 2021-04-22 14:06:35 -04:00 committed by GitHub
parent e67b9e6c37
commit 3837b642b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 35 additions and 12 deletions

View File

@ -100,7 +100,6 @@ What to Download of each Post
Do not xz compress JSON files, rather create pretty formatted JSONs. Do not xz compress JSON files, rather create pretty formatted JSONs.
What to Download of each Profile What to Download of each Profile
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -274,6 +273,12 @@ How to Download
.. versionadded:: 4.7 .. versionadded:: 4.7
.. option:: --no-iphone
Do not attempt to download iPhone version of images and videos.
.. versionadded:: 4.8
Miscellaneous Options Miscellaneous Options
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^

View File

@ -206,7 +206,8 @@ def _main(instaloader: Instaloader, targetlist: List[str],
if len(profiles) > 1: if len(profiles) > 1:
instaloader.context.log("Downloading {} profiles: {}".format(len(profiles), instaloader.context.log("Downloading {} profiles: {}".format(len(profiles),
' '.join([p.username for p in profiles]))) ' '.join([p.username for p in profiles])))
if profiles and (download_profile_pic or download_posts) and not instaloader.context.is_logged_in: if instaloader.context.iphone_support and profiles and (download_profile_pic or download_posts) and \
not instaloader.context.is_logged_in:
instaloader.context.log("Hint: Use --login to download higher-quality versions of pictures.") instaloader.context.log("Hint: Use --login to download higher-quality versions of pictures.")
instaloader.download_profiles(profiles, instaloader.download_profiles(profiles,
download_profile_pic, download_posts, download_tagged, download_igtv, download_profile_pic, download_posts, download_tagged, download_igtv,
@ -382,6 +383,8 @@ def main():
g_how.add_argument('--abort-on', type=http_status_code_list, metavar="STATUS_CODES", g_how.add_argument('--abort-on', type=http_status_code_list, metavar="STATUS_CODES",
help='Comma-separated list of HTTP status codes that cause Instaloader to abort, bypassing all ' help='Comma-separated list of HTTP status codes that cause Instaloader to abort, bypassing all '
'retry logic.') 'retry logic.')
g_how.add_argument('--no-iphone', action='store_true',
help='Do not attempt to download iPhone version of images and videos.')
g_misc = parser.add_argument_group('Miscellaneous Options') g_misc = parser.add_argument_group('Miscellaneous Options')
g_misc.add_argument('-q', '--quiet', action='store_true', g_misc.add_argument('-q', '--quiet', action='store_true',
@ -441,7 +444,8 @@ def main():
resume_prefix=resume_prefix, resume_prefix=resume_prefix,
check_resume_bbd=not args.use_aged_resume_files, check_resume_bbd=not args.use_aged_resume_files,
slide=args.slide, slide=args.slide,
fatal_status_codes=args.abort_on) fatal_status_codes=args.abort_on,
iphone_support=not args.no_iphone)
_main(loader, _main(loader,
args.profile, args.profile,
username=args.login.lower() if args.login is not None else None, username=args.login.lower() if args.login is not None else None,

View File

@ -65,6 +65,8 @@ class QueryReturnedNotFoundException(ConnectionException):
class TooManyRequestsException(ConnectionException): class TooManyRequestsException(ConnectionException):
pass pass
class IPhoneSupportDisabledException(InstaloaderException):
pass
class AbortDownloadException(Exception): class AbortDownloadException(Exception):
""" """

View File

@ -162,6 +162,7 @@ class Instaloader:
:param check_resume_bbd: Whether to check the date of expiry of resume files and reject them if expired. :param check_resume_bbd: Whether to check the date of expiry of resume files and reject them if expired.
:param slide: :option:`--slide` :param slide: :option:`--slide`
:param fatal_status_codes: :option:`--abort-on` :param fatal_status_codes: :option:`--abort-on`
:param iphone_support: not :option:`--no-iphone`
.. attribute:: context .. attribute:: context
@ -189,10 +190,12 @@ class Instaloader:
resume_prefix: Optional[str] = "iterator", resume_prefix: Optional[str] = "iterator",
check_resume_bbd: bool = True, check_resume_bbd: bool = True,
slide: Optional[str] = None, slide: Optional[str] = None,
fatal_status_codes: Optional[List[int]] = None): fatal_status_codes: Optional[List[int]] = None,
iphone_support: bool = True):
self.context = InstaloaderContext(sleep, quiet, user_agent, max_connection_attempts, self.context = InstaloaderContext(sleep, quiet, user_agent, max_connection_attempts,
request_timeout, rate_controller, fatal_status_codes) request_timeout, rate_controller, fatal_status_codes,
iphone_support)
# configuration parameters # configuration parameters
self.dirname_pattern = dirname_pattern or "{target}" self.dirname_pattern = dirname_pattern or "{target}"
@ -259,7 +262,8 @@ class Instaloader:
resume_prefix=self.resume_prefix, resume_prefix=self.resume_prefix,
check_resume_bbd=self.check_resume_bbd, check_resume_bbd=self.check_resume_bbd,
slide=self.slide, slide=self.slide,
fatal_status_codes=self.context.fatal_status_codes) fatal_status_codes=self.context.fatal_status_codes,
iphone_support=self.context.iphone_support)
yield new_loader yield new_loader
self.context.error_log.extend(new_loader.context.error_log) self.context.error_log.extend(new_loader.context.error_log)
new_loader.context.error_log = [] # avoid double-printing of errors new_loader.context.error_log = [] # avoid double-printing of errors

View File

@ -54,7 +54,8 @@ class InstaloaderContext:
def __init__(self, sleep: bool = True, quiet: bool = False, user_agent: Optional[str] = None, def __init__(self, sleep: bool = True, quiet: bool = False, user_agent: Optional[str] = None,
max_connection_attempts: int = 3, request_timeout: float = 300.0, max_connection_attempts: int = 3, request_timeout: float = 300.0,
rate_controller: Optional[Callable[["InstaloaderContext"], "RateController"]] = None, rate_controller: Optional[Callable[["InstaloaderContext"], "RateController"]] = None,
fatal_status_codes: Optional[List[int]] = None): fatal_status_codes: Optional[List[int]] = None,
iphone_support: bool = True):
self.user_agent = user_agent if user_agent is not None else default_user_agent() self.user_agent = user_agent if user_agent is not None else default_user_agent()
self.request_timeout = request_timeout self.request_timeout = request_timeout
@ -66,6 +67,7 @@ class InstaloaderContext:
self._graphql_page_length = 50 self._graphql_page_length = 50
self._root_rhx_gis = None self._root_rhx_gis = None
self.two_factor_auth_pending = None self.two_factor_auth_pending = None
self.iphone_support = iphone_support
# error log, filled with error() and printed at the end of Instaloader.main() # error log, filled with error() and printed at the end of Instaloader.main()
self.error_log = [] # type: List[str] self.error_log = [] # type: List[str]

View File

@ -168,6 +168,8 @@ class Post:
@property @property
def _iphone_struct(self) -> Dict[str, Any]: def _iphone_struct(self) -> Dict[str, Any]:
if not self._context.iphone_support:
raise IPhoneSupportDisabledException("iPhone support is disabled.")
if not self._context.is_logged_in: if not self._context.is_logged_in:
raise LoginRequiredException("--login required to access iPhone media info endpoint.") raise LoginRequiredException("--login required to access iPhone media info endpoint.")
if not self._iphone_struct_: if not self._iphone_struct_:
@ -246,7 +248,7 @@ class Post:
@property @property
def url(self) -> str: def url(self) -> str:
"""URL of the picture / video thumbnail of the post""" """URL of the picture / video thumbnail of the post"""
if self.typename == "GraphImage" and self._context.is_logged_in: if self.typename == "GraphImage" and self._context.iphone_support and self._context.is_logged_in:
try: try:
orig_url = self._iphone_struct['image_versions2']['candidates'][0]['url'] orig_url = self._iphone_struct['image_versions2']['candidates'][0]['url']
url = re.sub(r'([?&])se=\d+&?', r'\1', orig_url).rstrip('&') url = re.sub(r'([?&])se=\d+&?', r'\1', orig_url).rstrip('&')
@ -304,7 +306,7 @@ class Post:
node = edge['node'] node = edge['node']
is_video = node['is_video'] is_video = node['is_video']
display_url = node['display_url'] display_url = node['display_url']
if not is_video and self._context.is_logged_in: if not is_video and self._context.iphone_support and self._context.is_logged_in:
try: try:
carousel_media = self._iphone_struct['carousel_media'] carousel_media = self._iphone_struct['carousel_media']
orig_url = carousel_media[idx]['image_versions2']['candidates'][0]['url'] orig_url = carousel_media[idx]['image_versions2']['candidates'][0]['url']
@ -372,7 +374,7 @@ class Post:
def video_url(self) -> Optional[str]: def video_url(self) -> Optional[str]:
"""URL of the video, or None.""" """URL of the video, or None."""
if self.is_video: if self.is_video:
if self._context.is_logged_in: if self._context.iphone_support and self._context.is_logged_in:
try: try:
url = self._iphone_struct['video_versions'][0]['url'] url = self._iphone_struct['video_versions'][0]['url']
return url return url
@ -691,6 +693,8 @@ class Profile:
@property @property
def _iphone_struct(self) -> Dict[str, Any]: def _iphone_struct(self) -> Dict[str, Any]:
if not self._context.iphone_support:
raise IPhoneSupportDisabledException("iPhone support is disabled.")
if not self._context.is_logged_in: if not self._context.is_logged_in:
raise LoginRequiredException("--login required to access iPhone profile info endpoint.") raise LoginRequiredException("--login required to access iPhone profile info endpoint.")
if not self._iphone_struct_: if not self._iphone_struct_:
@ -834,7 +838,7 @@ class Profile:
.. versionchanged:: 4.2.1 .. versionchanged:: 4.2.1
Require being logged in for HD version (as required by Instagram).""" Require being logged in for HD version (as required by Instagram)."""
if self._context.is_logged_in: if self._context.iphone_support and self._context.is_logged_in:
try: try:
return self._iphone_struct['hd_profile_pic_url_info']['url'] return self._iphone_struct['hd_profile_pic_url_info']['url']
except (InstaloaderException, KeyError) as err: except (InstaloaderException, KeyError) as err:
@ -1021,6 +1025,8 @@ class StoryItem:
@property @property
def _iphone_struct(self) -> Dict[str, Any]: def _iphone_struct(self) -> Dict[str, Any]:
if not self._context.iphone_support:
raise IPhoneSupportDisabledException("iPhone support is disabled.")
if not self._context.is_logged_in: if not self._context.is_logged_in:
raise LoginRequiredException("--login required to access iPhone media info endpoint.") raise LoginRequiredException("--login required to access iPhone media info endpoint.")
if not self._iphone_struct_: if not self._iphone_struct_:
@ -1079,7 +1085,7 @@ class StoryItem:
@property @property
def url(self) -> str: def url(self) -> str:
"""URL of the picture / video thumbnail of the StoryItem""" """URL of the picture / video thumbnail of the StoryItem"""
if self.typename == "GraphStoryImage" and self._context.is_logged_in: if self.typename == "GraphStoryImage" and self._context.iphone_support and self._context.is_logged_in:
try: try:
orig_url = self._iphone_struct['image_versions2']['candidates'][0]['url'] orig_url = self._iphone_struct['image_versions2']['candidates'][0]['url']
url = re.sub(r'([?&])se=\d+&?', r'\1', orig_url).rstrip('&') url = re.sub(r'([?&])se=\d+&?', r'\1', orig_url).rstrip('&')