Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Some Profile Pictures are not shown when an account with multiple profile photos are specified. #482

Open
shion1305 opened this issue Jan 12, 2024 · 6 comments
Labels
bug Something isn't working

Comments

@shion1305
Copy link

Describe the bug

Looks like the result lacks some of the profile photos when the account with multiple profile photos are specified.

To Reproduce

Try ghunt email shion1305@gmail.com
You will get followings.

[+] Custom profile picture !
=> https://lh3.googleusercontent.com/cm/AOgkWRadPfpfwkMtuZiCMmCUbeUgB-fKemZhlgQb4O-vCiMyf0UZ85t5Jvy65fT2Xy8
🎭 No face detected.

[-] Default cover picture

However, my main profile photo are this...
https://lh3.googleusercontent.com/a-/ALV-UjVAZwNswrR856p1RmOX9FTFMgS7l9Hrj6qguQwFry_szec

Investigation

I referred to the corresponding source code for getting the profile photo.

async def people_lookup(self, as_client: httpx.AsyncClient, email: str, params_template="just_gaia_id") -> Tuple[bool, Person]:
endpoint_name = inspect.currentframe().f_code.co_name
verb = "GET"
base_url = "/v2/people/lookup"
data_type = None # json, data or None
params_templates = {
"just_gaia_id": {
"id": email,
"type": "EMAIL",
"matchType": "EXACT",
"requestMask.includeField.paths": "person.metadata"
},
"just_name": {
"id": email,
"type": "EMAIL",
"matchType": "EXACT",
"requestMask.includeField.paths": "person.name",
"core_id_params.enable_private_names": True
},
"max_details": {
"id": email,
"type": "EMAIL",
"match_type": "EXACT",
"extension_set.extension_names": [
"DYNAMITE_ADDITIONAL_DATA",
"DYNAMITE_ORGANIZATION_INFO",
# "GPLUS_ADDITIONAL_DATA"
],
"request_mask.include_field.paths": [
"person.metadata.best_display_name",
"person.photo",
"person.cover_photo",
"person.interaction_settings",
"person.legacy_fields",
"person.metadata",
"person.in_app_reachability",
"person.name",
"person.read_only_profile_info",
"person.sort_keys",
"person.email"
],
"request_mask.include_container": [
"AFFINITY",
"PROFILE",
"DOMAIN_PROFILE",
"ACCOUNT",
"EXTERNAL_ACCOUNT",
"CIRCLE",
"DOMAIN_CONTACT",
"DEVICE_CONTACT",
"GOOGLE_GROUP",
"CONTACT"
],
"core_id_params.enable_private_names": True
}
}
if not params_templates.get(params_template):
raise GHuntParamsTemplateError(f"The asked template {params_template} for the endpoint {endpoint_name} wasn't recognized by GHunt.")
self._load_endpoint(endpoint_name)
req = await self._query(as_client, verb, endpoint_name, base_url, params_templates[params_template], None, data_type)
# Parsing
data = json.loads(req.text)
person = Person()
if not data:
return False, person
person_data = list(data["people"].values())[0]
await person._scrape(as_client, person_data)
return True, person

printed out the data and got this.

