├── LICENSE ├── README.md ├── demo └── demo.gif └── linkedin_connect.js /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Mario 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![No Maintenance Intended](http://unmaintained.tech/badge.svg)](https://github.com/mariiio) 2 | 3 | # LinkedIn Connect 4 | 5 | LinkedIn Connect is a configurable and easy to use JavaScript script to automate connections with personalized messages. 6 | 7 | ![LinkedIn Connect Demo](demo/demo.gif) 8 | ## Prerequisites 9 | 10 | Make sure your _LinkedIn_ is in English 11 | 12 | ## Usage 13 | 1. Go to the _People_ section of the company you're interested in (https://www.linkedin.com/company/{COMPANY_NAME}/people/) 14 | 2. Modify the constants at the top of [linkedin_connect.js](https://raw.githubusercontent.com/mariiio/linkedin_connect/master/linkedin_connect.js) to your liking 15 | 16 | | Constant| Description | 17 | | --- | --- | 18 | | `MAX_CONNECTIONS` | Maximum amount of connection requests | 19 | | `WAIT_TO_CONNECT` | Time in ms to wait before requesting to connect | 20 | | `WAIT_AFTER_SCROLL` | Time in ms to wait before new employees load after scroll | 21 | | `MESSAGE` | Message to connect (`%EMPLOYEE%` and `%COMPANY%` will be replaced with real values, 300 characters max.) | 22 | | `POSITION_KEYWORDS` | Keywords to filter employees in specific positions | 23 | 24 | 3. Run it in the chrome dev tools [console](https://developers.google.com/web/tools/chrome-devtools/open#console) (or add it as a [snippet](https://developers.google.com/web/tools/chrome-devtools/javascript/snippets#create)) 25 | 26 | ## License 27 | [MIT](https://choosealicense.com/licenses/mit/) 28 | 29 | ## Disclaimer 30 | The code within this repository comes with no guarantee, the use of this code is your responsibility. 31 | Use at your own risk. 32 | -------------------------------------------------------------------------------- /demo/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mariiio/linkedin_connect/2b9854ca1615b5c9280038d1f01b125b25d97715/demo/demo.gif -------------------------------------------------------------------------------- /linkedin_connect.js: -------------------------------------------------------------------------------- 1 | // 1. Go to https://www.linkedin.com/company/{COMPANY_NAME}/people/ 2 | // 2. Make sure your LinkedIn is in English 3 | // 3. Modify the constants to your liking 4 | // 4. Open chrome dev tools and paste this script or add it as a snippet 5 | 6 | (async () => { 7 | // maximum amount of connection requests 8 | const MAX_CONNECTIONS = 10; 9 | // time in ms to wait before requesting to connect 10 | const WAIT_TO_CONNECT = 2000; 11 | // time in ms to wait before new employees load after scroll 12 | const WAIT_AFTER_SCROLL = 3000; 13 | // message to connect (%EMPLOYEE% and %COMPANY% will be replaced with real values) 14 | const MESSAGE = `Hi %EMPLOYEE%, I'm a Software Engineer with 4 yrs of experience in full-stack web development. 15 | I see you're currently working at %COMPANY% where I saw a Full Stack job post and was interested to hear more about it. 16 | Would you (or a colleague) have time to chat about the position? 17 | Thanks! Mario`; 18 | // keywords to filter employees in specific positions 19 | const POSITION_KEYWORDS = [ 20 | "software", 21 | "developer", 22 | "full stack", 23 | "back end", 24 | "front end", 25 | "r&d", 26 | ]; 27 | 28 | // <--> // 29 | 30 | const MESSAGE_CHAR_LIMIT = 300; 31 | 32 | function buildMessage(employee) { 33 | const company = document.getElementsByClassName( 34 | "org-top-card-summary__title" 35 | )[0].title; 36 | 37 | const replacements = { "%COMPANY%": company, "%EMPLOYEE%": employee }; 38 | const message = MESSAGE.replace(/%\w+%/g, (i) => { 39 | return replacements[i]; 40 | }); 41 | 42 | return message.length <= MESSAGE_CHAR_LIMIT ? message : ""; 43 | } 44 | 45 | function getButtonElements() { 46 | return [ 47 | ...document.querySelectorAll( 48 | 'button[data-control-name="people_profile_card_connect_button"]' 49 | ), 50 | ].filter((button) => { 51 | const cardInnerText = button.offsetParent.innerText.split("\n"); 52 | const positionIndex = cardInnerText.length > 3 ? 3 : 1; 53 | const position = cardInnerText[positionIndex]; 54 | return POSITION_KEYWORDS.some((p) => position.match(new RegExp(p, "gi"))); 55 | }); 56 | } 57 | 58 | function fillMessageAndConnect() { 59 | const employee = document 60 | .getElementById("send-invite-modal") 61 | .innerText.split(" ")[1]; 62 | document.getElementById("custom-message").value = buildMessage(employee); 63 | document 64 | .getElementById("artdeco-modal-outlet") 65 | .getElementsByTagName("button")[2] 66 | .click(); 67 | console.log(`🤝 Requested connection to ${employee}`); 68 | } 69 | 70 | async function connect(button) { 71 | return new Promise((resolve) => { 72 | setTimeout(() => { 73 | button.click(); 74 | fillMessageAndConnect(); 75 | resolve(); 76 | }, WAIT_TO_CONNECT); 77 | }); 78 | } 79 | 80 | async function* getConnectButtons() { 81 | while ((buttons = getButtonElements()).length > 0) { 82 | yield* buttons; 83 | await loadMoreButtons(); 84 | } 85 | } 86 | 87 | async function loadMoreButtons() { 88 | console.log("⏬ Scrolling.."); 89 | await Promise.resolve(window.scrollTo(0, document.body.scrollHeight)); 90 | return new Promise((resolve) => setTimeout(resolve, WAIT_AFTER_SCROLL)); 91 | } 92 | 93 | // <--> // 94 | 95 | console.log("⏳ Started connecting, please wait."); 96 | try { 97 | var connections = 0; 98 | const buttonsGenerator = getConnectButtons(); 99 | while ( 100 | connections < MAX_CONNECTIONS && 101 | !(next = await buttonsGenerator.next()).done 102 | ) { 103 | const button = next.value; 104 | await connect(button); 105 | connections++; 106 | } 107 | console.log( 108 | `✅ Done! Successfully requested connection to ${connections} people.` 109 | ); 110 | } catch { 111 | console.log( 112 | `⛔ Whoops, looks like something went wrong. 113 | Please go to https://github.com/mariiio/linkedin_connect and follow the instructions.` 114 | ); 115 | } 116 | })(); 117 | --------------------------------------------------------------------------------