From 5ff71b90e81475e173561035bb59c8a975d883c6 Mon Sep 17 00:00:00 2001 From: ION606 Date: Fri, 10 May 2024 17:11:13 -0700 Subject: [PATCH] added filtering for obfuscated 'LinkedIn Member' profiles in search --- classes/API.js | 16 +++++++++++----- src/types/index.d.ts | 3 ++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/classes/API.js b/classes/API.js index 33b80cb..7dbd1df 100644 --- a/classes/API.js +++ b/classes/API.js @@ -213,16 +213,16 @@ export default class linkedInAPIClass { * @param {String} keyword the user to search for * @param {Number?} [limit=1000] the function will find the bound the given number is contained in (see {@link findRangeIndex} for ranges) * @param {boolean?} [castToClass=true] whether the function should return a list of Company classes or just raw JSON + * @param {boolean} [filterObfuscated=true] where or not to filter out members with obfuscated profiles ("LinkedIn Member") * @param {Array?} currentCompanies * @param {Array<1 | 2 | 3>?} conDeg the level(s) of connection to include (defults to all) * @example * // search for "John Appleseed" (who works at github), but only the first 50 results who are also first connections * LAPI.searchEmployees("John Appleseed", 50, true, ["1418841"], [1]) */ - async searchEmployees(keyword, limit = 1000, castToClass = true, currentCompanies = [], conDeg = []) { + async searchEmployees(keyword, limit = 1000, castToClass = true, filterObfuscated = true, currentCompanies = [], conDeg = []) { const empAll = []; - for (let i = 0; i < limit; i += 50) { - if (empAll.length >= limit) break; + for (let i = 0; empAll.length < limit; i += 50) { let urlExt = `includeWebMetadata=true&variables=(start:${i},query:(keywords:${keyword},flagshipSearchIntent:SEARCH_SRP,queryParameters:List((key:resultType,value:List(PEOPLE))`; if (currentCompanies.length) urlExt += `,(key:currentCompany,value:List(${currentCompanies.join(',')}))`; @@ -230,9 +230,15 @@ export default class linkedInAPIClass { urlExt += ')))'; const r = await this._makeReq(urlExt); - if (!r?.included?.length) return []; - const filtered = r.included.filter(e => e.template === 'UNIVERSAL'); + // there's nothing left, returns what we have + if (!r?.included?.length) return empAll; + + // profiles with no info can be useless + const filtered = r.included.filter(e => { + if (!filterObfuscated) return e.template === 'UNIVERSAL'; + else return (e.template === 'UNIVERSAL' && e.title.text !== 'LinkedIn Member'); + }); if (filtered.length) empAll.push(...filtered); await this.evade(); diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 3aac53c..95c2d34 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -172,11 +172,12 @@ export default class linkedInAPIClass { * @param keyword The user to search for * @param limit Maximum number of results * @param castToClass Whether to cast the result to LinkedInProfile classes or return raw JSON + * @param filterObfuscated where or not to filter out members with obfuscated profiles ("LinkedIn Member") * @param currentCompanies Companies to filter by * @param conDeg Connection degrees to include * @returns Promise resolving to either an array of LinkedInProfile or raw JSON */ - searchEmployees(keyword: string, limit?: number, castToClass?: boolean, currentCompanies?: string[], conDeg?: Array<1 | 2 | 3>): Promise; + searchEmployees(keyword: string, limit?: number, castToClass?: boolean, filterObfuscated?: boolean, currentCompanies?: string[], conDeg?: Array<1 | 2 | 3>): Promise; /** * Makes a request to the LinkedIn API.