Fix anon username from id (find renamed profile)
maybe related to #95, #104, 67ac8f3397
.
This commit is contained in:
parent
1469064176
commit
2722da6ae4
@ -74,7 +74,10 @@ metadata of a Profile. :class:`Profile` instances can be created with:
|
|||||||
profile = Profile.from_username(L.context, USERNAME)
|
profile = Profile.from_username(L.context, USERNAME)
|
||||||
|
|
||||||
- :meth:`Profile_from_userid`
|
- :meth:`Profile_from_userid`
|
||||||
given its User ID (currently requires to be logged in).
|
given its User ID. This allows to easily lookup a Profile's username given
|
||||||
|
its ID::
|
||||||
|
|
||||||
|
Profile.from_id(L.context, USERID).username
|
||||||
|
|
||||||
- :meth:`Profile.get_followees`
|
- :meth:`Profile.get_followees`
|
||||||
Profiles that are followed by given user.
|
Profiles that are followed by given user.
|
||||||
|
@ -629,10 +629,6 @@ class Instaloader:
|
|||||||
else:
|
else:
|
||||||
self.context.log("Trying to find profile {0} using its unique ID {1}.".format(profile_name,
|
self.context.log("Trying to find profile {0} using its unique ID {1}.".format(profile_name,
|
||||||
profile_id))
|
profile_id))
|
||||||
if not self.context.is_logged_in:
|
|
||||||
self.context.error("Profile {} changed its name. "
|
|
||||||
"If you use --login=USERNAME, I can find out the new name.")
|
|
||||||
raise LoginRequiredException("--login=USERNAME required to obtain profile name from its ID number")
|
|
||||||
profile_from_id = Profile.from_id(self.context, profile_id)
|
profile_from_id = Profile.from_id(self.context, profile_id)
|
||||||
newname = profile_from_id.username
|
newname = profile_from_id.username
|
||||||
self.context.log("Profile {0} has changed its name to {1}.".format(profile_name, newname))
|
self.context.log("Profile {0} has changed its name to {1}.".format(profile_name, newname))
|
||||||
|
@ -56,6 +56,7 @@ class InstaloaderContext:
|
|||||||
self.quiet = quiet
|
self.quiet = quiet
|
||||||
self.max_connection_attempts = max_connection_attempts
|
self.max_connection_attempts = max_connection_attempts
|
||||||
self._graphql_page_length = 50
|
self._graphql_page_length = 50
|
||||||
|
self._root_rhx_gis = None
|
||||||
|
|
||||||
# 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 = []
|
self.error_log = []
|
||||||
@ -376,3 +377,14 @@ class InstaloaderContext:
|
|||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
self.error("[skipped by user]", repeat_at_end=False)
|
self.error("[skipped by user]", repeat_at_end=False)
|
||||||
raise ConnectionException(error_string) from err
|
raise ConnectionException(error_string) from err
|
||||||
|
|
||||||
|
@property
|
||||||
|
def root_rhx_gis(self) -> Optional[str]:
|
||||||
|
"""rhx_gis string returned in the / query."""
|
||||||
|
if self.is_logged_in:
|
||||||
|
# At the moment, rhx_gis seems to be required for anonymous requests only. By returning None when logged
|
||||||
|
# in, we can save the root_rhx_gis lookup query.
|
||||||
|
return None
|
||||||
|
if not self._root_rhx_gis:
|
||||||
|
self._root_rhx_gis = self.get_json('', {})['rhx_gis']
|
||||||
|
return self._root_rhx_gis
|
||||||
|
@ -145,8 +145,8 @@ class Post:
|
|||||||
else:
|
else:
|
||||||
# Sometimes, the 'owner' structure does not contain the username, only the user's ID. In that case,
|
# Sometimes, the 'owner' structure does not contain the username, only the user's ID. In that case,
|
||||||
# this call triggers downloading of the complete Post metadata struct, where the owner username
|
# this call triggers downloading of the complete Post metadata struct, where the owner username
|
||||||
# is contained. This is better than to get the username by user ID, since it is possible anonymously
|
# is contained. This is better than to get the username by user ID, since it
|
||||||
# and gives us other information that is more likely to be usable.
|
# gives us other information that is more likely to be usable.
|
||||||
owner_struct = self._full_metadata['owner']
|
owner_struct = self._full_metadata['owner']
|
||||||
if 'username' in owner_struct:
|
if 'username' in owner_struct:
|
||||||
self._owner_profile = Profile(self._context, owner_struct)
|
self._owner_profile = Profile(self._context, owner_struct)
|
||||||
@ -379,17 +379,16 @@ class Profile:
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_id(cls, context: InstaloaderContext, profile_id: int):
|
def from_id(cls, context: InstaloaderContext, profile_id: int):
|
||||||
"""If logged in, create a Profile instance from a given userid. If possible, use :meth:`Profile.from_username`
|
"""Create a Profile instance from a given userid. If possible, use :meth:`Profile.from_username`
|
||||||
or constructor directly rather than this method, since does many requests.
|
or constructor directly rather than this method, since it does many requests.
|
||||||
|
|
||||||
:param context: :attr:`Instaloader.context`
|
:param context: :attr:`Instaloader.context`
|
||||||
:param profile_id: userid
|
:param profile_id: userid
|
||||||
:raises: :class:`ProfileNotExistsException`, :class:`LoginRequiredException`, :class:`ProfileHasNoPicsException`
|
:raises: :class:`ProfileNotExistsException`, :class:`ProfileHasNoPicsException`
|
||||||
"""
|
"""
|
||||||
if not context.is_logged_in:
|
|
||||||
raise LoginRequiredException("--login=USERNAME required to obtain profile metadata from its ID number.")
|
|
||||||
data = context.graphql_query("472f257a40c653c64c666ce877d59d2b",
|
data = context.graphql_query("472f257a40c653c64c666ce877d59d2b",
|
||||||
{'id': str(profile_id), 'first': 1})['data']['user']
|
{'id': str(profile_id), 'first': 1},
|
||||||
|
rhx_gis=context.root_rhx_gis)['data']['user']
|
||||||
if data:
|
if data:
|
||||||
data = data["edge_owner_to_timeline_media"]
|
data = data["edge_owner_to_timeline_media"]
|
||||||
else:
|
else:
|
||||||
@ -400,7 +399,7 @@ class Profile:
|
|||||||
raise ProfileHasNoPicsException("Profile with ID {0}: no pics found.".format(str(profile_id)))
|
raise ProfileHasNoPicsException("Profile with ID {0}: no pics found.".format(str(profile_id)))
|
||||||
else:
|
else:
|
||||||
raise LoginRequiredException("Login required to determine username (ID: " + str(profile_id) + ").")
|
raise LoginRequiredException("Login required to determine username (ID: " + str(profile_id) + ").")
|
||||||
username = Post.from_mediaid(context, int(data['edges'][0]["node"]["id"])).owner_username
|
username = Post.from_shortcode(context, data['edges'][0]["node"]["shortcode"]).owner_username
|
||||||
return cls(context, {'username': username.lower(), 'id': profile_id})
|
return cls(context, {'username': username.lower(), 'id': profile_id})
|
||||||
|
|
||||||
def _asdict(self):
|
def _asdict(self):
|
||||||
|
@ -54,6 +54,10 @@ class TestInstaloaderAnonymously(unittest.TestCase):
|
|||||||
self.assertEqual(PUBLIC_PROFILE_ID,
|
self.assertEqual(PUBLIC_PROFILE_ID,
|
||||||
instaloader.Profile.from_username(self.L.context, PUBLIC_PROFILE).userid)
|
instaloader.Profile.from_username(self.L.context, PUBLIC_PROFILE).userid)
|
||||||
|
|
||||||
|
def test_get_username_by_id(self):
|
||||||
|
self.assertEqual(PUBLIC_PROFILE.lower(),
|
||||||
|
instaloader.Profile.from_id(self.L.context, PUBLIC_PROFILE_ID).username)
|
||||||
|
|
||||||
def test_post_from_mediaid(self):
|
def test_post_from_mediaid(self):
|
||||||
for post in instaloader.Profile.from_username(self.L.context, PUBLIC_PROFILE).get_posts():
|
for post in instaloader.Profile.from_username(self.L.context, PUBLIC_PROFILE).get_posts():
|
||||||
post2 = instaloader.Post.from_mediaid(self.L.context, post.mediaid)
|
post2 = instaloader.Post.from_mediaid(self.L.context, post.mediaid)
|
||||||
|
Loading…
Reference in New Issue
Block a user