{'matches': [{'lookupId': 'shion1305@gmail.com', 'personId': ['107694920401573579556']}], 'people': {'107694920401573579556': {'personId': '107694920401573579556', 'metadata': {'ownerId': '107694920401573579556', 'objectType': 'PERSON', 'contactId': ['5109819430929386011'], 'inViewerDomain': False, 'ownerUserType': ['GOOGLE_USER'], 'lastUpdateTimeMicros': '1704909803193', 'identityInfo': {'originalLookupToken': ['shion1305@gmail.com'], 'sourceIds': [{'container': 'PROFILE', 'id': '107694920401573579556', 'lastUpdatedMicros': '1704909803193055', 'sourceEtag': '#55oD9Qu79Ow=', 'containerType': 'PROFILE', 'lastUpdated': '2024-01-10T18:03:23.193055Z'}, {'container': 'CONTACT', 'id': '46e9b9b30eef4a1b', 'lastUpdatedMicros': '1504564690767001', 'sourceEtag': '#EW59UGzhbok=', 'containerType': 'CONTACT', 'lastUpdated': '2017-09-04T22:38:10.767001Z'}]}, 'bestDisplayName': {'displayName': '市川 詩恩', 'displayNameLastFirst': '市川詩恩', 'containerType': 'CONTACT'}, 'model': 'PROFILE_CENTRIC'}, 'name': [{'metadata': {'writeable': True, 'container': 'CONTACT', 'primary': True, 'containerId': '5109819430929386011', 'encodedContainerId': '46e9b9b30eef4a1b', 'containerType': 'CONTACT'}, 'displayName': '市川 詩恩', 'givenName': '詩恩', 'familyName': '市川', 'displayNameLastFirst': '市川詩恩', 'unstructuredName': '市川 詩恩'}, {'metadata': {'container': 'PROFILE', 'encodedContainerId': '107694920401573579556', 'containerPrimary': True, 'containerType': 'PROFILE'}, 'displayName': 'Shion Ichikawa', 'givenName': 'Shion', 'familyName': 'Ichikawa', 'displayNameLastFirst': 'Ichikawa, Shion', 'unstructuredName': 'Shion Ichikawa'}], 'photo': [{'metadata': {'container': 'PROFILE', 'primary': True, 'visibility': 'PUBLIC', 'encodedContainerId': '107694920401573579556', 'containerType': 'PROFILE'}, 'url': 'https://lh3.googleusercontent.com/a-/ALV-UjVAZwNswrR856p1RmOX9FTFMgS7l9Hrj6qguQwFry_szec', 'photoToken': 'EhUxMDc2OTQ5MjA0MDE1NzM1Nzk1NTYoATCd4v2__f____8B'}, {'metadata': {'writeable': True, 'container': 'CONTACT', 'containerId': '5109819430929386011', 'encodedContainerId': '46e9b9b30eef4a1b', 'containerType': 'CONTACT'}, 'url': 'https://lh3.googleusercontent.com/cm/AOgkWRadPfpfwkMtuZiCMmCUbeUgB-fKemZhlgQb4O-vCiMyf0UZ85t5Jvy65fT2Xy8', 'isDefault': True, 'photoToken': 'EhA0NmU5YjliMzBlZWY0YTFiKAIw48uZ1QQ=', 'isMonogram': True, 'monogramBackground': 'C2185B'}], 'email': [{'metadata': {'writeable': True, 'container': 'CONTACT', 'primary': True, 'edgeKey': True, 'containerId': '5109819430929386011', 'encodedContainerId': '46e9b9b30eef4a1b', 'containerPrimary': True, 'edgeKeyInfo': [{'containerId': '107694920401573579556', 'containerType': 'PROFILE', 'materialized': True}], 'containerType': 'CONTACT'}, 'value': 'shion1305@gmail.com'}, {'metadata': {'container': 'PROFILE', 'encodedContainerId': '107694920401573579556', 'containerType': 'PROFILE'}, 'value': 'shion1305@gmail.com', 'extendedData': {'isPlaceholder': True}}], 'sortKeys': {'name': '3zeSqEeQvEkyYEer8--', 'lastName': '3zeSqEeQvEkyYEer8--', 'nameRaw': '0市川詩恩', 'lastNameRaw': '0市川詩恩'}, 'fingerprint': '%EhEBAgMJGRseICssLjY3ODk7ZBoJAQIDBQYHCAkLIgxFVzU5VUd6aGJvaz0=', 'coverPhoto': [{'imageUrl': 'https://lh3.googleusercontent.com/c5dqxl-2uHZ82ah9p7yxrVF1ZssrJNSV_15Nu0TUZwzCWqmtoLxCUJgEzLGtxsrJ6-v6R6rKU_-FYm881TTiMCJ_=s1600', 'isDefault': True, 'metadata': {'container': 'PROFILE', 'primary': True, 'visibility': 'PUBLIC', 'encodedContainerId': '107694920401573579556', 'containerType': 'PROFILE'}}], 'inAppReachability': [{'metadata': {'container': 'PROFILE', 'visibility': 'PUBLIC', 'encodedContainerId': '107694920401573579556', 'containerType': 'PROFILE'}, 'appType': 'YOUTUBE', 'status': 'REACHABLE', 'reachabilityKey': {'keyType': 'OBFUSCATED_GAIA_ID', 'keyValue': '107694920401573579556'}}, {'metadata': {'container': 'PROFILE', 'visibility': 'PUBLIC', 'encodedContainerId': '107694920401573579556', 'containerType': 'PROFILE'}, 'appType': 'PHOTOS', 'status': 'REACHABLE', 'reachabilityKey': {'keyType': 'OBFUSCATED_GAIA_ID', 'keyValue': '107694920401573579556'}}, {'metadata': {'container': 'PROFILE', 'visibility': 'PUBLIC', 'encodedContainerId': '107694920401573579556', 'containerType': 'PROFILE'}, 'appType': 'MAPS', 'status': 'REACHABLE', 'reachabilityKey': {'keyType': 'OBFUSCATED_GAIA_ID', 'keyValue': '107694920401573579556'}}], 'extendedData': {'dynamiteExtendedData': {'presence': 'UNKNOWN', 'entityType': 'PERSON', 'dndState': 'AVAILABLE', 'organizationInfo': {'consumerInfo': {}}}}, 'readOnlyProfileInfo': [{'metadata': {'container': 'PROFILE', 'encodedContainerId': '107694920401573579556', 'containerType': 'PROFILE'}, 'ownerId': '107694920401573579556', 'ownerUserType': ['GOOGLE_USER'], 'inViewerDomain': False}]}}}

