(function () { 'use strict'; // ==UserScript== // @name data extraction linkedin // @namespace Violentmonkey Scripts // @match https://www.linkedin.com/* // @grant GM_getValue // @grant GM_setValue // @grant GM_getValues // @grant GM_setValues // @grant GM_listValues // @grant GM_deleteValue // @grant GM_deleteValues // @grant GM_addStyle // @grant GM_addElement // @version 0.1 // @author Siarhei Siniak // @license Unlicense // @description 10/08/2024, 8:44:59 PM // @run-at document-body // @inject-into content // @require https://cdn.jsdelivr.net/npm/@violentmonkey/dom@1 // @require https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.min.js // @noframes // ==/UserScript== /* Use this extension to disalbe CSP for linkedin https://addons.mozilla.org/en-US/firefox/addon/header-editor/ https://github.com/FirefoxBar/HeaderEditor https://github.com/violentmonkey/violentmonkey/issues/1335 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src { "request": [], "sendHeader": [], "receiveHeader": [ { "enable": true, "name": "disable CSP for linkedin", "ruleType": "modifyReceiveHeader", "matchType": "domain", "pattern": "www.linkedin.com", "exclude": "", "group": "Ungrouped", "isFunction": false, "action": { "name": "content-security-policy", "value": "" } } ], "receiveBody": [] } */ class Linkedin { constructor() { this.data = new Map(); this.ui = { root: null, entries: null, search: null, state: null }; this.state = { search: '' }; } clean_page() { if (location.href.search('empty_body=true') != -1) { $('head').empty(); $('body').empty(); $('body').addClass('no-border'); } } async data_load() { let self = this; const keys = await GM_listValues(); let loaded = 0; for (let o of keys) { if (!o.startsWith('data-')) { return; } self.data.set(o.slice(5), await GM_getValue(o)); loaded += 1; } console.log({ action: 'loaded', total: loaded }); } string_reduce(text) { return text.replaceAll(/\s+/gi, ' ').trim(); } parse_header() { let self = this; return [$('.scaffold-finite-scroll__content > div > .relative .update-components-header').map((i, o) => ({ header: o.innerText })), $('.scaffold-finite-scroll__content > div > .relative .update-components-actor').map((i, o) => { let header = $(o); let teaser = $(o).parents('.relative').parent().find('.feed-shared-update-v2__description-wrapper'); return { header: self.string_reduce(header.text()), teaser: self.string_reduce(teaser.text()) }; })]; } async data_add(entry) { let self = this; if (self.data.has(entry.header)) { return false; } self.data.set(entry.header, { entry: entry, ts: new Date().valueOf() }); await GM_setValue('data-' + entry.header, self.data.get(entry.header)); console.log('saved ' + entry.header); console.log(self.data.get(entry.header)); return true; } async document_on_changed() { let self = this; let state_changed = false; if (JSON.stringify(self.state_get()) != JSON.stringify(self.state)) { state_changed = true; self.old_state = self.state; self.state = self.state_get(); } let current_data = self.parse_header(); let changed = false; for (let o of current_data[0]) { let current_changed = await self.data_add(o); if (current_changed) { changed = current_changed; } } for (let o of current_data[1]) { let current_changed = await self.data_add(o); if (current_changed) { changed = current_changed; } } if (changed || state_changed || self.ui.entries === null && self.data.size > 0) { self.display(); } } listener_add() { let self = this; return VM.observe(document.body, () => { self.document_on_changed(); }); } display_init() { let self = this; self.ui.root = $(`
`); $('head').append($('