LinkedIn Connect

Add "Auto Connect" button that automatically sends connection requests

  1. // ==UserScript==
  2. // @name LinkedIn Connect
  3. // @namespace http://tampermonkey.net/
  4. // @version 2025-02-27
  5. // @description Add "Auto Connect" button that automatically sends connection requests
  6. // @author Miguelx97
  7. // @match https://www.linkedin.com/mynetwork/grow/*
  8. // @icon data:image/jpeg;base64,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
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. "use strict";
  14.  
  15. /** Configuration constants and selectors */
  16. const CONFIG = {
  17. DEV_MODE: false,
  18. DELAY_SHORT: 200,
  19. DELAY_LONG: 2000,
  20. LIMIT_SCROLL: 8,
  21. LIMIT_CONNECTIONS: 16,
  22. MUTUAL_CONNECTION_THRESHOLD: 20,
  23. COLORS: {
  24. success: "#09ff00",
  25. danger: "#f2d8d8",
  26. },
  27. SELECTORS: {
  28. btnShowMore: '[data-view-name="cohort-section-see-all"]',
  29. scrollChild:
  30. '[data-sdui-screen="com.linkedin.sdui.flagshipnav.mynetwork.CohortSeeAll"]',
  31. listUsers:
  32. "div._1a8ay891.cnuthtbc.cnuthtj4._1a8ay893._1a8ay895._1a8ay89a.cnuthtew._1k2lxmew0._1k2lxmezs._1k2lxme13k._1k2lxme17c._139m7k23",
  33. userItem: "div.cnuthtaw",
  34. userContainer: '[role="listitem"]',
  35. mutualConnectionMsg:
  36. "p._12p2gmq9._12p2gmq2._12p2gmqi._29kmc32._29kmc33._29kmc38._29kmc3d._1lu65cq3._1lu65cq1._1xoe5hd3._1s9oaxgo._1ptbkx6c8._1s9oaxg5._1s9oaxgc._139m7k1fr._1s9oaxgn",
  37. btnConnect:
  38. "button.yyosfl1.h8e4ml0._1xoe5hd0._139m7k1gx._1s9oaxg7._1s9oaxgi.yyosfl4.yyosfl3.cnuthtc0.cnutht0.cnutht1i0._1k2lxmew._1ptbkx61go",
  39. topBar: "main ul.cnuthtb4.cnuthte8.cnuthth4.cnuththk",
  40. },
  41. };
  42.  
  43. /** Utility function for delaying execution */
  44. const delay = (ms) => new Promise((res) => setTimeout(res, ms));
  45.  
  46. /**
  47. * Waits for an element to appear in the DOM.
  48. * @param {string} selector - The CSS selector to wait for.
  49. * @param {HTMLElement} [container=document] - The container element.
  50. * @param {number} [timeout=10000] - Timeout in milliseconds.
  51. * @returns {Promise<HTMLElement>}
  52. */
  53. async function waitForElement(
  54. selector,
  55. container = document,
  56. timeout = 10000
  57. ) {
  58. const start = Date.now();
  59. return new Promise((resolve, reject) => {
  60. (function check() {
  61. const el = container.querySelector(selector);
  62. if (el) {
  63. return resolve(el);
  64. }
  65. if (Date.now() - start > timeout) {
  66. return reject(
  67. new Error(`Element ${selector} not found within timeout`)
  68. );
  69. }
  70. requestAnimationFrame(check);
  71. })();
  72. });
  73. }
  74.  
  75. /** Opens the "See all" connections modal */
  76. async function openConnectionsModal() {
  77. const btnShowMore = await waitForElement(CONFIG.SELECTORS.btnShowMore);
  78. btnShowMore.click();
  79. }
  80.  
  81. /** Scrolls the modal to load more user items and inserts a counter UI */
  82. async function scrollToLoadUsers() {
  83. const scrollChildEl = await waitForElement(CONFIG.SELECTORS.scrollChild);
  84. // Insert connection counter UI
  85. scrollChildEl.insertAdjacentHTML(
  86. "afterbegin",
  87. `<p style="text-align: center; font-size: 14px; margin: 4px;">
  88. Connection Requests: <span id="connectionRequests">0</span><span id="finishMsg"></span>
  89. </p>`
  90. );
  91. const scrollContainer = scrollChildEl.parentElement;
  92. const limitScroll = CONFIG.DEV_MODE ? 2 : CONFIG.LIMIT_SCROLL;
  93. for (let i = 0; i < limitScroll; i++) {
  94. if (i > 0) await delay(CONFIG.DELAY_LONG);
  95. scrollContainer.scrollTo({
  96. top: scrollContainer.scrollHeight,
  97. behavior: "smooth",
  98. });
  99. }
  100. // Scroll back to the top
  101. scrollContainer.scrollTo({ top: 0, behavior: "smooth" });
  102. return scrollChildEl;
  103. }
  104.  
  105. /** Processes the list of users, marking those that meet the criteria and triggering connection */
  106. async function processConnections(scrollChildEl) {
  107. const listUsersElement = scrollChildEl.querySelector(
  108. CONFIG.SELECTORS.listUsers
  109. );
  110. if (!listUsersElement) {
  111. throw new Error("List users element not found");
  112. }
  113. const users = listUsersElement.querySelectorAll(CONFIG.SELECTORS.userItem);
  114. let connectionsCount = 0;
  115. for (const userEl of users) {
  116. const container = userEl.querySelector(CONFIG.SELECTORS.userContainer);
  117. if (!container) continue;
  118.  
  119. const msgEl = container.querySelector(
  120. CONFIG.SELECTORS.mutualConnectionMsg
  121. );
  122. if (!msgEl) continue;
  123.  
  124. const regex = /and\s+(\d+)\s+other mutual connection(?:s)?/;
  125. const match = msgEl.textContent.match(regex);
  126. const numMutualConnections = match ? parseInt(match[1], 10) : 0;
  127.  
  128. // Determine the styling based on the number of mutual connections
  129. const { success, danger } = CONFIG.COLORS;
  130. let color = danger;
  131. let border = 2;
  132. const wannaConnect =
  133. numMutualConnections > CONFIG.MUTUAL_CONNECTION_THRESHOLD;
  134. if (wannaConnect) {
  135. color = success;
  136. border = Math.min(
  137. (numMutualConnections / CONFIG.MUTUAL_CONNECTION_THRESHOLD) * 2,
  138. 6
  139. );
  140. }
  141. container.style.border = `solid ${border}px ${color}`;
  142. await delay(CONFIG.DELAY_SHORT);
  143.  
  144. // If the criteria are met, click the Connect button
  145. if (wannaConnect) {
  146. const btnConnect = container.querySelector(CONFIG.SELECTORS.btnConnect);
  147. if (!btnConnect) continue;
  148. if (connectionsCount < CONFIG.LIMIT_CONNECTIONS && !CONFIG.DEV_MODE) {
  149. btnConnect.click();
  150. connectionsCount++;
  151. scrollChildEl.querySelector("#connectionRequests").textContent =
  152. connectionsCount;
  153. }
  154. }
  155. }
  156. scrollChildEl.querySelector("#finishMsg").textContent = " · Finished!";
  157. }
  158.  
  159. /** Main auto-connect function that coordinates the process */
  160. async function startAutoConnect() {
  161. try {
  162. await openConnectionsModal();
  163. const scrollChildEl = await scrollToLoadUsers();
  164. await processConnections(scrollChildEl);
  165. } catch (error) {
  166. console.error("Error in auto connect:", error);
  167. }
  168. }
  169.  
  170. /** Inserts the "Auto Connect" button into the page's top bar */
  171. async function addAutoConnectButton() {
  172. const topBar = await waitForElement(CONFIG.SELECTORS.topBar);
  173. if (!topBar) return;
  174. await delay(CONFIG.DELAY_SHORT);
  175. topBar.insertAdjacentHTML(
  176. "beforeend",
  177. `<li style="margin-left:auto;">
  178. <a id="auto-connect" class="minvu03 cnutht0 _139m7k7f h8e4ml0 _1xoe5hd0 _139m7k19r _139m7k1a1 _139m7k19w _1mamebb1 cnuthtb4 cnutht1i0 _1s9oaxgi _1pylls4i _1pylls4m _1ptbkx61fc minvu04 _1k2lxme13k _1k2lxme17c _1k2lxmevk _1k2lxmezc cnuthtig cnutht180">
  179. <span class="_12p2gmq9 _1s9oaxg7 _12p2gmqk _29kmc3a _29kmc3b _29kmc3g _29kmc3l _1s9oaxg6 _139m7k1gx _1s9oaxgn" style="color:#0a66c2;">Auto Connect</span>
  180. </span>
  181. </a>
  182. </li>`
  183. );
  184. const btnAutoConnect = await waitForElement("#auto-connect");
  185. btnAutoConnect.addEventListener("click", startAutoConnect);
  186. }
  187.  
  188. addAutoConnectButton();
  189. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址