Fix MyHeritage with new design - #115
Conversation
Update from master
Merge from master
|
If it helps, here was my work in progress that I haven't had time to finish. |
|
@eljeffeg e.g. for https://www.myheritage.com/profile-420551751-1500056/dov-kushnir: Unfortunately, the GraphQL request is sent with a |
|
Ideally speaking - we need to tap on these responses and everything you need is there but I'm not sure how to fetch this data from JQuery/HTML |
|
I found this code: It seems that they generate the link on the |
|
I fixed various things - |
|
OK @eljeffeg , I think we're in a whole new realm here. As you can see The question now is... it seems that we can't just fetch this from the HTML itself (as the logic happens today) - and some React analysis is required. Here's what Google Gemini said:
|
|
Yeah, I see what you mean with https://familygraphql.myheritage.com. That's suppose to be MyHeritage's API - wonder if it's still an accessible option. For the react, a content script probably wouldn't work for this part of SmartCopy, but a background script might. We do have a background script that runs from the popup in |
|
What you have is a lot better than the failure now, so I wonder if we should just commit that and let everyone know we're still working out the dates. We might be able to at least put the years in there, since that appears to be in the data. |
|
@eljeffeg - the problem is not the dates rather than the urls. Without it, SmartCopy (atleast today's implementation) doesn't "recognize" the family members - which is, I think, a crucial part. I'd definitely leave the dates out, but in my opinion, the URLs are a must.... |
|
In a perfect world, I'd somehow reuse the bearer token and call the GraphQL myself (rather than parsing the HTML) and fetch all the data from there. However, couple of thoughts on this:
On the other hand, I have no clear idea about accessing React Component's state from within an Extension. |
|
Commenting without too much knowledge ... this is about translating the list of family members into queries that fetch the information about the family members? Is the URL you need the one for the family member's page? Wild thought - is it possible to just follow the relative links from within the page and intercept the queries so that you can figure out what the complete URL has become? (the interception could also return a 5xx code to avoid bumping the rate limiter)? Or is the result of following the relative link a different URL from the one you need? |
The problem here is how to get the links - the way this is implemented is through React Components, when the page is built - each family member in the list has a The trouble here is how to get these links... React BS... |
|
@eljeffeg as a temp solution. We can set the url as the current page url for all family members, so they'll be added but referenced to the source person and not the actual person. WDYT? |
|
If we can add "referenced in " to the text of the URL in family members, that would make it clear what's happening. |
|
any chance of getting this merged? I'm still hurting from the lack of MyHeritage SmartCopy. |
|
Still hoping to get it working with actual URLs. |
|
As we update the parsers for particular sites, we may want to consider implementing a model based on beautifulsoup. https://beautiful-soup-4.readthedocs.io/en/latest/ |
|
@eljeffeg any references in the project? Isn't beautiful soup is a python tool? |
|
Ha, you're right. I work with Python so much I forgot that this project is pretty much just JS. |
FamilySearch Json - Fix no spouse => null
|
OK. I give up. I'll set the |
|
Is this ready to merge, then? |
|
@alvestrand - this won't do, I'm afraid. |
|
|
I see that when loading - the page does a GraphQL Query: This is for Request to **https://familygraphql.myheritage.com/profile_header_data**RequestResponseResponseRequest to **https://familygraphql.myheritage.com/profile_details_data**RequestResponseResponseThis could be a potential to use it - but we need to extract the BearerToken from the page somehow |
|
Yeah, if you can use the background script, it's not too hard to call listener functions in that and wait for the response. |
I'd love to see an example |
|
Superseded by #179. This PR's approach (parsing the new page design in place) got the focus person's own data working, but left family-member linking as a known gap ( #179 solves it: spouse/children links come from the Facts section's real anchor tags (and, as a bonus, those facts already carry full birth date+place for children), while parents/siblings - who have no link anywhere in the rendered HTML at all - are recovered by walking React's internal fiber tree in a MAIN-world content script, since the link only exists as an unrendered Thank you for the initial exploration here - it was very helpful reference for what the new page's markup looks like. |
MyHeritage rolled out a redesigned profile page under a new URL shape (profile-<site>-<id>) that the existing collections/myheritage.js doesn't match, so visiting one fell through to "This website is not yet supported by SmartCopy." Adds a separate collection rather than modifying the existing one, so the working legacy path stays untouched while this is iterated on. Fixes eljeffeg#110, supersedes the abandoned eljeffeg#115. The new page is fully client-rendered (the server response is an empty shell), so this reads the live tab DOM after React has rendered it (same mechanism as every other parseProfileData collection), not a background fetch - a recursive fetch of any linked relative's own page also comes back empty for the same reason, which the family-linking code below accounts for. Family linking, solved in three layers, each covering what the others can't: - Spouse/children: the Facts section has real <a href> links, and "Birth of son/daughter:" facts already carry the child's own full birth date+place, used directly instead of needing a second fetch. - Parents/siblings: the "Immediate Family" cards have no href at all - the click handler reads a link_in_profile_page value straight out of a React component's props, which never reaches the DOM. New file annotateMyHeritageLinks.js is injected into the page's MAIN world (not the isolated world getPagesSource.js runs in, which can't see JS properties the page's own React attached) to walk React's fiber tree and stamp that link onto the card as a data attribute before the page is serialized. - Birth/death years for parents/spouse/siblings (full dates aren't rendered anywhere for them) come from the Immediate Family cards' coarse "1881 - 1968" / "Born: 1937" year-range text as a fallback. Also fixes a real gender-detection bug in the process: the gender_F/gender_M class lives on the photo wrapper itself, whether the person has a real photo or a silhouette placeholder - checking only the silhouette classes (as this file's first draft did) missed every profile with an actual photo. Bump version to 4.14.0.0, and update the credits box for this release (Randy Schoenberg's Geni Curator role, and Dan Bodenheimer's Geni Curator/Testing/Bug Triage credit). Verified against real profile pages (both the raw pre-render source and the live rendered DOM) with a jsdom harness reproducing the actual markup, and confirmed live in Chrome: focus person data, spouse, children, both parents, and a sibling all resolve correctly with real profile ids and vitals from a single page load. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* Add Firefox/MV3 compatibility (background page, offscreen fallback, gecko settings) Firefox's MV3 implementation doesn't support background.service_worker (it uses background.scripts instead) and has no chrome.offscreen API at all, so the extension was previously non-functional on Firefox despite declaring manifest_version 3. Fixes #178. - manifest.json: declare both background.scripts and background.service_worker so each browser picks up what it supports (modern Chrome ignores scripts, modern Firefox ignores service_worker); add browser_specific_settings.gecko with an extension id, minimum version, and the data_collection_permissions Mozilla now requires for submission. - background.js: evalObject() (used by Ancestry's legacy PersonCard eval fallback) now branches on chrome.offscreen - Firefox's MV3 background is a real event page with its own document, so it hosts the sandboxed eval iframe directly instead of going through the Chrome-only offscreen document indirection. - popup.js: guard the navigator.serviceWorker re-registration check, which doesn't exist in Firefox's popup context and was throwing uncaught, halting the rest of popup.js's top-level execution - including the `collections` array initialization, which cascaded into every single collection failing to register. Verified by loading as a temporary add-on in Firefox: the popup now loads and collections register correctly (previously every collection threw "collections is undefined"). Confirmed 0 errors from Mozilla's own web-ext lint, down from the warnings the unfixed manifest produced. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Add MyHeritage new-page-design collection with family linking MyHeritage rolled out a redesigned profile page under a new URL shape (profile-<site>-<id>) that the existing collections/myheritage.js doesn't match, so visiting one fell through to "This website is not yet supported by SmartCopy." Adds a separate collection rather than modifying the existing one, so the working legacy path stays untouched while this is iterated on. Fixes #110, supersedes the abandoned #115. The new page is fully client-rendered (the server response is an empty shell), so this reads the live tab DOM after React has rendered it (same mechanism as every other parseProfileData collection), not a background fetch - a recursive fetch of any linked relative's own page also comes back empty for the same reason, which the family-linking code below accounts for. Family linking, solved in three layers, each covering what the others can't: - Spouse/children: the Facts section has real <a href> links, and "Birth of son/daughter:" facts already carry the child's own full birth date+place, used directly instead of needing a second fetch. - Parents/siblings: the "Immediate Family" cards have no href at all - the click handler reads a link_in_profile_page value straight out of a React component's props, which never reaches the DOM. New file annotateMyHeritageLinks.js is injected into the page's MAIN world (not the isolated world getPagesSource.js runs in, which can't see JS properties the page's own React attached) to walk React's fiber tree and stamp that link onto the card as a data attribute before the page is serialized. - Birth/death years for parents/spouse/siblings (full dates aren't rendered anywhere for them) come from the Immediate Family cards' coarse "1881 - 1968" / "Born: 1937" year-range text as a fallback. Also fixes a real gender-detection bug in the process: the gender_F/gender_M class lives on the photo wrapper itself, whether the person has a real photo or a silhouette placeholder - checking only the silhouette classes (as this file's first draft did) missed every profile with an actual photo. Bump version to 4.14.0.0, and update the credits box for this release (Randy Schoenberg's Geni Curator role, and Dan Bodenheimer's Geni Curator/Testing/Bug Triage credit). Verified against real profile pages (both the raw pre-render source and the live rendered DOM) with a jsdom harness reproducing the actual markup, and confirmed live in Chrome: focus person data, spouse, children, both parents, and a sibling all resolve correctly with real profile ids and vitals from a single page load. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Document how to load a development/test build in Chrome Requested in #163 by someone testing without an npm/build toolchain available - a plain "Load unpacked" pointed at the repo folder is all that's needed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Capture marriage date/place from MyHeritage's "Marriage to:" fact The Facts loop already reads this fact's date+place to help build the spouse family link, but never saved it onto profiledata itself - every other event type (birth, death, burial, baptism) does. Fixes #85, which - checking the old collections/myheritage.js - was never actually implemented there either (just a `// marriage data - parse event tab` stub that was never filled in). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Lower Firefox strict_min_version to 140.0 (was 142.0) 142.0 was only required for Firefox-for-Android compatibility with browser_specific_settings.gecko.data_collection_permissions; desktop Firefox only needs 140.0 for that field. Since this extension has no Android-specific concerns, prefer the lower desktop floor and accept the one Android-only lint warning that comes with it - better than blocking everyone on desktop Firefox below 142 (confirmed this was a real, hard install-blocking gate: "Add-on ... is not compatible with application version" on Firefox 140). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Carry marriage date/place onto the spouse's own family record The "Marriage to:" fact's date/place was already being saved onto the focus person's own profiledata, but never onto the spouse's family- link entry - unlike children, whose own birth date/place (from "Birth of son/daughter:") was already wired through. Same fix, same pattern: attach the marriage data to the husband/wife entry directly, and carry it through the recursive-fetch fallback the same way birth/death already are. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Fix location fields submitting both flat and geocoded representations at once Every location (birth/death/marriage/etc, for the focus profile and every family member) is offered two alternative representations in the form: a flat "Place:" string, and a geocoded breakdown split into place/city/county/state/country. Only one is meant to be active at a time, toggled by the geo on/off switch (geoqueryCheck()) - but whether a field actually gets *submitted* is controlled separately by isEnabled(), which only checks if the value was auto-flagged as new/ different data ("scored"), never which representation is the active one. Since both representations share the same "scored" flag, both could end up enabled and submitted together even though only one was visible, and Geni's own combined location summary would then show the flat place name and the geocoded city/state/country stacked back to back - e.g. copying "Grunewald, Berlin, Germany" over an existing "Berlin, Germany" produced "Grunewald, Berlin, Germany, Berlin, Germany" on Geni. Fix: gate auto-enable on whichever representation is actually active (placeScored/geoScored, derived from the same geoqueryCheck() the visibility toggle already uses), so only one is ever auto-submitted. The separate #forcegeoswitch manual override for the geo breakdown is left untouched. This lives in buildform.js, shared by every collection, so it affected birth/death/marriage/etc for any site, not anything MyHeritage or Ancestry-specific. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Blank Geni's full location schema when submitting a flat place name The previous fix (from the now-merged location-duplication branch) only cleared city/county/state/country when submitting the flat "Place:" field. Turns out Geni's location schema has more fields than SmartCopy's UI exposes at all - address_line_1/2/3 and postal_code - and stale values in any of those keep showing up concatenated with the new place name for the same reason as before. Confirmed by reviewing Geni's actual edit form field list. Clearing all of them now, so the flat place name is unambiguously the only thing describing the location afterward. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Guard the Geni iframe header-stripping rule against Firefox On Firefox, chrome.runtime.id returns the browser_specific_settings. gecko.id from the manifest (an email-like string), not a Chrome-style extension id. declarativeNetRequest's initiatorDomains rejects that outright ("Invalid domain"), which was throwing uncaught on every extension load/reload in Firefox. Wrapped in try/catch plus a .catch() on the update call, so a browser that can't set this specific rule just skips it - this feature (stripping X-Frame-Options for this extension's own Geni iframes) degrades gracefully rather than blocking anything else from working. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Revert speculative address_line_1/2/3 and postal_code blanking Live testing showed Geni's update API returning a 500 with these fields included. Their names were guessed from labels shown in Geni's own UI, never confirmed against the actual API - unlike city/county/state/country, which are already used successfully by the existing geo-breakdown submission code elsewhere in this file. Rather than keep guessing field names against live Geni data, dropping the unverified four and keeping only the confirmed-safe ones. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Blank street_address1 using the correct field name from Geni's API docs Per Geni's actual API documentation: place_name, city, county, state, country, street_address1, latitude, longitude - a single address field (not address_line_1/2/3), and no postal_code field at all. Adds street_address1 to the fields cleared when submitting a flat place name, now that the real field name is confirmed rather than guessed. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Fix "Promised response...went out of scope" errors on Firefox Two onMessage listeners (background.js's "icon" action, popup.js's "getSource" action) returned true - signaling an async sendResponse call was coming - without ever actually calling it, since neither caller passes a callback in the first place (both are fire-and-forget chrome.runtime.sendMessage calls). Chrome tolerates this mismatch silently; Firefox's stricter message-port lifecycle tracking flags it as an uncaught error once the listener's context is torn down. Fixed both to return false, matching what actually happens (no response is ever sent, because none was ever expected). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Dan Bodenheimer <dan@authentify.art> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>



Still work in progress.... DO NOT MERGE YET
Solves #110