I see the profile photo link I was expecting on ['people']['107694920401573579556']['photo'][0].
So looks like this is just a parsing problem.

@mxrch
Copy link
Owner

mxrch commented Jan 12, 2024

Good catch, thanks ! I'll deploy a fix soon.

@mxrch mxrch added the bug Something isn't working label Jan 12, 2024
@AlexMurd
Copy link

7d117a3

96e78c0

maybe it fix the glitch

@mxrch
Copy link
Owner

mxrch commented Jan 16, 2024

Hey, I cannot reproduce this bug.
I see you have two containers in your response : the PROFILE and CONTACT, and for an unknown reason, for you, it takes the CONTACT container to show the picture, despite that I hardcoded the PROFILE container there :

container = "PROFILE"
gb.rc.print("\n🙋 Google Account data\n", style="plum2")
if container in target.names:
print(f"Name : {target.names[container].fullname}\n")
if container in target.profilePhotos:
if target.profilePhotos[container].isDefault:
print("[-] Default profile picture")
else:
print("[+] Custom profile picture !")

@shion1305
Copy link
Author

Did you type my email? ( shion1305@gmail.com )
I've upgraded to ghunt to the latest version, but still getting the same result.
image

@shion1305
Copy link
Author

I'll work on this issue.

@shion1305
Copy link
Author

@mxrch
I've noticed an issue where the first image's data is being overwritten by the second image's data when loading two photos. This occurs due to profile_data["metadata"]["container"] having the same value (PROFILE) for both images, as seen in the code at ghunt/parsers/people.py#L148-L151.

for photo_data in person_data["photo"]:
person_photo = PersonPhoto()
await person_photo._scrape(as_client, photo_data, "profile_photo")
self.profilePhotos[profile_data["metadata"]["container"]] = person_photo

I propose two potential solutions:

  1. Change Person.profilePhotos to Dict[str, list[PersonPhoto]]: Given that both profile photos use the PROFILE key, we could store both images by converting the value to a list. This approach is less disruptive to the existing code structure.

  2. Change Person.profilePhotos to list[PersonPhoto]: Since all profile images use the PROFILE key, converting this field to a list simplifies the structure. While this method is more straightforward, it is also more invasive and may reduce flexibility in accommodating future changes from Google.

I lean towards the second option for its simplicity and clarity, but it does come with the risk of reduced adaptability. I need the maintainer's opinion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants