-
Notifications
You must be signed in to change notification settings - Fork 206
fix: linkedin sync broken due to apify schema changes #889
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -324,19 +324,18 @@ const LinkedInLocation = z.object({ | |
| }); | ||
|
|
||
| const LinkedInProfile = z.object({ | ||
| element: z.object({ | ||
| education: z.array(LinkedInEducation), | ||
| experience: z.array(LinkedInExperience), | ||
| headline: z.string().nullish(), | ||
| location: LinkedInLocation, | ||
| openToWork: z.boolean().nullish(), | ||
| photo: z.string().url().nullish(), | ||
| }), | ||
| education: z.array(LinkedInEducation), | ||
| error: z.undefined(), | ||
| experience: z.array(LinkedInExperience), | ||
| headline: z.string().nullish(), | ||
| location: LinkedInLocation, | ||
| openToWork: z.boolean().nullish(), | ||
| photo: z.string().url().nullish(), | ||
| originalQuery: z.object({ url: z.string() }), | ||
| }); | ||
|
|
||
| const LinkedInFailure = z.object({ | ||
| element: z.null(), | ||
| error: z.array(z.any()), | ||
| originalQuery: z.object({ url: z.string() }), | ||
| }); | ||
|
|
||
|
|
@@ -345,11 +344,11 @@ const LinkedInResult = z.union([LinkedInProfile, LinkedInFailure]); | |
| // Types | ||
|
|
||
| type LinkedInEducation = NonNullable< | ||
| z.infer<typeof LinkedInProfile>['element']['education'][number] | ||
| z.infer<typeof LinkedInProfile>['education'][number] | ||
| >; | ||
|
|
||
| type LinkedInExperience = NonNullable< | ||
| z.infer<typeof LinkedInProfile>['element']['experience'][number] | ||
| z.infer<typeof LinkedInProfile>['experience'][number] | ||
| >; | ||
|
|
||
| type LinkedInProfile = z.infer<typeof LinkedInProfile>; | ||
|
|
@@ -430,7 +429,7 @@ export async function syncLinkedInProfiles( | |
|
|
||
| // This is the case where there are multiple members with the same | ||
| // LinkedIn URL, something that should be fixed. | ||
| if (!profile.element || !member) { | ||
| if (profile.error || !member) { | ||
| await finishSync(memberId); | ||
|
|
||
| console.log(`Profile not found for ${memberId}, moving on.`); | ||
|
|
@@ -746,7 +745,7 @@ async function scrapeProfiles(profilesToScrape: string[]) { | |
| await db.transaction().execute(async (trx) => { | ||
| await Promise.all( | ||
| newResults.map(async (result) => { | ||
| if (result.element) { | ||
| if (!result.error) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cache key unchanged despite schema change causing parse failuresHigh Severity The cache key version remains Additional Locations (1) |
||
| return successfulResults.push(result); | ||
| } | ||
|
|
||
|
|
@@ -803,7 +802,7 @@ async function processProfile({ | |
| } | ||
| }); | ||
|
|
||
| const checkEducationPromises = profile.element.education.map( | ||
| const checkEducationPromises = profile.education.map( | ||
| async (education) => { | ||
| if (!education) { | ||
| return; | ||
|
|
@@ -826,7 +825,7 @@ async function processProfile({ | |
| } | ||
| ); | ||
|
|
||
| const checkExperiencesPromises = profile.element.experience.map( | ||
| const checkExperiencesPromises = profile.experience.map( | ||
| async (experience) => { | ||
| if (!experience) { | ||
| return; | ||
|
|
@@ -896,7 +895,7 @@ type CheckMemberInput = { | |
|
|
||
| async function checkMember({ member, profile, trx }: CheckMemberInput) { | ||
| const updatedLocation = await run(async () => { | ||
| const locationFromLinkedIn = profile.element.location.parsed?.text; | ||
| const locationFromLinkedIn = profile.location.parsed?.text; | ||
|
|
||
| if (!locationFromLinkedIn) { | ||
| return null; | ||
|
|
@@ -914,18 +913,18 @@ async function checkMember({ member, profile, trx }: CheckMemberInput) { | |
| return getMostRelevantLocation(locationFromLinkedIn, 'geocode'); | ||
| }); | ||
|
|
||
| if (!!profile.element.photo && !profile.element.openToWork) { | ||
| if (!!profile.photo && !profile.openToWork) { | ||
| await uploadProfilePicture({ | ||
| memberId: member.id, | ||
| pictureUrl: profile.element.photo, | ||
| pictureUrl: profile.photo, | ||
| }); | ||
| } | ||
|
|
||
| return trx | ||
| .updateTable('students') | ||
| .set({ | ||
| ...(!member.headline && { | ||
| headline: profile.element.headline, | ||
| headline: profile.headline, | ||
| }), | ||
| ...(!!updatedLocation && { | ||
| currentLocation: updatedLocation.formattedAddress, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Company lookup broken when using company names
High Severity
The
saveCompanyIfNecessaryfunction accepts both company names and LinkedIn IDs (as indicated by the parameter name and database query), but the new URL construction assumes the input is always a LinkedIn ID or slug. When called fromoffers.tswith human-readable company names like "Google" or "The Walt Disney Company", the constructed URLhttps://www.linkedin.com/company/${companyNameOrLinkedInId}will likely fail since company display names rarely match their LinkedIn universal names exactly. Additionally, company names with spaces aren't URL-encoded, creating malformed URLs. This breaks the offer creation flow for any company not already in the database.