This code automates LinkedIn interactions by retrieving a list of connections and sending connection requests to specified profiles.
npm run import -- "connect on linkedin"
var importer = require('../Core');
var fs = require('fs');
var PROFILE_PATH = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
var project = PROFILE_PATH + '/Collections/conversations';
function listAllConnections(list) {
var friends = [];
// TODO: create utility function for managing time critical files like this.
if (fs.existsSync(project + '/new-connections.json')) {
return Promise.resolve(JSON.parse(
fs.readFileSync(project + '/new-connections.json')));
}
return client
.getUrl()
.then(url => {
if(list && list.includes('linkedin.com')) {
return client
.url(list)
.pause(3000);
}
return client
.url('https://www.linkedin.com/mynetwork/')
.pause(3000);
})
.then(() => getAllUntil(
false,
'//a[contains(@href, "/in/")]/@href',
friends,
(a, b) => a === b,
(i) => i < 10
))
.then(r => r.filter((l, i, arr) => arr.indexOf(l) === i))
.then(r => {
fs.writeFileSync(
project + '/new-connections.json',
JSON.stringify(r, null, 4));
return r;
})
.catch(e => console.log(e))
};
function connectLinkedin(profile) {
return client
.then(() => clickSpa('https://linkedin.com' + profile))
.pause(3000)
.isExisting('//button[contains(., "Connect")]')
.then(is => {
console.log(is + ' - ' + profile);
return is
? client
.isVisible('//button[contains(., "Connect")]')
.then(is => is
? client
.click('//button[contains(., "Connect")]')
.pause(1000)
: [])
: client
.isExisting('//button[contains(., "More")]')
.then(is => is ? client.click('//button[contains(., "More")]').pause(500) : [])
.isVisible('//button[contains(., "Connect")][not(contains(., "Remove"))]')
.then(is => is
? client
.click('//button[contains(., "Connect")][not(contains(., "Remove"))]')
.pause(1000)
: [])
})
.isExisting('//button[contains(., "Send now")]')
.then(is => is
? client
.isVisible('//button[contains(., "Send now")]')
.then(is => is
? client
.click('//button[contains(., "Send now")]')
.pause(2000)
: [])
: [])
.pause(1000)
.catch(e => console.log(e))
}
module.exports = {
listAllConnections,
connectLinkedin
};
const fs = require('fs');
const client = require('../Core');
const PROFILE_PATH = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
const project = `${PROFILE_PATH}/Collections/conversations`;
const NEW_CONNECTIONS_FILE = `${project}/new-connections.json`;
class ConnectionManager {
async listAllConnections(list) {
if (fs.existsSync(NEW_CONNECTIONS_FILE)) {
try {
return JSON.parse(fs.readFileSync(NEW_CONNECTIONS_FILE));
} catch (error) {
console.error('Error reading new connections file:', error);
}
}
try {
const url = await client.getUrl();
if (list && list.includes('linkedin.com')) {
await client.url(list).pause(3000);
} else {
await client.url('https://www.linkedin.com/mynetwork/').pause(3000);
}
const friends = await this.getAllUntil(false, '//a[contains(@href, "/in/")]/@href', []);
const uniqueFriends = [...new Set(friends)];
fs.writeFileSync(NEW_CONNECTIONS_FILE, JSON.stringify(uniqueFriends, null, 4));
return uniqueFriends;
} catch (error) {
console.error('Error listing connections:', error);
}
}
async getAllUntil(isAsync, selector, result, equality, condition) {
try {
const element = await client.isVisible(selector);
if (element) {
const elements = await client.getElements(selector);
result = result.concat(elements.map((element) => element.getAttribute('href')));
if (equality(result[result.length - 1], result[result.length - 2])) {
return result;
}
if (condition(result.length)) {
return result;
}
return this.getAllUntil(isAsync, selector, result, equality, condition);
}
} catch (error) {
console.error('Error getting elements:', error);
}
}
async connectLinkedin(profile) {
try {
await client.clickSpa(`https://linkedin.com${profile}`).pause(3000);
const connectButton = await client.isVisible('//button[contains(., "Connect")]');
if (connectButton) {
await client.click('//button[contains(., "Connect")]').pause(1000);
} else {
const moreButton = await client.isVisible('//button[contains(., "More")]');
if (moreButton) {
await client.click('//button[contains(., "More")]').pause(500);
const connectButton = await client.isVisible('//button[contains(., "Connect")][not(contains(., "Remove"))]');
if (connectButton) {
await client.click('//button[contains(., "Connect")][not(contains(., "Remove"))]').pause(1000);
}
}
}
const sendNowButton = await client.isVisible('//button[contains(., "Send now")]');
if (sendNowButton) {
await client.click('//button[contains(., "Send now")]').pause(2000);
}
return true;
} catch (error) {
console.error('Error connecting to LinkedIn:', error);
return false;
}
}
}
module.exports = new ConnectionManager();
This code snippet defines two functions, listAllConnections
and connectLinkedin
, that automate interactions with LinkedIn, specifically focusing on retrieving a list of connections and sending connection requests.
Here's a breakdown:
listAllConnections
Function:
new-connections.json
exists in a specified directory (project
). If it does, it reads the JSON data from the file and returns it as a promise.client
(presumably a web automation client) to navigate to the LinkedIn "My Network" page or a specified URL if provided.getAllUntil
(not shown in the provided code) to extract LinkedIn profile URLs from the page.new-connections.json
before being returned.connectLinkedin
Function:
client
to navigate to the specified profile.Purpose:
This code provides a way to programmatically scrape LinkedIn for a list of connections and send connection requests to specific profiles.