linkedin-private-api
Advanced tools
Comparing version 1.0.5 to 1.1.0
@@ -1,5 +0,5 @@ | ||
import { LinkedInSearchHit } from './linkedin-search-hit.entity'; | ||
import { LinkedInSearchHitV2 } from './linkedin-search-hit-v2.entity'; | ||
import { MiniCompany } from './mini-company.entity'; | ||
export interface CompanySearchHit extends LinkedInSearchHit { | ||
export interface CompanySearchHit extends LinkedInSearchHitV2 { | ||
company: MiniCompany; | ||
} |
@@ -20,3 +20,3 @@ export * from './company-search-hit.entity'; | ||
export * from './linkedin-search-cluster.entity'; | ||
export * from './linkedin-search-hit.entity'; | ||
export * from './linkedin-search-hit-v2.entity'; | ||
export * from './linkedin-text-view-model.entity'; | ||
@@ -30,1 +30,3 @@ export * from './linkedin-vector-artifact.entity'; | ||
export * from './profile.entity'; | ||
export * from './linkedin-base-company'; | ||
export * from './linkedin-job-posting'; |
@@ -32,3 +32,3 @@ "use strict"; | ||
__exportStar(require("./linkedin-search-cluster.entity"), exports); | ||
__exportStar(require("./linkedin-search-hit.entity"), exports); | ||
__exportStar(require("./linkedin-search-hit-v2.entity"), exports); | ||
__exportStar(require("./linkedin-text-view-model.entity"), exports); | ||
@@ -42,2 +42,4 @@ __exportStar(require("./linkedin-vector-artifact.entity"), exports); | ||
__exportStar(require("./profile.entity"), exports); | ||
__exportStar(require("./linkedin-base-company"), exports); | ||
__exportStar(require("./linkedin-job-posting"), exports); | ||
//# sourceMappingURL=index.js.map |
import { SearchResultType } from '../types/search-result-type.enum'; | ||
import { LinkedInSearchHit } from './linkedin-search-hit.entity'; | ||
import { LinkedInSearchHitV2 } from './linkedin-search-hit-v2.entity'; | ||
export interface LinkedInSearchCluster { | ||
$type: 'com.linkedin.voyager.search.BlendedSearchCluster'; | ||
elements: LinkedInSearchHit[]; | ||
elements: LinkedInSearchHitV2[]; | ||
type: SearchResultType; | ||
} |
@@ -1,5 +0,5 @@ | ||
import { LinkedInSearchHit } from './linkedin-search-hit.entity'; | ||
import { LinkedInSearchHitV2 } from './linkedin-search-hit-v2.entity'; | ||
import { MiniProfile } from './mini-profile.entity'; | ||
export interface PeopleSearchHit extends LinkedInSearchHit { | ||
export interface PeopleSearchHit extends LinkedInSearchHitV2 { | ||
profile: MiniProfile; | ||
} |
@@ -8,12 +8,8 @@ "use strict"; | ||
const linkedin_profile_entity_1 = require("../entities/linkedin-profile.entity"); | ||
const getProfilePictureUrls = (picture) => { | ||
return lodash_1.map(picture === null || picture === void 0 ? void 0 : picture.artifacts, artifact => `${picture === null || picture === void 0 ? void 0 : picture.rootUrl}${artifact.fileIdentifyingUrlPathSegment}`); | ||
}; | ||
const transformMiniProfile = (miniProfile) => { | ||
return { | ||
...miniProfile, | ||
pictureUrls: getProfilePictureUrls(miniProfile.picture), | ||
profileId: (miniProfile.entityUrn || '').replace('urn:li:fs_miniProfile:', ''), | ||
}; | ||
}; | ||
const getProfilePictureUrls = (picture) => lodash_1.map(picture === null || picture === void 0 ? void 0 : picture.artifacts, artifact => `${picture === null || picture === void 0 ? void 0 : picture.rootUrl}${artifact.fileIdentifyingUrlPathSegment}`); | ||
const transformMiniProfile = (miniProfile) => ({ | ||
...miniProfile, | ||
pictureUrls: getProfilePictureUrls(miniProfile.picture), | ||
profileId: (miniProfile.entityUrn || '').replace('urn:li:fs_miniProfile:', ''), | ||
}); | ||
const getProfilesFromResponse = (response) => { | ||
@@ -20,0 +16,0 @@ const miniProfiles = lodash_1.filter(response.included, p => p.$type === linkedin_mini_profile_entity_1.MINI_PROFILE_TYPE); |
@@ -5,3 +5,5 @@ import { Client } from '../core/client'; | ||
import { PeopleSearchScroller } from '../scrollers/people-search.scroller'; | ||
import { JobSearchScroller } from '../scrollers/job-search.scroller'; | ||
import { PeopleSearchFilters } from '../types/people-search-filters'; | ||
import { JobSearchFilters } from '../types/job-search-filters'; | ||
export declare class SearchRepository { | ||
@@ -36,4 +38,11 @@ client: Client; | ||
}): PeopleSearchScroller; | ||
searchJobs({ skip, limit, filters, keywords, }?: { | ||
skip?: number; | ||
limit?: number; | ||
filters?: JobSearchFilters; | ||
keywords?: string; | ||
}): JobSearchScroller; | ||
private fetchPeople; | ||
private fetchCompanies; | ||
private fetchJobs; | ||
} |
@@ -8,2 +8,3 @@ "use strict"; | ||
const people_search_scroller_1 = require("../scrollers/people-search.scroller"); | ||
const job_search_scroller_1 = require("../scrollers/job-search.scroller"); | ||
const network_enum_1 = require("../types/network.enum"); | ||
@@ -13,2 +14,4 @@ const search_result_type_enum_1 = require("../types/search-result-type.enum"); | ||
const profile_repository_1 = require("./profile.repository"); | ||
const linkedin_job_posting_1 = require("../entities/linkedin-job-posting"); | ||
const linkedin_base_company_1 = require("../entities/linkedin-base-company"); | ||
class SearchRepository { | ||
@@ -53,2 +56,11 @@ constructor({ client }) { | ||
} | ||
searchJobs({ skip = 0, limit = 10, filters = {}, keywords, } = {}) { | ||
return new job_search_scroller_1.JobSearchScroller({ | ||
skip, | ||
limit, | ||
filters, | ||
keywords, | ||
fetchJobs: this.fetchJobs.bind(this), | ||
}); | ||
} | ||
async fetchPeople({ skip = 0, limit = 10, filters = {}, keywords, } = {}) { | ||
@@ -88,4 +100,33 @@ const response = await this.client.request.search.searchBlended({ | ||
} | ||
async fetchJobs({ skip = 0, limit = 10, filters = {}, keywords, } = {}) { | ||
var _a, _b, _c; | ||
const response = await this.client.request.search.searchJobs({ | ||
filters, | ||
keywords, | ||
skip, | ||
limit, | ||
}); | ||
const jobPostings = (_a = response === null || response === void 0 ? void 0 : response.included) === null || _a === void 0 ? void 0 : _a.filter(element => element.$type === linkedin_job_posting_1.JOB_POSTING_TYPE); | ||
const companies = (_b = response === null || response === void 0 ? void 0 : response.included) === null || _b === void 0 ? void 0 : _b.filter(element => element.$type === linkedin_base_company_1.BASE_COMPANY_TYPE); | ||
const keyedPostings = lodash_1.keyBy(jobPostings, 'entityUrn'); | ||
const keyedCompanies = lodash_1.keyBy(companies, 'entityUrn'); | ||
const searchHits = (_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.elements.map(searchHit => { | ||
const jobPosting = keyedPostings[searchHit.hitInfo.jobPosting]; | ||
const company = keyedCompanies[jobPosting.companyDetails.company]; | ||
const populatedPosting = { | ||
...jobPosting, | ||
companyDetails: { ...jobPosting.companyDetails, company }, | ||
}; | ||
return { | ||
...searchHit, | ||
hitInfo: { | ||
...searchHit.hitInfo, | ||
jobPosting: populatedPosting, | ||
}, | ||
}; | ||
}); | ||
return searchHits; | ||
} | ||
} | ||
exports.SearchRepository = SearchRepository; | ||
//# sourceMappingURL=search.repository.js.map |
@@ -0,1 +1,3 @@ | ||
import { GetJobSearchResponse } from '../responses/jobs-search.reponse.get'; | ||
import { JobSearchFilters } from '../types/job-search-filters'; | ||
import { LinkedInRequest } from '../core/linkedin-request'; | ||
@@ -15,2 +17,8 @@ import { GetBlendedSearchResponse } from '../responses/blended-search.reponse.get'; | ||
}): Promise<GetBlendedSearchResponse>; | ||
searchJobs({ skip, limit, filters, keywords, }: { | ||
skip?: number; | ||
limit?: number; | ||
filters?: JobSearchFilters; | ||
keywords?: string; | ||
}): Promise<GetJobSearchResponse>; | ||
} |
@@ -25,4 +25,22 @@ "use strict"; | ||
} | ||
searchJobs({ skip = 0, limit = 10, filters = {}, keywords, }) { | ||
const queryParams = { | ||
filters, | ||
count: limit, | ||
...(keywords ? { keywords: encodeURIComponent(keywords) } : {}), | ||
origin: 'JOB_SEARCH_RESULTS_PAGE', | ||
decorationId: 'com.linkedin.voyager.deco.jserp.WebJobSearchHitLite-14', | ||
q: 'jserpFilters', | ||
queryContext: { | ||
primaryHitType: 'JOBS', | ||
spellCorrectionEnabled: true, | ||
}, | ||
start: skip, | ||
}; | ||
return this.request.get('search/hits', { | ||
params: queryParams, | ||
}); | ||
} | ||
} | ||
exports.SearchRequest = SearchRequest; | ||
//# sourceMappingURL=search.request.js.map |
@@ -5,1 +5,2 @@ export * from './conversation.scroller'; | ||
export * from './people-search.scroller'; | ||
export * from './job-search.scroller'; |
@@ -17,2 +17,3 @@ "use strict"; | ||
__exportStar(require("./people-search.scroller"), exports); | ||
__exportStar(require("./job-search.scroller"), exports); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "linkedin-private-api", | ||
"version": "1.0.5", | ||
"version": "1.1.0", | ||
"description": "", | ||
@@ -9,2 +9,9 @@ "main": "dist/index.js", | ||
"license": "MIT", | ||
"keywords": [ | ||
"linkedin-nodejs-api", | ||
"linkedin-api", | ||
"linked-private-api", | ||
"linked-unofficial-api", | ||
"linkedin-web-api" | ||
], | ||
"engines": { | ||
@@ -45,3 +52,3 @@ "node": ">=14.0.0" | ||
"devDependencies": { | ||
"@types/config": "^0.0.38", | ||
"@types/config": "^0.0.39", | ||
"@types/cookie": "^0.4.0", | ||
@@ -51,3 +58,3 @@ "@types/faker": "^5.1.2", | ||
"@types/lodash": "^4.14.161", | ||
"@types/node": "^15.12.4", | ||
"@types/node": "^16.0.0", | ||
"@typescript-eslint/eslint-plugin": "^4.2.0", | ||
@@ -65,3 +72,3 @@ "@typescript-eslint/parser": "^4.2.0", | ||
"faker": "^5.1.0", | ||
"husky": "^4.3.0", | ||
"husky": "^7.0.0", | ||
"intermock": "^0.2.2", | ||
@@ -68,0 +75,0 @@ "jest": "^26.4.2", |
@@ -1,5 +0,5 @@ | ||
# NodeJS LinkedIn Private API | ||
# NodeJS LinkedIn API | ||
![Build](https://github.com/eilonmore/linkedin-private-api/workflows/Build/badge.svg?branch=master) | ||
Wrapper API for LinkedIn unofficial API, written in TypeScript. | ||
NodeJS Wrapper API for LinkedIn API, written in TypeScript. | ||
No tokens are needed for using this API, only a working LinkedIn account. | ||
@@ -27,12 +27,20 @@ | ||
// search for companies | ||
const companiesScroller = await client.search.searchCompanies({ keywords: 'Microsoft' }); | ||
const [{ company: microsoft }] = await companiesScroller.scrollNext(); | ||
// Search for React development jobs in Israel | ||
const jobsScroller = await client.search.searchJobs({ | ||
keywords: 'React', | ||
filters: { location: 'Israel' }, | ||
limit: 20, | ||
skip: 5, | ||
}); | ||
const [someReactJobHit] = await jobsScroller.scrollNext(); | ||
const jobCompanyName = someReactJobHit.hitInfo.jobPosting.companyDetails.company.name; | ||
// Fetch the job's company | ||
const companiesScroller = await client.search.searchCompanies({ keywords: jobCompanyName }); | ||
const [{ company: jobCompany }] = await companiesScroller.scrollNext(); | ||
// Search for profiles and send an invitation | ||
const peopleScroller = await client.search.searchPeople({ | ||
keywords: 'Bill Gates', | ||
filters: { | ||
pastCompany: microsoft.companyId | ||
} | ||
keywords: 'Bill Gates' | ||
}); | ||
@@ -109,2 +117,3 @@ const [{ profile: billGates }] = await peopleScroller.scrollNext(); | ||
|[PeopleSearchHit](https://github.com/eilonmore/linkedin-private-api/blob/master/docs/interfaces/_src_entities_people_search_hit_entity_.peoplesearchhit.md)| | ||
|[JobSearchHit](https://github.com/eilonmore/linkedin-private-api/blob/master/docs/modules/_src_entities_job_search_hit_entity_.md)| | ||
|[MessageCreateResponse](https://github.com/eilonmore/linkedin-private-api/blob/master/docs/interfaces/_src_entities_message_create_response_entity_.messageeventcreateresponse.md)| | ||
@@ -156,3 +165,2 @@ | ||
* Invitation improvements - be able to do some more actions like "remove connection". | ||
* Search improvements - support jobs searching. | ||
* Improve login API | ||
@@ -159,0 +167,0 @@ * Add services so automate common workflows |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
538935
344
6061
175
11